From 7a948416001d0886e19bd2575d9010b58e721198 Mon Sep 17 00:00:00 2001 From: James Ives Date: Thu, 10 Dec 2020 11:49:37 -0500 Subject: [PATCH] Simplifies Token Setup (#530) * Token simplification * Access Token / Github Token -> Token * Oops * Typos * Update README.md * Update README.md * Update action.yml Co-authored-by: Axel Hecht * Update README.md Co-authored-by: Axel Hecht * Update README.md Co-authored-by: Axel Hecht --- README.md | 23 +++++------ __tests__/git.test.ts | 24 ++++++------ __tests__/main.test.ts | 7 ++-- __tests__/util.test.ts | 86 +++++++++++------------------------------- action.yml | 15 +++++--- src/constants.ts | 19 ++++------ src/util.ts | 24 ++++-------- 7 files changed, 73 insertions(+), 125 deletions(-) diff --git a/README.md b/README.md index 36e31051..e5a017a5 100644 --- a/README.md +++ b/README.md @@ -64,10 +64,8 @@ jobs: - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@3.7.1 with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages # The branch the action should deploy to. FOLDER: build # The folder the action should deploy. - CLEAN: true # Automatically remove deleted files from the deploy branch ``` If you'd like to make it so the workflow only triggers on push events to specific branches then you can modify the `on` section. @@ -105,7 +103,7 @@ Calling the functions directly will require you to pass in an object containing import run from "github-pages-deploy-action"; run({ - accessToken: process.env["ACCESS_TOKEN"], + token: process.env["ACCESS_TOKEN"], branch: "gh-pages", folder: "build", repositoryName: "JamesIves/github-pages-deploy-action", @@ -122,28 +120,27 @@ The `with` portion of the workflow **must** be configured before the action will #### Required Setup -One of the following deployment options must be configured. - -| Key | Value Information | Type | Required | -| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- | -| `GITHUB_TOKEN` | In order for GitHub to trigger the rebuild of your page you must provide the action with the repository's provided GitHub token. This can be referenced in the workflow `yml` file by using `${{ secrets.GITHUB_TOKEN }}`. If you experience any issues with your changes not being reflected after the deployment it may be neccersary to use either the `SSH` or `ACCESS_TOKEN` options. | `secrets / with` | **Yes** | -| `SSH` | You can configure the action to deploy using SSH by setting this option to `true`. For more information on how to add your ssh key pair please refer to the [Using a Deploy Key section of this README](https://github.com/JamesIves/github-pages-deploy-action/tree/dev#using-an-ssh-deploy-key-). | `with` | **Yes** | -| `ACCESS_TOKEN` | Depending on the repository's permissions you may need to provide the action with a GitHub personal access token instead of the provided GitHub token in order to deploy. You can [learn more about how to generate one here](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line). **This should be stored as a secret**. | `secrets / with` | **Yes** | - -In addition to the deployment options you must also configure the following. +The following options must be configured in order to make a deployment. | Key | Value Information | Type | Required | | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | | `BRANCH` | This is the branch you wish to deploy to, for example `gh-pages` or `docs`. | `with` | **Yes** | | `FOLDER` | The folder in your repository that you want to deploy. If your build script compiles into a directory named `build` you'd put it here. If you wish to deploy the root directory you can place a `.` here. You can also utilize absolute file paths by appending `~` to your folder path. | `with` | **Yes** | +By default the action does not need any token configuration and uses the provided repository scoped GitHub token to make the deployment. If you require most customization you can modify the deployment type using the following options. + +| Key | Value Information | Type | Required | +| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | -------- | +| `TOKEN` | This option defaults to the repository scoped GitHub Token. However if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. This should be stored in the `secrets / with` menu **as a secret**. We reccomend using a service account with the least permissions neccersary and recommend when generating a new PAT that you select the least permission scopes neccersary. [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) | **No** | +| `SSH` | You can configure the action to deploy using SSH by setting this option to `true`. For more information on how to add your ssh key pair please refer to the [Using a Deploy Key section of this README](https://github.com/JamesIves/github-pages-deploy-action/tree/dev#using-an-ssh-deploy-key-). | `with` | **No** | + #### Optional Choices | Key | Value Information | Type | Required | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | | `GIT_CONFIG_NAME` | Allows you to customize the name that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the name in the GitHub context, followed by the name of the action. | `with` | **No** | | `GIT_CONFIG_EMAIL` | Allows you to customize the email that is attached to the git config which is used when pushing the deployment commits. If this is not included it will use the email in the GitHub context, followed by a generic noreply GitHub email. | `with` | **No** | -| `REPOSITORY_NAME` | Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: `JamesIves/github-pages-deploy-action`. You'll need to use an `ACCESS_TOKEN` for this configuration option to work properly. | `with` | **No** | +| `REPOSITORY_NAME` | Allows you to specify a different repository path so long as you have permissions to push to it. This should be formatted like so: `JamesIves/github-pages-deploy-action`. You'll need to use a PAT in the `TOKEN` input for this configuration option to work properly. | `with` | **No** | | `TARGET_FOLDER` | If you'd like to push the contents of the deployment folder into a specific directory on the deployment branch you can specify it here. | `with` | **No** | | `COMMIT_MESSAGE` | If you need to customize the commit message for an integration you can do so. | `with` | **No** | | `CLEAN` | If your project generates hashed files on build you can use this option to automatically delete them from the deployment branch with each deploy. This option is turned on by default, and can be toggled off by setting it to `false`. | `with` | **No** | diff --git a/__tests__/git.test.ts b/__tests__/git.test.ts index ce3fda76..6a47a1fd 100644 --- a/__tests__/git.test.ts +++ b/__tests__/git.test.ts @@ -43,7 +43,7 @@ describe('git', () => { Object.assign(action, { silent: false, repositoryPath: 'JamesIves/github-pages-deploy-action', - accessToken: '123', + token: '123', branch: 'branch', folder: '.', isTest: true, @@ -67,7 +67,7 @@ describe('git', () => { it('should execute five commands', async () => { Object.assign(action, { silent: false, - accessToken: '123', + token: '123', branch: 'branch', folder: '.', pusher: { @@ -87,7 +87,7 @@ describe('git', () => { Object.assign(action, { silent: false, - accessToken: '123', + token: '123', branch: 'branch', folder: '.', pusher: { @@ -112,7 +112,7 @@ describe('git', () => { silent: false, folder: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -139,7 +139,7 @@ describe('git', () => { dryRun: true, folder: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -166,7 +166,7 @@ describe('git', () => { folder: 'other', folderPath: 'other', branch: 'branch', - gitHubToken: '123', + token: '123', singleCommit: true, pusher: { name: 'asd', @@ -188,7 +188,7 @@ describe('git', () => { folder: 'assets', folderPath: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -214,7 +214,7 @@ describe('git', () => { folder: 'other', folderPath: 'other', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -237,7 +237,7 @@ describe('git', () => { folder: 'assets', folderPath: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -258,7 +258,7 @@ describe('git', () => { silent: false, folder: '.', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: {}, clean: true, targetFolder: 'new_folder', @@ -279,7 +279,7 @@ describe('git', () => { silent: false, folder: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -302,7 +302,7 @@ describe('git', () => { silent: false, folder: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 7a475eb5..6044032f 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -39,7 +39,7 @@ describe('main', () => { repositoryPath: 'JamesIves/github-pages-deploy-action', folder: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -58,7 +58,7 @@ describe('main', () => { repositoryPath: 'JamesIves/github-pages-deploy-action', folder: 'assets', branch: 'branch', - gitHubToken: '123', + token: '123', pusher: { name: 'asd', email: 'as@cat' @@ -74,9 +74,8 @@ describe('main', () => { Object.assign(action, { folder: 'assets', branch: 'branch', - gitHubToken: null, + token: null, ssh: null, - accessToken: null, pusher: { name: 'asd', email: 'as@cat' diff --git a/__tests__/util.test.ts b/__tests__/util.test.ts index 1f21cf39..dd37eff0 100644 --- a/__tests__/util.test.ts +++ b/__tests__/util.test.ts @@ -37,38 +37,23 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: 'build', - gitHubToken: null, - accessToken: null, + token: null, ssh: true, silent: false } expect(generateTokenType(action)).toEqual('SSH Deploy Key') }) - it('should return access token if access token is provided', async () => { + it('should return deploy token if token is provided', async () => { const action = { branch: '123', workspace: 'src/', folder: 'build', - gitHubToken: null, - accessToken: '123', + token: '123', ssh: null, silent: false } - expect(generateTokenType(action)).toEqual('Access Token') - }) - - it('should return github token if github token is provided', async () => { - const action = { - branch: '123', - workspace: 'src/', - folder: 'build', - gitHubToken: '123', - accessToken: null, - ssh: null, - silent: false - } - expect(generateTokenType(action)).toEqual('GitHub Token') + expect(generateTokenType(action)).toEqual('Deploy Token') }) it('should return ... if no token is provided', async () => { @@ -76,8 +61,7 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: 'build', - gitHubToken: null, - accessToken: null, + token: null, ssh: null, silent: false } @@ -92,8 +76,7 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: 'build', - gitHubToken: null, - accessToken: null, + token: null, ssh: true, silent: false } @@ -102,30 +85,13 @@ describe('util', () => { ) }) - it('should return https if access token is provided', async () => { + it('should return https with x-access-token if deploy token is provided', async () => { const action = { repositoryName: 'JamesIves/github-pages-deploy-action', branch: '123', workspace: 'src/', folder: 'build', - gitHubToken: null, - accessToken: '123', - ssh: null, - silent: false - } - expect(generateRepositoryPath(action)).toEqual( - 'https://123@github.com/JamesIves/github-pages-deploy-action.git' - ) - }) - - it('should return https with x-access-token if github token is provided', async () => { - const action = { - repositoryName: 'JamesIves/github-pages-deploy-action', - branch: '123', - workspace: 'src/', - folder: 'build', - gitHubToken: '123', - accessToken: null, + token: '123', ssh: null, silent: false } @@ -143,14 +109,13 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: 'build', - accessToken: 'supersecret999%%%', - gitHubToken: 'anothersecret123333', + token: 'anothersecret123333', silent: false } - const string = `This is an error message! It contains ${action.accessToken} and ${action.gitHubToken} and ${action.repositoryPath} and ${action.accessToken} again!` + const string = `This is an error message! It contains ${action.token} and ${action.repositoryPath} and ${action.token} again!` expect(suppressSensitiveInformation(string, action)).toBe( - 'This is an error message! It contains *** and *** and *** and *** again!' + 'This is an error message! It contains *** and *** and *** again!' ) }) @@ -162,16 +127,15 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: 'build', - accessToken: 'supersecret999%%%', - gitHubToken: 'anothersecret123333', + token: 'anothersecret123333', silent: false } process.env['RUNNER_DEBUG'] = '1' - const string = `This is an error message! It contains ${action.accessToken} and ${action.gitHubToken} and ${action.repositoryPath}` + const string = `This is an error message! It contains ${action.token} and ${action.repositoryPath}` expect(suppressSensitiveInformation(string, action)).toBe( - 'This is an error message! It contains supersecret999%%% and anothersecret123333 and https://x-access-token:supersecret999%%%@github.com/anothersecret123333' + 'This is an error message! It contains anothersecret123333 and https://x-access-token:supersecret999%%%@github.com/anothersecret123333' ) }) }) @@ -183,8 +147,7 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: 'build', - gitHubToken: null, - accessToken: null, + token: null, ssh: null, silent: false } @@ -196,8 +159,7 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: '/home/user/repo/build', - gitHubToken: null, - accessToken: null, + token: null, ssh: null, silent: false } @@ -209,8 +171,7 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: './build', - gitHubToken: null, - accessToken: null, + token: null, ssh: null, silent: false } @@ -222,8 +183,7 @@ describe('util', () => { branch: '123', workspace: 'src/', folder: '~/repo/build', - gitHubToken: null, - accessToken: null, + token: null, ssh: null, silent: false } @@ -251,11 +211,11 @@ describe('util', () => { } }) - it('should fail if access token is defined but it is an empty string', () => { + it('should fail if token is defined but it is an empty string', () => { const action = { silent: false, repositoryPath: undefined, - accessToken: '', + token: '', branch: 'branch', folder: 'build', workspace: 'src/' @@ -274,7 +234,7 @@ describe('util', () => { const action = { silent: false, repositoryPath: undefined, - accessToken: '123', + token: '123', branch: '', folder: 'build', workspace: 'src/' @@ -291,7 +251,7 @@ describe('util', () => { const action = { silent: false, repositoryPath: undefined, - gitHubToken: '123', + token: '123', branch: 'branch', folder: '', workspace: 'src/' @@ -310,7 +270,7 @@ describe('util', () => { const action: ActionInterface = { silent: false, repositoryPath: undefined, - gitHubToken: '123', + token: '123', branch: 'branch', folder: 'notARealFolder', workspace: '.' diff --git a/action.yml b/action.yml index abd495e6..2383a022 100644 --- a/action.yml +++ b/action.yml @@ -12,13 +12,18 @@ inputs: description: 'You can configure the action to deploy using SSH by setting this option to true. More more information on how to add your ssh key pair please refer to the Using a Deploy Key section of this README.' required: false - ACCESS_TOKEN: - description: 'Depending on the repository permissions you may need to provide the action with a GitHub personal access token instead of the provided GitHub token in order to deploy. This should be stored as a secret.' - required: false + TOKEN: + description: > + This option defaults to the repository scoped GitHub Token. + However if you need more permissions for things such as deploying to another repository, you can add a Personal Access Token (PAT) here. + This should be stored in the `secrets / with` menu **as a secret**. - GITHUB_TOKEN: - description: 'In order for GitHub to trigger the rebuild of your page you must provide the action with the repositories provided GitHub token.' + We recommend using a service account with the least permissions neccersary + and when generating a new PAT that you select the least permission scopes required. + + [Learn more about creating and using encrypted secrets here.](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) required: false + default: ${{ github.token }} BRANCH: description: 'This is the branch you wish to deploy to, for example gh-pages or docs.' diff --git a/src/constants.ts b/src/constants.ts index 63558f8b..0b85dcde 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -6,8 +6,6 @@ const {pusher, repository} = github.context.payload /* For more information please refer to the README: https://github.com/JamesIves/github-pages-deploy-action */ export interface ActionInterface { - /** Deployment access token. */ - accessToken?: string | null /** The branch that the action should deploy to. */ branch: string /** git push with --dry-run */ @@ -24,8 +22,6 @@ export interface ActionInterface { folder: string /** The auto generated folder path. */ folderPath?: string - /** GitHub deployment token. */ - gitHubToken?: string | null /** Determines if the action is running in test mode or not. */ isTest?: boolean | null /** The git config name. */ @@ -42,7 +38,9 @@ export interface ActionInterface { ssh?: boolean | null /** If you'd like to push the contents of the deployment folder into a specific directory on the deployment branch you can specify it here. */ targetFolder?: string - /** The token type, ie ssh/github token/access token, this gets automatically generated. */ + /** Deployment token. */ + token?: string | null + /** The token type, ie ssh/token, this gets automatically generated. */ tokenType?: string /** The folder where your deployment project lives. */ workspace: string @@ -50,16 +48,14 @@ export interface ActionInterface { /** 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 + /** GitHub deployment token. */ + token?: string | null /** 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. */ @@ -70,7 +66,6 @@ export interface NodeActionInterface { /* Required action data that gets initialized when running within the GitHub Actions environment. */ export const action: ActionInterface = { - accessToken: getInput('ACCESS_TOKEN'), folder: getInput('FOLDER'), branch: getInput('BRANCH'), commitMessage: getInput('COMMIT_MESSAGE'), @@ -91,7 +86,6 @@ export const action: ActionInterface = { : `${ process.env.GITHUB_ACTOR || 'github-pages-deploy-action' }@users.noreply.github.com`, - gitHubToken: getInput('GITHUB_TOKEN'), name: !isNullOrUndefined(getInput('GIT_CONFIG_NAME')) ? getInput('GIT_CONFIG_NAME') : pusher && pusher.name @@ -104,6 +98,7 @@ export const action: ActionInterface = { : repository && repository.full_name ? repository.full_name : process.env.GITHUB_REPOSITORY, + token: getInput('TOKEN'), singleCommit: !isNullOrUndefined(getInput('SINGLE_COMMIT')) ? getInput('SINGLE_COMMIT').toLowerCase() === 'true' : false, @@ -120,7 +115,7 @@ export const action: ActionInterface = { /** Types for the required action parameters. */ export type RequiredActionParameters = Pick< ActionInterface, - 'accessToken' | 'gitHubToken' | 'ssh' | 'branch' | 'folder' + 'token' | 'ssh' | 'branch' | 'folder' > /** Status codes for the action. */ diff --git a/src/util.ts b/src/util.ts index cde4c3de..d43a1e09 100644 --- a/src/util.ts +++ b/src/util.ts @@ -13,21 +13,15 @@ export const isNullOrUndefined = (value: any): boolean => /* Generates a token type used for the action. */ export const generateTokenType = (action: ActionInterface): string => - action.ssh - ? 'SSH Deploy Key' - : action.accessToken - ? 'Access Token' - : action.gitHubToken - ? 'GitHub Token' - : '…' + action.ssh ? 'SSH Deploy Key' : action.token ? 'Deploy Token' : '…' /* Generates a the repository path used to make the commits. */ export const generateRepositoryPath = (action: ActionInterface): string => action.ssh ? `git@github.com:${action.repositoryName}` - : `https://${ - action.accessToken || `x-access-token:${action.gitHubToken}` - }@github.com/${action.repositoryName}.git` + : `https://${`x-access-token:${action.token}`}@github.com/${ + action.repositoryName + }.git` /* Genetate absolute folder path by the provided folder name */ export const generateFolderPath = (action: ActionInterface): string => { @@ -52,7 +46,7 @@ const hasRequiredParameters = ( /* 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'])) { + if (!hasRequiredParameters(action, ['token', 'ssh'])) { throw new Error( 'No deployment token/method was provided. You must provide the action with either a Personal Access Token or the GitHub Token secret in order to deploy. If you wish to use an ssh deploy token then you must set SSH to true.' ) @@ -85,11 +79,9 @@ export const suppressSensitiveInformation = ( return value } - const orderedByLength = ([ - action.accessToken, - action.gitHubToken, - action.repositoryPath - ].filter(Boolean) as string[]).sort((a, b) => b.length - a.length) + const orderedByLength = ([action.token, action.repositoryPath].filter( + Boolean + ) as string[]).sort((a, b) => b.length - a.length) for (const find of orderedByLength) { value = replaceAll(value, find, '***')