diff --git a/.changeset/silly-jokes-refuse.md b/.changeset/silly-jokes-refuse.md new file mode 100644 index 00000000..e130dc9e --- /dev/null +++ b/.changeset/silly-jokes-refuse.md @@ -0,0 +1,5 @@ +--- +"@changesets/action": minor +--- + +Add support for commit signing with a GPG key diff --git a/README.md b/README.md index b64a4f0e..489a15f5 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ This action for [Changesets](https://github.com/atlassian/changesets) creates a - version - The command to update version, edit CHANGELOG, read and delete changesets. Default to `changeset version` if not provided - commit - The commit message to use. Default to `Version Packages` - title - The pull request title. Default to `Version Packages` +- gitUserName - The Git user name on commits. Default to `"github-actions[bot]"` +- gitUserEmail - The Git user email on commits. Default to `"github-actions[bot]@users.noreply.github.com"` ### Outputs @@ -173,3 +175,26 @@ If you are using [Yarn Plug'n'Play](https://yarnpkg.com/features/pnp), you shoul version: yarn changeset version ... ``` + +#### With Git commit signing + +If you would like to have the commits signed in the pull request, this action supports [commit signature verification using GPG](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification). + +To enable this: + +1. Add your GPG private key as a GitHub secret +2. Pass the secret in as the `GPG_PRIVATE_KEY` env variable +3. Pass in the associated email with the `gitUserEmail` input +4. (Optional) pass in a user name for the commits + +```yaml +- uses: changesets/action@v1 + env: + GPG_PRIVATE_KEY: ${{ secrets.GPG_SIGN_KEY }} + with: + gitUserEmail: 'octocat@github.com' + gitUserName: 'octocat' + ... +``` + +> Note: GPG needs to be installed on whichever image you're using in your GitHub action. diff --git a/action.yml b/action.yml index 61200769..5d69986c 100644 --- a/action.yml +++ b/action.yml @@ -17,6 +17,12 @@ inputs: title: description: The pull request title. Default to `Version Packages` required: false + gitUserName: + description: The Git user name on commits. Default to `"github-actions[bot]"` + required: false + gitUserEmail: + description: The Git user email on commits. Default to `"github-actions[bot]@users.noreply.github.com"` + required: false outputs: published: description: A boolean value to indicate whether a publishing is happened or not diff --git a/src/gitUtils.ts b/src/gitUtils.ts index 3c579830..7a0c0660 100644 --- a/src/gitUtils.ts +++ b/src/gitUtils.ts @@ -1,17 +1,18 @@ import { exec } from "@actions/exec"; import { execWithOutput } from "./utils"; -export const setupUser = async () => { - await exec("git", [ - "config", - "user.name", - `"github-actions[bot]"`, - ]); - await exec("git", [ - "config", - "user.email", - `"github-actions[bot]@users.noreply.github.com"`, - ]); +export const setupUser = async({ name, email }: { name: string; email: string; }) => { + await exec("git", ["config", "user.name", name]); + await exec("git", ["config", "user.email", email]); +}; + +export const setupCommitSigning = async (gpgPrivateKey: string) => { + await exec("gpg", ["--import"], { input: Buffer.from(gpgPrivateKey) }); + const { stdout: keyId } = await execWithOutput( + `/bin/bash -c "gpg --list-secret-keys --with-colons | grep '^sec:' | cut -d ':' -f 5"` + ); + await exec("git", ["config", "user.signingkey", keyId.trim()]); + await exec("git", ["config", "commit.gpgsign", "true"]); }; export const pullBranch = async (branch: string) => { diff --git a/src/index.ts b/src/index.ts index 5f3b871a..7efc498f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,8 +14,19 @@ const getOptionalInput = (name: string) => core.getInput(name) || undefined; return; } + const gitUserName = getOptionalInput("gitUserName") || `"github-actions[bot]"`; + const gitUserEmail = getOptionalInput("gitUserEmail") || `"github-actions[bot]@users.noreply.github.com"`; + console.log("setting git user"); - await gitUtils.setupUser(); + + await gitUtils.setupUser({ name: gitUserName, email: gitUserEmail }); + + const gpgPrivateKey = process.env.GPG_PRIVATE_KEY; + + if (gpgPrivateKey) { + console.log("using provided gpg private key for commit signing"); + await gitUtils.setupCommitSigning(gpgPrivateKey); + } console.log("setting GitHub credentials"); await fs.writeFile(