diff --git a/README.md b/README.md index 0f0afa5c..ec14beea 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ npm install @jamesives/github-pages-deploy-action It can then be imported into your project like so. ```javascript -import run, {ActionInterface} from "github-pages-deploy-action"; +import run from "github-pages-deploy-action"; ``` Calling the functions directly will require you to pass in an object containing the variables found in the configuration section, you'll also need to provide a `workspace` with a path to your project. @@ -109,11 +109,12 @@ run({ branch: "gh-pages", folder: "build", repositoryName: "JamesIves/github-pages-deploy-action", + silent: true, workspace: "src/project/location", }); ``` -For more information regarding the [action interface please click here](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/src/constants.ts#L7). +For more information regarding the [action interface please click here](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/src/constants.ts#L7). ## Configuration πŸ“ @@ -335,8 +336,4 @@ If you'd like to enable action debugging you can set the `ACTIONS_STEP_DEBUG` en This project would not be possible without all of our fantastic [contributors](https://github.com/JamesIves/github-pages-deploy-action/graphs/contributors). - - - - If you'd like to support the maintenance and upkeep of this project you can [donate via GitHub Sponsors](https://github.com/sponsors/JamesIves). This project is distributed under the [MIT](https://github.com/JamesIves/github-pages-deploy-action/blob/dev/LICENSE) license. \ No newline at end of file diff --git a/__tests__/git.test.ts b/__tests__/git.test.ts index 1ef54c6d..0ccb78bf 100644 --- a/__tests__/git.test.ts +++ b/__tests__/git.test.ts @@ -23,7 +23,8 @@ jest.mock('@actions/io', () => ({ })) jest.mock('../src/execute', () => ({ - execute: jest.fn() + __esModule: true, + execute: jest.fn(), })) describe('git', () => { @@ -50,6 +51,33 @@ describe('git', () => { await init(action) expect(execute).toBeCalledTimes(7) }) + + it('should catch when a function throws an error', async () => { + + (execute as jest.Mock).mockImplementationOnce(() => { + throw new Error('Mocked throw'); + }); + + Object.assign(action, { + silent: false, + repositoryPath: 'JamesIves/github-pages-deploy-action', + accessToken: '123', + branch: 'branch', + folder: '.', + preserve: true, + isTest: true, + pusher: { + name: 'asd', + email: 'as@cat' + } + }) + + try { + await init(action) + } catch (error) { + expect(error.message).toBe('There was an error initializing the repository: Mocked throw ❌'); + } + }) }) describe('generateBranch', () => { @@ -68,6 +96,30 @@ describe('git', () => { await generateBranch(action) expect(execute).toBeCalledTimes(6) }) + + it('should catch when a function throws an error', async () => { + + (execute as jest.Mock).mockImplementationOnce(() => { + throw new Error('Mocked throw'); + }); + + Object.assign(action, { + silent: false, + accessToken: '123', + branch: 'branch', + folder: '.', + pusher: { + name: 'asd', + email: 'as@cat' + } + }) + + try { + await generateBranch(action) + } catch (error) { + expect(error.message).toBe('There was an error creating the deployment branch: There was an error switching to the base branch: Mocked throw ❌ ❌'); + } + }) }) describe('switchToBaseBranch', () => { @@ -103,6 +155,32 @@ describe('git', () => { await switchToBaseBranch(action) expect(execute).toBeCalledTimes(1) }) + + + it('should catch when a function throws an error', async () => { + + (execute as jest.Mock).mockImplementationOnce(() => { + throw new Error('Mocked throw'); + }); + + Object.assign(action, { + silent: false, + baseBranch: '123', + accessToken: '123', + branch: 'branch', + folder: '.', + pusher: { + name: 'asd', + email: 'as@cat' + } + }) + + try { + await switchToBaseBranch(action) + } catch (error) { + expect(error.message).toBe('There was an error switching to the base branch: Mocked throw ❌'); + } + }) }) describe('deploy', () => { @@ -276,5 +354,30 @@ describe('git', () => { expect(rmRF).toBeCalledTimes(1) expect(response).toBe(Status.SKIPPED) }) + + it('should catch when a function throws an error', async () => { + + (execute as jest.Mock).mockImplementationOnce(() => { + throw new Error('Mocked throw'); + }); + + Object.assign(action, { + silent: false, + folder: 'assets', + branch: 'branch', + gitHubToken: '123', + lfs: true, + pusher: { + name: 'asd', + email: 'as@cat' + } + }) + + try { + await deploy(action) + } catch (error) { + expect(error.message).toBe('The deploy step encountered an error: Mocked throw ❌'); + } + }) }) }) diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 0437586b..1f21cf39 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -321,7 +321,7 @@ describe('util', () => { checkParameters(action) } catch (e) { expect(e.message).toMatch( - `The ${action.folderPath} directory you're trying to deploy doesn't exist.` + `The directory you're trying to deploy named notARealFolder doesn't exist. Please double check the path and any prerequisite build scripts and try again. ❗` ) } }) diff --git a/src/constants.ts b/src/constants.ts index 8c56f2a9..44843445 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -24,6 +24,7 @@ export interface ActionInterface { email?: string /** The folder to deploy. */ folder: string + /** The auto generated folder path. */ folderPath?: string /** GitHub deployment token. */ gitHubToken?: string | null @@ -53,6 +54,26 @@ export interface ActionInterface { workspace: string } +/** The minimum required values to run the action as a node module. */ +export interface NodeActionInterface { + /** Deployment access token. */ + accessToken?: string | null + /** The branch that the action should deploy to. */ + branch: string + /** The folder to deploy. */ + folder: string + /** GitHub deployment token. */ + gitHubToken?: string | null + /** The repository path, for example JamesIves/github-pages-deploy-action. */ + repositoryName: string + /** Determines if the action should run in silent mode or not. */ + silent: boolean + /** Set to true if you're using an ssh client in your build step. */ + ssh?: boolean | null + /** The folder where your deployment project lives. */ + workspace: string +} + /* Required action data that gets initialized when running within the GitHub Actions environment. */ export const action: ActionInterface = { accessToken: getInput('ACCESS_TOKEN'), @@ -107,6 +128,7 @@ export const action: ActionInterface = { workspace: process.env.GITHUB_WORKSPACE || '' } +/** */ export type RequiredActionParameters = Pick< ActionInterface, 'accessToken' | 'gitHubToken' | 'ssh' | 'branch' | 'folder' diff --git a/src/lib.ts b/src/lib.ts index 6569351f..47ddb7a3 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -1,5 +1,5 @@ import {exportVariable, info, setFailed} from '@actions/core' -import {action, ActionInterface, Status} from './constants' +import {ActionInterface, Status, NodeActionInterface} from './constants' import {deploy, init} from './git' import { generateFolderPath, @@ -13,7 +13,7 @@ import { * @param {object} configuration - The action configuration. */ export default async function run( - configuration: ActionInterface + configuration: ActionInterface | NodeActionInterface ): Promise { let status: Status = Status.RUNNING @@ -22,25 +22,25 @@ export default async function run( GitHub Pages Deploy Action πŸš€ πŸš€ Getting Started Guide: https://github.com/marketplace/actions/deploy-to-github-pages - ❓ FAQ/Wiki: https://github.com/JamesIves/github-pages-deploy-action/wiki - πŸ”§ Support: https://github.com/JamesIves/github-pages-deploy-action/issues + ❓ Discussions / Q&A: https://github.com/JamesIves/github-pages-deploy-action/discussions + πŸ”§ Report a Bug: https://github.com/JamesIves/github-pages-deploy-action/issues ⭐ Contribute: https://github.com/JamesIves/github-pages-deploy-action/blob/dev/CONTRIBUTING.md - - πŸ“£ Maintained by James Ives (https://jamesiv.es)`) + + πŸ“£ Maintained by James Ives (https://jamesiv.es) + ❀ Support: https://github.com/sponsors/JamesIves`) info('Checking configuration and starting deployment… 🚦') - const settings = { - ...action, + const settings: ActionInterface = { ...configuration } - // Defines the folder paths + // Defines the repository/folder paths and token types. + // Also verifies that the action has all of the required parameters. settings.folderPath = generateFolderPath(settings) checkParameters(settings) - // Defines the repository paths and token types. settings.repositoryPath = generateRepositoryPath(settings) settings.tokenType = generateTokenType(settings) diff --git a/src/util.ts b/src/util.ts index fc52f541..cde4c3de 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,6 +3,7 @@ import path from 'path' import {isDebug} from '@actions/core' import {ActionInterface, RequiredActionParameters} from './constants' +/* Replaces all instances of a match in a string. */ const replaceAll = (input: string, find: string, replace: string): string => input.split(find).join(replace) @@ -49,6 +50,7 @@ const hasRequiredParameters = ( return Boolean(nonNullParams.length) } +/* Verifies the action has the required parameters to run, otherwise throw an error. */ export const checkParameters = (action: ActionInterface): void => { if (!hasRequiredParameters(action, ['accessToken', 'gitHubToken', 'ssh'])) { throw new Error( @@ -66,7 +68,7 @@ export const checkParameters = (action: ActionInterface): void => { if (!existsSync(action.folderPath as string)) { throw new Error( - `The ${action.folderPath} directory you're trying to deploy doesn't exist. ❗` + `The directory you're trying to deploy named ${action.folderPath} doesn't exist. Please double check the path and any prerequisite build scripts and try again. ❗` ) } }