Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compliant Updates #56

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,45 @@ jobs:
token: ${{ secrets.GH_TOKEN_FOR_UPDATES }}
```

### Authenticating via a Github App

A GitHub App can both produce verified commits _and_ create pull requests that will trigger further GitHub Actions.

> **NOTE**: This will produce commits without a Nix-generated summary; i.e. the commit message will not tell you which inputs were updated from which old version to which new version.

Create a stub Github App in your organization. Disable webhooks, add Content write and Pull Request write permissions, and make it available only within your organization. Install the App in the Organization (possibly restricting only to relevant repos). Copy the App secret into an Actions secret, along with the App ID.

Set up your workflow like this:

```yaml
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 0 * * 1,4' # Run twice a week

jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v17
- name: Get Updater Token
uses: tibdex/github-app-token@v1
id: generate-token
with:
app_id: ${{ secrets.UPDATE_APP_ID}}
private_key: ${{secrets.UPDATE_APP_KEY}}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@vX
with:
token: ${{ steps.generate-token.outputs.token }}
commit-with-token: true

```

## With GPG commit signing

It's possible for the bot to produce GPG signed commits. Associating a GPG public key to a github user account is not required but it is necessary if you want the signed commits to appear as verified in Github. This can be a compliance requirement in some cases.
Expand All @@ -175,7 +214,7 @@ You can follow [Github's guide on creating and/or adding a new GPG key to an use

For the bot to produce signed commits, you will have to provide the GPG private keys to this action's input parameters. You can safely do that with [Github secrets as explained here](https://github.com/crazy-max/ghaction-import-gpg#prerequisites).

When using commit signing, the commit author name and email for the commits produced by this bot would correspond to the ones associated to the GPG Public Key.
When using commit signing, the commit author name and email for the commits produced by this bot would correspond to the ones associated to the GPG Public Key.

If you want to sign using a subkey, you must specify the subkey fingerprint using the `gpg-fingerprint` input parameter.

Expand Down
34 changes: 34 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ inputs:
description: 'GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT)'
required: false
default: ${{ github.token }}
commit-with-token:
description: 'Set to "true" to produce a verified commit with token'
required: false
default: ''
commit-msg:
description: 'The message provided with the commit'
required: false
Expand Down Expand Up @@ -119,6 +123,36 @@ runs:
TARGETS: ${{ inputs.inputs }}
COMMIT_MSG: ${{ inputs.commit-msg }}
PATH_TO_FLAKE_DIR: ${{ inputs.path-to-flake-dir }}
COMMIT_WITH_TOKEN: ${{ inputs.commit-with-token }}

- name: Commit changes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than dealing with the "get a verified-by-github commit" ourselves, I would much rather call out to an action or two that do this for us. And it just so happens that there is a combination of actions we can use to get the same result:

      - name: Create branch for ${{ inputs.branch }}
        if: ${{ inputs.commit-with-token == 'true' }}
        uses: peterjgrainger/[email protected]
        env:
          GITHUB_TOKEN: ${{ inputs.token }}
        with:
          branch: refs/heads/${{ inputs.branch }}
      - name: Create GitHub-verified commit
        if: ${{ inputs.commit-with-token == 'true' }}
        uses: swinton/[email protected]
        env:
          GH_TOKEN: ${{ inputs.token }}
        with:
          files: |
            flake.lock
          commit-message: ${{ inputs.commit-msg }}
          ref: refs/heads/${{ inputs.branch }}

You can see it works here: cole-h/test#7.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me try this on my fork

if: ${{ inputs.commit-with-token == 'true' }}
env:
GITHUB_TOKEN: ${{ inputs.token }}
FILE_TO_COMMIT: flake.lock
DESTINATION_BRANCH: ${{ inputs.branch }}
shell: bash
run: |
set -x
export CONTENT=$( base64 -i $FILE_TO_COMMIT )
export BASE=$DESTINATION_BRANCH
if gh api --method GET /repos/:owner/:repo/git/refs/heads/$DESTINATION_BRANCH; then
git fetch origin $DESTINATION_BRANCH
else
export BASE=$(gh repo view --json defaultBranchRef --template '{{ .defaultBranchRef.name }}' ${{github.repository}})
export BASE_SHA=$( git rev-parse origin/$BASE )
gh api --method POST /repos/:owner/:repo/git/refs \
--field ref=refs/heads/$DESTINATION_BRANCH \
--field sha=$BASE_SHA
fi
export BASE_SHA=$( git rev-parse origin/$BASE )
export SHA=$( git rev-parse origin/$BASE:$FILE_TO_COMMIT )
gh api --method PUT /repos/:owner/:repo/contents/$FILE_TO_COMMIT \
--field message="${{inputs.commit-msg}}" \
--field content="$CONTENT" \
--field encoding="base64" \
--field branch="$DESTINATION_BRANCH" \
--field sha="$SHA"
- name: Save PR Body as file
uses: DamianReeves/[email protected]
with:
Expand Down
10 changes: 8 additions & 2 deletions update-flake-lock.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@ if [[ -n "$PATH_TO_FLAKE_DIR" ]]; then
cd "$PATH_TO_FLAKE_DIR"
fi

commitArg=""
if [[ "$COMMIT_WITH_TOKEN" != "true" ]]; then
# Commit happening in next step
commitArg="suppress"
fi

if [[ -n "$TARGETS" ]]; then
inputs=()
for input in $TARGETS; do
inputs+=("--update-input" "$input")
done
nix flake lock "${inputs[@]}" --commit-lock-file --commit-lockfile-summary "$COMMIT_MSG"
nix flake lock "${inputs[@]}" ${commitArg:+"--commit-lock-file"} --commit-lockfile-summary "$COMMIT_MSG"
else
nix flake update --commit-lock-file --commit-lockfile-summary "$COMMIT_MSG"
nix flake update ${commitArg:+"--commit-lock-file"} --commit-lockfile-summary "$COMMIT_MSG"
fi