Compare commits

..

No commits in common. "main" and "v15" have entirely different histories.
main ... v15

25 changed files with 212 additions and 94336 deletions

View file

@ -1,10 +1,15 @@
# https://editorconfig.org
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
[*.{yml,yaml}]
indent_size = 2

1
.envrc
View file

@ -1 +0,0 @@
use flake

View file

@ -1,74 +0,0 @@
{
"plugins": ["@typescript-eslint"],
"extends": ["plugin:github/recommended"],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"project": "./tsconfig.json"
},
"settings": {
"import/resolver": {
"typescript": {}
}
},
"rules": {
"i18n-text/no-en": "off",
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_"
}
],
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "no-public"
}
],
"@typescript-eslint/no-base-to-string": "error",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "error",
"camelcase": "error",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true
}
],
"@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error"
},
"env": {
"node": true,
"es6": true
}
}

View file

@ -1,40 +1,17 @@
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
typescript-action:
runs-on: ubuntu-22.04
shellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Check Nixpkgs
uses: DeterminateSystems/flake-checker-action@main
with:
fail-mode: true
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- name: Enable FlakeHub Cache
uses: DeterminateSystems/flakehub-cache-action@main
- name: Install pnpm dependencies
run: nix develop --command pnpm install
- name: Check formatting
run: nix develop --command pnpm run check-fmt
- name: Lint
run: nix develop --command pnpm run lint
- name: Build
run: nix develop --command pnpm run build
- name: Run test suite
run: nix develop --command pnpm run test
- name: Package
run: nix develop --command pnpm run package
- name: Check git status
run: git status --porcelain=v1
- name: Ensure no staged changes
run: git diff --exit-code
- name: Install Nix
uses: cachix/install-nix-action@v17
- name: Shellcheck
run: nix-shell --run 'shellcheck $(find . -type f -name "*.sh" -executable)'

View file

@ -1,23 +1,19 @@
name: update-flake-lock
on:
workflow_dispatch:
schedule:
- cron: "0 0 * * 0"
- cron: '0 0 * * 0'
jobs:
lockfile:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
- name: Checkout repository
uses: actions/checkout@v3
- name: Install Nix
uses: cachix/install-nix-action@v17
with:
determinate: true
- name: Enable FlakeHub Cache
uses: DeterminateSystems/flakehub-cache-action@main
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: ./.
with:
_internal-strict-mode: true

View file

@ -1,5 +1,4 @@
name: CI
on:
pull_request:
push:
@ -7,13 +6,13 @@ on:
jobs:
validate:
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Validate YAML
uses: nwisbeta/validate-yaml-schema@v2.0.0
uses: nwisbeta/validate-yaml-schema@v1.0.3
with:
yamlSchemasJson: |
{

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
# JS dependencies
node_modules/

View file

@ -1,5 +0,0 @@
dist/
lib/
node_modules/
pnpm-lock.yaml
README.md

216
README.md
View file

@ -1,18 +1,15 @@
# update-flake-lock
This is a GitHub Action that updates the [`flake.lock`][lockfile] file for your [Nix flake][flakes] whenever it is run.
This is a GitHub Action that will update your flake.lock file whenever it is run.
> [!NOTE]
> As of v3, this action no longer automatically installs [Determinate Nix][det-nix] to the action runner.
> You **must** set up Nix with flakes support enabled prior to running this action or your workflow will not function as expected.
> **NOTE:** As of v3, this action will no longer automatically install Nix to the action runner. You **MUST** set up a Nix with flakes support enabled prior to running this action, or your workflow will not function as expected.
## Example
Here's an example GitHub Action workflow using this Action:
An example GitHub Action workflow using this action would look like the following:
```yaml
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
@ -23,13 +20,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
with:
determinate: true
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
pr-title: "Update flake.lock" # Title of PR to be created
pr-labels: | # Labels to be set on the PR
@ -39,14 +37,12 @@ jobs:
## Example updating specific input(s)
> [!NOTE]
> If any inputs have a stale reference (e.g. the lockfile thinks a git input wants its "ref" to be "nixos-unstable", but the flake.nix specifies "nixos-unstable-small"), they are also updated. At this time, there is no known workaround.
> **NOTE**: If any inputs have a stale reference (e.g. the lockfile thinks a git input wants its "ref" to be "nixos-unstable", but the flake.nix specifies "nixos-unstable-small"), they will also be updated. At this time, there is no known workaround.
It's also possible to update specific [flake inputs][inputs] by specifying them in a space-separated list:
It is also possible to update specific inputs by specifying them in a space-separated list:
```yaml
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
@ -57,44 +53,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
with:
determinate: true
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
inputs: input1 input2 input3
```
## Example adding options to nix command
It's also possible to use specific options to the `nix` command in a space-separated list:
```yaml
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
- cron: '0 0 * * 0' # runs weekly on Sunday at 00:00
jobs:
lockfile:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
with:
nix-options: --debug --log-format raw
```
## Example that prints the number of the created PR
```yaml
@ -109,14 +79,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
with:
determinate: true
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
id: update
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
inputs: input1 input2 input3
- name: Print PR number
@ -140,14 +111,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
with:
determinate: true
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
if: ${{ github.event_name != 'pull_request' }}
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
inputs: input1 input2 input3
path-to-flake-dir: 'nix/' # in this example our flake doesn't sit at the root of the repository, it sits under 'nix/flake.nix'
@ -169,33 +141,41 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
with:
determinate: true
extra_nix_config: |
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
git-author-name: Jane Author
git-author-email: github-actions[bot]@users.noreply.github.com
git-committer-name: John Committer
git-committer-email: github-actions[bot]@users.noreply.github.com
git-author-name: 'Jane Author'
git-author-email: 'github-actions[bot]@users.noreply.github.com'
git-committer-name: 'John Committer'
git-committer-email: 'github-actions[bot]@users.noreply.github.com'
```
## Running GitHub Actions CI
GitHub Actions doesn't run workflows when a branch is pushed by or a PR is opened by a GitHub Action.
There are two ways to have GitHub Actions CI run on a PR submitted by this action.
GitHub Actions will not run workflows when a branch is pushed by or a PR is opened by a GitHub Action. There are two ways to have GitHub Actions CI run on a PR submitted by this action.
### Without a Personal Authentication Token
Without using a Personal Authentication Token, close and reopen the pull request manually to kick off CI.
Without using a Personal Authentication Token, you can manually run the following to kick off a CI run:
```
git branch -D update_flake_lock_action
git fetch origin
git checkout update_flake_lock_action
git commit --amend --no-edit
git push origin update_flake_lock_action --force
```
### With a Personal Authentication Token
By providing a Personal Authentication Token, the PR is submitted in a way that bypasses this limitation (GitHub essentially thinks it's the owner of the PAT submitting the PR, and not an Action).
You can create a token by visiting https://github.com/settings/tokens and select at least the `repo` scope. For the new fine-grained tokens, you need to enable read and write access for "Contents" and "Pull Requests" permissions. Then, store this token in your repository secrets (i.e. `https://github.com/<USER>/<REPO>/settings/secrets/actions`) as `GH_TOKEN_FOR_UPDATES` and set up your workflow file like the following:
By providing a Personal Authentication Token, the PR will be submitted in a way that bypasses this limitation (GitHub will essentially think it is the owner of the PAT submitting the PR, and not an Action).
You can create a token by visiting https://github.com/settings/tokens and select at least the `repo` scope. Then, store this token in your repository secrets (i.e. `https://github.com/<USER>/<REPO>/settings/secrets/actions`) as `GH_TOKEN_FOR_UPDATES` and set up your workflow file like the following:
```yaml
name: update-flake-lock
@ -209,37 +189,31 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
token: ${{ secrets.GH_TOKEN_FOR_UPDATES }}
```
## 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 isn't 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.
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.
You can follow [GitHub's guide to creating and/or adding a new GPG key to an user account](https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-new-gpg-key-to-your-github-account).
Using a specific GitHub user account for the bot can be a good security measure to dissociate this bot's actions and commits from your personal GitHub account.
You can follow [Github's guide on creating and/or adding a new GPG key to an user account](https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-new-gpg-key-to-your-github-account). Using a specific github user account for the bot can be a good security measure to dissociate this bot's actions and commits from your personal github account.
For the bot to produce signed commits, you need 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).
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.
If you want to sign using a subkey, you must specify the subkey fingerprint using the `gpg-fingerprint` input parameter.
Here's an example of how to using this action with commit signing:
You can find an example of how to using this action with commit signing below:
```yaml
name: update-flake-lock
on:
workflow_dispatch: # allows manual triggering
schedule:
@ -250,13 +224,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v16
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
uses: DeterminateSystems/update-flake-lock@vX
with:
sign-commits: true
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
@ -266,19 +238,18 @@ jobs:
## Custom PR Body
By default, the generated PR body uses this template:
By default the generated PR body is set to be the following template:
````handlebars
Automated changes by the [update-flake-lock](https://github.com/DeterminateSystems/update-flake-lock) GitHub Action.
````
```
{{ env.GIT_COMMIT_MESSAGE }}
````
```
### Running GitHub Actions on this PR
GitHub Actions doesn't run workflows on pull requests that are opened by a GitHub Action.
GitHub Actions will not run workflows on pull requests which are opened by a GitHub Action.
To run GitHub Actions workflows on this PR, run:
@ -291,56 +262,17 @@ git push origin update_flake_lock_action --force
```
````
You can customize it, however, using variable interpolation performed with [Handlebars].
This enables you to customize the template with these variables:
- `env.GIT_AUTHOR_NAME`
- `env.GIT_AUTHOR_EMAIL`
- `env.GIT_COMMITTER_NAME`
- `env.GIT_COMMITTER_EMAIL`
- `env.GIT_COMMIT_MESSAGE`
## Add assignees or reviewers
You can assign the PR to or request a review from one or more GitHub users with `pr-assignees` and `pr-reviewers`, respectively.
These properties expect a comma or newline separated list of GitHub usernames:
```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@v4
- name: Install Determinate Nix
uses: DeterminateSystems/nix-installer-action@main
with:
determinate: true
- name: Update flake.lock
uses: DeterminateSystems/update-flake-lock@main
with:
pr-assignees: SomeGitHubUsername
pr-reviewers: SomeOtherGitHubUsername,SomeThirdGitHubUsername
```
However you can customize it, with variable interpolation performed with [Handlebars](https://handlebarsjs.com/). This allows you to customize the template with the following variables:
- env.GIT_AUTHOR_NAME
- env.GIT_AUTHOR_EMAIL
- env.GIT_COMMITTER_NAME
- env.GIT_COMMITTER_EMAIL
- env.GIT_COMMIT_MESSAGE
## Contributing
Feel free to send a PR or open an issue if you find that something functions unexpectedly!
Please make sure to test your changes and update any related documentation before submitting your PR.
Feel free to send a PR or open an issue if you find something functions unexpectedly! Please make sure to test your changes and update any related documentation before submitting your PR.
### How to test changes
In order to more easily test your changes to this action, we have created a template repository that should point you in the right direction: https://github.com/DeterminateSystems/update-flake-lock-test-template.
Please see the README in that repository for instructions on testing your changes.
[det-nix]: https://docs.determinate.systems/determinate-nix
[flakes]: https://zero-to-nix.com/concepts/flakes
[handlebars]: https://handlebarsjs.com
[inputs]: https://zero-to-nix.com/concepts/flakes/#inputs
[lockfile]: https://zero-to-nix.com/concepts/flakes/#lockfile
In order to more easily test your changes to this action, we have created a template repository that should point you in the right direction: https://github.com/DeterminateSystems/update-flake-lock-test-template. Please see the README in that repository for instructions on testing your changes.

View file

@ -1,34 +1,32 @@
name: "Update Nix Flake Lock"
description: "Update your Nix flake.lock and send a PR"
name: 'Update flake.lock'
description: 'Update your flake.lock and send a PR'
inputs:
inputs:
description: "A space-separated list of inputs to update. Leave empty to update all inputs."
description: 'A space-separated list of inputs to update. Leave empty to update all inputs.'
required: false
default: ""
default: ''
token:
description: "GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT)"
description: 'GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT)'
required: false
default: ${{ github.token }}
commit-msg:
description: "The message provided with the commit"
description: 'The message provided with the commit'
required: false
default: "flake.lock: Update"
base:
description: "Sets the pull request base branch. Defaults to the branch checked out in the workflow."
required: false
branch:
description: "The branch of the PR to be created"
description: 'The branch of the PR to be created'
required: false
default: "update_flake_lock_action"
path-to-flake-dir:
description: "The path of the directory containing `flake.nix` file within your repository. Useful when `flake.nix` cannot reside at the root of your repository."
description: 'The path of the directory containing `flake.nix` file within your repository. Useful when `flake.nix` cannot reside at the root of your repository.'
required: false
default: ''
pr-title:
description: "The title of the PR to be created"
description: 'The title of the PR to be created'
required: false
default: "flake.lock: Update"
pr-body:
description: "The body of the PR to be created"
description: 'The body of the PR to be created'
required: false
default: |
Automated changes by the [update-flake-lock](https://github.com/DeterminateSystems/update-flake-lock) GitHub Action.
@ -41,79 +39,65 @@ inputs:
GitHub Actions will not run workflows on pull requests which are opened by a GitHub Action.
**To run GitHub Actions workflows on this PR, close and re-open this pull request.**
To run GitHub Actions workflows on this PR, run:
```sh
git branch -D update_flake_lock_action
git fetch origin
git checkout update_flake_lock_action
git commit --amend --no-edit
git push origin update_flake_lock_action --force
```
pr-labels:
description: "A comma or newline separated list of labels to set on the Pull Request to be created"
description: 'A comma or newline separated list of labels to set on the Pull Request to be created'
required: false
default: ""
pr-assignees:
description: "A comma or newline separated list of assignees (GitHub usernames)."
required: false
default: ""
pr-reviewers:
description: "A comma or newline separated list of reviewers (GitHub usernames) to request a review from."
required: false
default: ""
default: ''
git-author-name:
description: "Author name used for commit. Only used if sign-commits is false."
description: 'Author name used for commit. Only used if sign-commits is false.'
required: false
default: "github-actions[bot]"
default: 'github-actions[bot]'
git-author-email:
description: "Author email used for commit. Only used if sign-commits is false."
description: 'Author email used for commit. Only used if sign-commits is false.'
required: false
default: "github-actions[bot]@users.noreply.github.com"
default: 'github-actions[bot]@users.noreply.github.com'
git-committer-name:
description: "Committer name used for commit. Only used if sign-commits is false."
description: 'Committer name used for commit. Only used if sign-commits is false.'
required: false
default: "github-actions[bot]"
default: 'github-actions[bot]'
git-committer-email:
description: "Committer email used for commit. Only used if sign-commits is false."
description: 'Committer email used for commit. Only used if sign-commits is false.'
required: false
default: "github-actions[bot]@users.noreply.github.com"
default: 'github-actions[bot]@users.noreply.github.com'
sign-commits:
description: "Set to true if the action should sign the commit with GPG"
description: 'Set to true if the action should sign the commit with GPG'
required: false
default: "false"
default: 'false'
gpg-private-key:
description: "GPG Private Key with which to sign the commits in the PR to be created"
description: 'GPG Private Key with which to sign the commits in the PR to be created'
required: false
default: ""
default: ''
gpg-fingerprint:
description: "Fingerprint of specific GPG subkey to use"
description: 'Fingerprint of specific GPG subkey to use'
required: false
gpg-passphrase:
description: "GPG Private Key Passphrase for the GPG Private Key with which to sign the commits in the PR to be created"
description: 'GPG Private Key Passphrase for the GPG Private Key with which to sign the commits in the PR to be created'
required: false
default: ""
nix-options:
description: "A space-separated list of options to pass to the nix command"
required: false
default: ""
_internal-strict-mode:
description: Whether to fail when any errors are thrown. Used only to test the Action; do not set this in your own workflows.
required: false
default: false
default: ''
outputs:
pull-request-number:
description: "The number of the opened pull request"
description: 'The number of the opened pull request'
value: ${{ steps.create-pr.outputs.pull-request-number }}
pull-request-url:
description: "The The URL of the opened pull request."
value: ${{ steps.create-pr.outputs.pull-request-url }}
pull-request-operation:
description: "The pull request operation performed by the action, `created`, `updated` or `closed`."
value: ${{ steps.create-pr.outputs.pull-request-operation }}
runs:
using: "composite"
steps:
- name: Import bot's GPG key for signing commits
if: ${{ inputs.sign-commits == 'true' }}
id: import-gpg
uses: crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ inputs.gpg-private-key }}
fingerprint: ${{ inputs.gpg-fingerprint }}
fingerprint: ${{ inputs.gpg-fingerprint }}
passphrase: ${{ inputs.gpg-passphrase }}
git_config_global: true
git_user_signingkey: true
@ -140,37 +124,19 @@ runs:
echo "GIT_AUTHOR_EMAIL=<${{ inputs.git-author-email }}>" >> $GITHUB_ENV
echo "GIT_COMMITTER_NAME=${{ inputs.git-committer-name }}" >> $GITHUB_ENV
echo "GIT_COMMITTER_EMAIL=<${{ inputs.git-committer-email }}>" >> $GITHUB_ENV
- name: Run update-flake-lock
- name: Run update-flake-lock.sh
run: $GITHUB_ACTION_PATH/update-flake-lock.sh
shell: bash
run: node "$GITHUB_ACTION_PATH/dist/index.js"
env:
# The following manually exposes all of the action inputs into INPUT_ environment variables so actionsCore.getInput works:
# https://github.com/actions/toolkit/blob/ae38557bb0dba824cdda26ce787bd6b66cf07a83/packages/core/src/core.ts#L126
INPUT_BASE: ${{ inputs.base }}
INPUT_BRANCH: ${{ inputs.branch }}
INPUT_COMMIT-MSG: ${{ inputs.commit-msg }}
INPUT_GIT-AUTHOR-EMAIL: ${{ inputs.git-author-email }}
INPUT_GIT-AUTHOR-NAME: ${{ inputs.git-author-name }}
INPUT_GIT-COMMITTER-EMAIL: ${{ inputs.git-committer-email }}
INPUT_GIT-COMMITTER-NAME: ${{ inputs.git-committer-name }}
INPUT_GPG-FINGERPRINT: ${{ inputs.gpg-fingerprint }}
INPUT_GPG-PASSPHRASE: ${{ inputs.gpg-passphrase }}
INPUT_GPG-PRIVATE-KEY: ${{ inputs.gpg-private-key }}
INPUT_INPUTS: ${{ inputs.inputs }}
INPUT_NIX-OPTIONS: ${{ inputs.nix-options }}
INPUT_PATH-TO-FLAKE-DIR: ${{ inputs.path-to-flake-dir }}
INPUT_PR-ASSIGNEES: ${{ inputs.pr-assignees }}
INPUT_PR-BODY: ${{ inputs.pr-body }}
INPUT_PR-LABELS: ${{ inputs.pr-labels }}
INPUT_PR-REVIEWERS: ${{ inputs.pr-reviewers }}
INPUT_PR-TITLE: ${{ inputs.pr-title }}
INPUT_PULL-REQUEST-NUMBER: ${{ inputs.pull-request-number }}
INPUT_PULL-REQUEST-OPERATION: ${{ inputs.pull-request-operation }}
INPUT_SIGN-COMMITS: ${{ inputs.sign-commits }}
INPUT_TOKEN: ${{ inputs.token }}
INPUT__INTERNAL-STRICT-MODE: ${{ inputs._internal-strict-mode }}
GIT_AUTHOR_NAME: ${{ env.GIT_AUTHOR_NAME }}
GIT_AUTHOR_EMAIL: ${{ env.GIT_AUTHOR_EMAIL }}
GIT_COMMITTER_NAME: ${{ env.GIT_COMMITTER_NAME }}
GIT_COMMITTER_EMAIL: ${{ env.GIT_COMMITTER_EMAIL }}
TARGETS: ${{ inputs.inputs }}
COMMIT_MSG: ${{ inputs.commit-msg }}
PATH_TO_FLAKE_DIR: ${{ inputs.path-to-flake-dir }}
- name: Save PR Body as file
uses: DamianReeves/write-file-action@v1.3
uses: DamianReeves/write-file-action@v1.1
with:
path: pr_body.template
contents: ${{ inputs.pr-body }}
@ -178,20 +144,20 @@ runs:
- name: Set additional env variables (GIT_COMMIT_MESSAGE)
shell: bash
run: |
DELIMITER=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
COMMIT_MESSAGE="$(git log --format=%b -n 1)"
echo "GIT_COMMIT_MESSAGE<<$DELIMITER" >> $GITHUB_ENV
echo "$COMMIT_MESSAGE" >> $GITHUB_ENV
echo "$DELIMITER" >> $GITHUB_ENV
echo "GIT_COMMIT_MESSAGE is: ${COMMIT_MESSAGE}"
GIT_COMMIT_MESSAGE="$(git log --format=%b -n 1)"
GIT_COMMIT_MESSAGE="${GIT_COMMIT_MESSAGE//'%'/'%25'}"
GIT_COMMIT_MESSAGE="${GIT_COMMIT_MESSAGE//$'\n'/'%0A'}"
GIT_COMMIT_MESSAGE="${GIT_COMMIT_MESSAGE//$'\r'/'%0D'}"
echo "GIT_COMMIT_MESSAGE=$GIT_COMMIT_MESSAGE" >> $GITHUB_ENV
echo "GIT_COMMIT_MESSAGE is: ${GIT_COMMIT_MESSAGE}"
- name: Interpolate PR Body
uses: pedrolamas/handlebars-action@2995d7eadacbc8f2f6ab8431a01d84a5fa3b8bb4 # v2.4.0
uses: pedrolamas/handlebars-action@v2.0.0
with:
files: "pr_body.template"
output-filename: "pr_body.txt"
files: 'pr_body.template'
output-filename: 'pr_body.txt'
- name: Read pr_body.txt
id: pr_body
uses: juliangruber/read-file-action@v1
uses: andstor/file-reader-action@v1
with:
path: "pr_body.txt"
# We need to remove the pr_body files so that the
@ -202,16 +168,13 @@ runs:
run: rm -f pr_body.txt pr_body.template
- name: Create PR
id: create-pr
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5
uses: peter-evans/create-pull-request@v3
with:
base: ${{ inputs.base }}
branch: ${{ inputs.branch }}
delete-branch: true
committer: ${{ env.GIT_COMMITTER_NAME }} ${{ env.GIT_COMMITTER_EMAIL }}
author: ${{ env.GIT_AUTHOR_NAME }} ${{ env.GIT_AUTHOR_EMAIL }}
title: ${{ inputs.pr-title }}
token: ${{ inputs.token }}
assignees: ${{ inputs.pr-assignees }}
labels: ${{ inputs.pr-labels }}
reviewers: ${{ inputs.pr-reviewers }}
body: ${{ steps.pr_body.outputs.content }}
body: ${{ steps.pr_body.outputs.contents }}

2
dist/index.d.ts vendored
View file

@ -1,2 +0,0 @@
export { }

88703
dist/index.js vendored

File diff suppressed because one or more lines are too long

1
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

3
dist/package.json vendored
View file

@ -1,3 +0,0 @@
{
"type": "module"
}

View file

@ -2,16 +2,18 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1744232761,
"narHash": "sha256-gbl9hE39nQRpZaLjhWKmEu5ejtQsgI5TWYrIVVJn30U=",
"rev": "f675531bc7e6657c10a18b565cfebd8aa9e24c14",
"revCount": 781462,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.781462%2Brev-f675531bc7e6657c10a18b565cfebd8aa9e24c14/019624ad-56cd-7f8b-93ed-52e57165b6b6/source.tar.gz"
"lastModified": 1659131907,
"narHash": "sha256-8bz4k18M/FuVC+EVcI4aREN2PsEKT7LGmU2orfjnpCg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "8d435fca5c561da8168abb30270788d2da2a7951",
"type": "github"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz"
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {

View file

@ -1,23 +1,30 @@
{
description = "update-flake-lock";
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz";
inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
outputs = { self, nixpkgs }:
outputs =
{ self
, nixpkgs
}:
let
supportedSystems = [ "x86_64-linux" "aarch64-darwin" "aarch64-linux" "x86_64-darwin" ];
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
pkgs = import nixpkgs { inherit system; };
});
nameValuePair = name: value: { inherit name value; };
genAttrs = names: f: builtins.listToAttrs (map (n: nameValuePair n (f n)) names);
allSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
forAllSystems = f: genAttrs allSystems
(system: f {
inherit system;
pkgs = import nixpkgs { inherit system; };
});
in
{
devShells = forEachSupportedSystem ({ pkgs }: {
default = pkgs.mkShell {
packages = with pkgs; [
nodejs_latest
nodePackages_latest.pnpm
];
};
});
devShell = forAllSystems
({ system, pkgs, ... }:
pkgs.stdenv.mkDerivation {
name = "update-flake-lock-devshell";
buildInputs = [ pkgs.shellcheck ];
src = self;
});
};
}

View file

@ -1,47 +0,0 @@
{
"name": "update-flake-lock",
"version": "1.0.0",
"description": "",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"type": "module",
"scripts": {
"build": "tsup",
"format": "prettier --write .",
"check-fmt": "prettier --check .",
"lint": "eslint src/**/*.ts --ignore-pattern *.test.ts",
"package": "ncc build",
"test": "vitest --watch false",
"all": "pnpm run format && pnpm run lint && pnpm run build && pnpm run package"
},
"repository": {
"type": "git",
"url": "git+https://github.com/DeterminateSystems/update-flake-lock.git"
},
"keywords": [],
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/DeterminateSystems/update-flake-lock/issues"
},
"homepage": "https://github.com/DeterminateSystems/update-flake-lock#readme",
"dependencies": {
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"detsys-ts": "github:DeterminateSystems/detsys-ts"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@vercel/ncc": "^0.38.3",
"eslint": "^8.57.1",
"eslint-import-resolver-typescript": "^3.10.0",
"eslint-plugin-github": "^4.10.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-prettier": "^5.2.6",
"prettier": "^3.5.3",
"tsup": "^8.4.0",
"typescript": "^5.8.3",
"vitest": "^3.1.1"
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
/** @type {import('prettier').Config} */
module.exports = {
plugins: [require.resolve("@trivago/prettier-plugin-sort-imports")],
semi: true,
singleQuote: false,
tabWidth: 2,
trailingComma: "all",
useTabs: false,
// Import sorting
importOrderSeparation: true,
importOrderSortSpecifiers: true,
};

View file

@ -1,76 +0,0 @@
import { makeNixCommandArgs } from "./nix.js";
import * as actionsCore from "@actions/core";
import * as actionsExec from "@actions/exec";
import { DetSysAction, inputs } from "detsys-ts";
const EVENT_EXECUTION_FAILURE = "execution_failure";
class UpdateFlakeLockAction extends DetSysAction {
private commitMessage: string;
private nixOptions: string[];
private flakeInputs: string[];
private pathToFlakeDir: string | null;
constructor() {
super({
name: "update-flake-lock",
fetchStyle: "universal",
requireNix: "fail",
});
this.commitMessage = inputs.getString("commit-msg");
this.flakeInputs = inputs.getArrayOfStrings("inputs", "space");
this.nixOptions = inputs.getArrayOfStrings("nix-options", "space");
this.pathToFlakeDir = inputs.getStringOrNull("path-to-flake-dir");
}
async main(): Promise<void> {
await this.update();
}
// No post phase
async post(): Promise<void> {}
async update(): Promise<void> {
// Nix command of this form:
// nix ${maybe nix options} flake ${"update" or "lock"} ${maybe --update-input flags} --commit-lock-file --commit-lockfile-summary ${commit message}
// Example commands:
// nix --extra-substituters https://example.com flake lock --update-input nixpkgs --commit-lock-file --commit-lockfile-summary "updated flake.lock"
// nix flake update --commit-lock-file --commit-lockfile-summary "updated flake.lock"
const nixCommandArgs: string[] = makeNixCommandArgs(
this.nixOptions,
this.flakeInputs,
this.commitMessage,
);
actionsCore.debug(
JSON.stringify({
options: this.nixOptions,
inputs: this.flakeInputs,
message: this.commitMessage,
args: nixCommandArgs,
}),
);
const execOptions: actionsExec.ExecOptions = {
cwd: this.pathToFlakeDir !== null ? this.pathToFlakeDir : undefined,
};
const exitCode = await actionsExec.exec("nix", nixCommandArgs, execOptions);
if (exitCode !== 0) {
this.recordEvent(EVENT_EXECUTION_FAILURE, {
exitCode,
});
actionsCore.setFailed(`non-zero exit code of ${exitCode} detected`);
} else {
actionsCore.info(`flake.lock file was successfully updated`);
}
}
}
function main(): void {
new UpdateFlakeLockAction().execute();
}
main();

View file

@ -1,77 +0,0 @@
import { makeNixCommandArgs } from "./nix.js";
import { expect, test } from "vitest";
type TestCase = {
inputs: {
nixOptions: string[];
flakeInputs: string[];
commitMessage: string;
};
expected: string[];
};
test("Nix command arguments", () => {
const testCases: TestCase[] = [
{
inputs: {
nixOptions: ["--log-format", "raw"],
flakeInputs: [],
commitMessage: "just testing",
},
expected: [
"--log-format",
"raw",
"flake",
"update",
"--commit-lock-file",
"--option",
"commit-lockfile-summary",
"just testing",
],
},
{
inputs: {
nixOptions: [],
flakeInputs: ["nixpkgs", "rust-overlay"],
commitMessage: "just testing",
},
expected: [
"flake",
"lock",
"--update-input",
"nixpkgs",
"--update-input",
"rust-overlay",
"--commit-lock-file",
"--option",
"commit-lockfile-summary",
"just testing",
],
},
{
inputs: {
nixOptions: ["--debug"],
flakeInputs: [],
commitMessage: "just testing",
},
expected: [
"--debug",
"flake",
"update",
"--commit-lock-file",
"--option",
"commit-lockfile-summary",
"just testing",
],
},
];
testCases.forEach(({ inputs, expected }) => {
const args = makeNixCommandArgs(
inputs.nixOptions,
inputs.flakeInputs,
inputs.commitMessage,
);
expect(args).toStrictEqual(expected);
});
});

View file

@ -1,31 +0,0 @@
// Build the Nix args out of inputs from the Actions environment
export function makeNixCommandArgs(
nixOptions: string[],
flakeInputs: string[],
commitMessage: string,
): string[] {
const flakeInputFlags = flakeInputs.flatMap((input) => [
"--update-input",
input,
]);
// NOTE(cole-h): In Nix versions 2.23.0 and later, `commit-lockfile-summary` became an alias to
// the setting `commit-lock-file-summary` (https://github.com/NixOS/nix/pull/10691), and Nix does
// not treat aliases the same as their "real" setting by requiring setting aliases to be
// configured via `--option <alias name> <option value>`
// (https://github.com/NixOS/nix/issues/10989).
// So, we go the long way so that we can support versions both before and after Nix 2.23.0.
const lockfileSummaryFlags = [
"--option",
"commit-lockfile-summary",
commitMessage,
];
const updateLockMechanism = flakeInputFlags.length === 0 ? "update" : "lock";
return nixOptions
.concat(["flake", updateLockMechanism])
.concat(flakeInputFlags)
.concat(["--commit-lock-file"])
.concat(lockfileSummaryFlags);
}

View file

@ -1,15 +0,0 @@
{
"compilerOptions": {
"target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
"module": "Node16",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"rootDir": "./src",
"strict": true /* Enable all strict type-checking options. */,
"noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
"resolveJsonModule": true,
"declaration": true
},
"exclude": ["node_modules", "**/*.test.ts", "dist"]
}

View file

@ -1,16 +0,0 @@
import { name } from "./package.json";
import { defineConfig } from "tsup";
export default defineConfig({
name,
entry: ["src/index.ts"],
format: ["esm"],
target: "node20",
bundle: true,
splitting: false,
sourcemap: true,
clean: true,
dts: {
resolve: true,
},
});

16
update-flake-lock.sh Executable file
View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ -n "$PATH_TO_FLAKE_DIR" ]]; then
cd "$PATH_TO_FLAKE_DIR"
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"
else
nix flake update --commit-lock-file --commit-lockfile-summary "$COMMIT_MSG"
fi