mirror of
https://github.com/DeterminateSystems/update-flake-lock.git
synced 2024-12-23 13:32:07 +01:00
Merge pull request #101 from DeterminateSystems/detsys-ts
Convert the Action into TypeScript
This commit is contained in:
commit
bcabaab2f1
24 changed files with 99328 additions and 115 deletions
|
@ -1,15 +1,10 @@
|
||||||
# EditorConfig helps developers define and maintain consistent
|
# https://editorconfig.org
|
||||||
# coding styles between different editors and IDEs
|
|
||||||
# editorconfig.org
|
|
||||||
|
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
|
||||||
end_of_line = lf
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
|
||||||
[*.{yml,yaml}]
|
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
1
.envrc
Normal file
1
.envrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
use flake
|
73
.eslintrc.json
Normal file
73
.eslintrc.json
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
"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-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
|
||||||
|
}
|
||||||
|
}
|
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
|
@ -5,8 +5,8 @@ on:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
shellcheck:
|
typescript-action:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
@ -15,5 +15,19 @@ jobs:
|
||||||
uses: DeterminateSystems/nix-installer-action@main
|
uses: DeterminateSystems/nix-installer-action@main
|
||||||
- name: Enable magic Nix cache
|
- name: Enable magic Nix cache
|
||||||
uses: DeterminateSystems/magic-nix-cache-action@main
|
uses: DeterminateSystems/magic-nix-cache-action@main
|
||||||
- name: Shellcheck
|
- name: Install pnpm dependencies
|
||||||
run: nix-shell --run 'shellcheck $(find . -type f -name "*.sh" -executable)'
|
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
|
||||||
|
|
2
.github/workflows/update.yml
vendored
2
.github/workflows/update.yml
vendored
|
@ -2,7 +2,7 @@ name: update-flake-lock
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * 0'
|
- cron: "0 0 * * 0"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lockfile:
|
lockfile:
|
||||||
|
|
2
.github/workflows/validate.yml
vendored
2
.github/workflows/validate.yml
vendored
|
@ -6,7 +6,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validate:
|
validate:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# JS dependencies
|
||||||
|
node_modules/
|
5
.prettierignore
Normal file
5
.prettierignore
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
dist/
|
||||||
|
lib/
|
||||||
|
node_modules/
|
||||||
|
pnpm-lock.yaml
|
||||||
|
README.md
|
113
action.yml
113
action.yml
|
@ -1,35 +1,34 @@
|
||||||
name: 'Update Nix Flake Lock'
|
name: "Update Nix Flake Lock"
|
||||||
description: 'Update your Nix flake.lock and send a PR'
|
description: "Update your Nix flake.lock and send a PR"
|
||||||
inputs:
|
inputs:
|
||||||
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
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
token:
|
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
|
required: false
|
||||||
default: ${{ github.token }}
|
default: ${{ github.token }}
|
||||||
commit-msg:
|
commit-msg:
|
||||||
description: 'The message provided with the commit'
|
description: "The message provided with the commit"
|
||||||
required: false
|
required: false
|
||||||
default: "flake.lock: Update"
|
default: "flake.lock: Update"
|
||||||
base:
|
base:
|
||||||
description: "Sets the pull request base branch. Defaults to the branch checked out in the workflow."
|
description: "Sets the pull request base branch. Defaults to the branch checked out in the workflow."
|
||||||
required: false
|
required: false
|
||||||
branch:
|
branch:
|
||||||
description: 'The branch of the PR to be created'
|
description: "The branch of the PR to be created"
|
||||||
required: false
|
required: false
|
||||||
default: "update_flake_lock_action"
|
default: "update_flake_lock_action"
|
||||||
path-to-flake-dir:
|
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
|
required: false
|
||||||
default: ''
|
|
||||||
pr-title:
|
pr-title:
|
||||||
description: 'The title of the PR to be created'
|
description: "The title of the PR to be created"
|
||||||
required: false
|
required: false
|
||||||
default: "flake.lock: Update"
|
default: "flake.lock: Update"
|
||||||
pr-body:
|
pr-body:
|
||||||
description: 'The body of the PR to be created'
|
description: "The body of the PR to be created"
|
||||||
required: false
|
required: false
|
||||||
default: |
|
default: |
|
||||||
Automated changes by the [update-flake-lock](https://github.com/DeterminateSystems/update-flake-lock) GitHub Action.
|
Automated changes by the [update-flake-lock](https://github.com/DeterminateSystems/update-flake-lock) GitHub Action.
|
||||||
|
@ -53,58 +52,58 @@ inputs:
|
||||||
```
|
```
|
||||||
|
|
||||||
pr-labels:
|
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
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
pr-assignees:
|
pr-assignees:
|
||||||
description: 'A comma or newline separated list of assignees (GitHub usernames).'
|
description: "A comma or newline separated list of assignees (GitHub usernames)."
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
pr-reviewers:
|
pr-reviewers:
|
||||||
description: 'A comma or newline separated list of reviewers (GitHub usernames) to request a review from.'
|
description: "A comma or newline separated list of reviewers (GitHub usernames) to request a review from."
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
git-author-name:
|
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
|
required: false
|
||||||
default: 'github-actions[bot]'
|
default: "github-actions[bot]"
|
||||||
git-author-email:
|
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
|
required: false
|
||||||
default: 'github-actions[bot]@users.noreply.github.com'
|
default: "github-actions[bot]@users.noreply.github.com"
|
||||||
git-committer-name:
|
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
|
required: false
|
||||||
default: 'github-actions[bot]'
|
default: "github-actions[bot]"
|
||||||
git-committer-email:
|
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
|
required: false
|
||||||
default: 'github-actions[bot]@users.noreply.github.com'
|
default: "github-actions[bot]@users.noreply.github.com"
|
||||||
sign-commits:
|
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
|
required: false
|
||||||
default: 'false'
|
default: "false"
|
||||||
gpg-private-key:
|
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
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
gpg-fingerprint:
|
gpg-fingerprint:
|
||||||
description: 'Fingerprint of specific GPG subkey to use'
|
description: "Fingerprint of specific GPG subkey to use"
|
||||||
required: false
|
required: false
|
||||||
gpg-passphrase:
|
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
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
nix-options:
|
nix-options:
|
||||||
description: 'A space-separated list of options to pass to the nix command'
|
description: "A space-separated list of options to pass to the nix command"
|
||||||
required: false
|
required: false
|
||||||
default: ''
|
default: ""
|
||||||
outputs:
|
outputs:
|
||||||
pull-request-number:
|
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 }}
|
value: ${{ steps.create-pr.outputs.pull-request-number }}
|
||||||
pull-request-operation:
|
pull-request-operation:
|
||||||
description: 'The pull request operation performed by the action, `created`, `updated` or `closed`.'
|
description: "The pull request operation performed by the action, `created`, `updated` or `closed`."
|
||||||
value: ${{ steps.create-pr.outputs.pull-request-operation }}
|
value: ${{ steps.create-pr.outputs.pull-request-operation }}
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
|
@ -115,7 +114,7 @@ runs:
|
||||||
uses: crazy-max/ghaction-import-gpg@v6
|
uses: crazy-max/ghaction-import-gpg@v6
|
||||||
with:
|
with:
|
||||||
gpg_private_key: ${{ inputs.gpg-private-key }}
|
gpg_private_key: ${{ inputs.gpg-private-key }}
|
||||||
fingerprint: ${{ inputs.gpg-fingerprint }}
|
fingerprint: ${{ inputs.gpg-fingerprint }}
|
||||||
passphrase: ${{ inputs.gpg-passphrase }}
|
passphrase: ${{ inputs.gpg-passphrase }}
|
||||||
git_config_global: true
|
git_config_global: true
|
||||||
git_user_signingkey: true
|
git_user_signingkey: true
|
||||||
|
@ -142,18 +141,34 @@ runs:
|
||||||
echo "GIT_AUTHOR_EMAIL=<${{ inputs.git-author-email }}>" >> $GITHUB_ENV
|
echo "GIT_AUTHOR_EMAIL=<${{ inputs.git-author-email }}>" >> $GITHUB_ENV
|
||||||
echo "GIT_COMMITTER_NAME=${{ inputs.git-committer-name }}" >> $GITHUB_ENV
|
echo "GIT_COMMITTER_NAME=${{ inputs.git-committer-name }}" >> $GITHUB_ENV
|
||||||
echo "GIT_COMMITTER_EMAIL=<${{ inputs.git-committer-email }}>" >> $GITHUB_ENV
|
echo "GIT_COMMITTER_EMAIL=<${{ inputs.git-committer-email }}>" >> $GITHUB_ENV
|
||||||
- name: Run update-flake-lock.sh
|
- name: Run update-flake-lock
|
||||||
run: $GITHUB_ACTION_PATH/update-flake-lock.sh
|
|
||||||
shell: bash
|
shell: bash
|
||||||
|
run: node "$GITHUB_ACTION_PATH/dist/index.js"
|
||||||
env:
|
env:
|
||||||
GIT_AUTHOR_NAME: ${{ env.GIT_AUTHOR_NAME }}
|
# The following manually exposes all of the action inputs into INPUT_ environment variables so actionsCore.getInput works:
|
||||||
GIT_AUTHOR_EMAIL: ${{ env.GIT_AUTHOR_EMAIL }}
|
# https://github.com/actions/toolkit/blob/ae38557bb0dba824cdda26ce787bd6b66cf07a83/packages/core/src/core.ts#L126
|
||||||
GIT_COMMITTER_NAME: ${{ env.GIT_COMMITTER_NAME }}
|
INPUT_BASE: ${{ inputs.base }}
|
||||||
GIT_COMMITTER_EMAIL: ${{ env.GIT_COMMITTER_EMAIL }}
|
INPUT_BRANCH: ${{ inputs.branch }}
|
||||||
NIX_OPTIONS: ${{ inputs.nix-options }}
|
INPUT_COMMIT-MSG: ${{ inputs.commit-msg }}
|
||||||
TARGETS: ${{ inputs.inputs }}
|
INPUT_GIT-AUTHOR-EMAIL: ${{ inputs.git-author-email }}
|
||||||
COMMIT_MSG: ${{ inputs.commit-msg }}
|
INPUT_GIT-AUTHOR-NAME: ${{ inputs.git-author-name }}
|
||||||
PATH_TO_FLAKE_DIR: ${{ inputs.path-to-flake-dir }}
|
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 }}
|
||||||
- name: Save PR Body as file
|
- name: Save PR Body as file
|
||||||
uses: DamianReeves/write-file-action@v1.3
|
uses: DamianReeves/write-file-action@v1.3
|
||||||
with:
|
with:
|
||||||
|
@ -172,8 +187,8 @@ runs:
|
||||||
- name: Interpolate PR Body
|
- name: Interpolate PR Body
|
||||||
uses: pedrolamas/handlebars-action@v2.4.0
|
uses: pedrolamas/handlebars-action@v2.4.0
|
||||||
with:
|
with:
|
||||||
files: 'pr_body.template'
|
files: "pr_body.template"
|
||||||
output-filename: 'pr_body.txt'
|
output-filename: "pr_body.txt"
|
||||||
- name: Read pr_body.txt
|
- name: Read pr_body.txt
|
||||||
id: pr_body
|
id: pr_body
|
||||||
uses: juliangruber/read-file-action@v1
|
uses: juliangruber/read-file-action@v1
|
||||||
|
|
2
dist/index.d.ts
vendored
Normal file
2
dist/index.d.ts
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
export { }
|
94395
dist/index.js
vendored
Normal file
94395
dist/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/index.js.map
vendored
Normal file
1
dist/index.js.map
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"sources":["../src/nix.ts","../src/index.ts"],"sourcesContent":["// Build the Nix args out of inputs from the Actions environment\nexport function makeNixCommandArgs(\n nixOptions: string[],\n flakeInputs: string[],\n commitMessage: string,\n): string[] {\n const flakeInputFlags = flakeInputs.flatMap((input) => [\n \"--update-input\",\n input,\n ]);\n\n const updateLockMechanism = flakeInputFlags.length === 0 ? \"update\" : \"lock\";\n\n return nixOptions\n .concat([\"flake\", updateLockMechanism])\n .concat(flakeInputFlags)\n .concat([\"--commit-lock-file\", \"--commit-lockfile-summary\", commitMessage]);\n}\n","import { makeNixCommandArgs } from \"./nix.js\";\nimport * as actionsCore from \"@actions/core\";\nimport * as actionsExec from \"@actions/exec\";\nimport { ActionOptions, IdsToolbox, inputs } from \"detsys-ts\";\n\nconst EVENT_EXECUTION_FAILURE = \"execution_failure\";\n\nclass UpdateFlakeLockAction {\n idslib: IdsToolbox;\n private commitMessage: string;\n private nixOptions: string[];\n private flakeInputs: string[];\n private pathToFlakeDir: string | null;\n\n constructor() {\n const options: ActionOptions = {\n name: \"update-flake-lock\",\n fetchStyle: \"universal\",\n requireNix: \"fail\",\n };\n\n this.idslib = new IdsToolbox(options);\n this.commitMessage = inputs.getString(\"commit-msg\");\n this.flakeInputs = inputs.getArrayOfStrings(\"inputs\", \"comma\");\n this.nixOptions = inputs.getArrayOfStrings(\"nix-options\", \"space\");\n this.pathToFlakeDir = inputs.getStringOrNull(\"path-to-flake-dir\");\n }\n\n async update(): Promise<void> {\n // Nix command of this form:\n // nix ${maybe nix options} flake ${\"update\" or \"lock\"} ${maybe --update-input flags} --commit-lock-file --commit-lockfile-summary ${commit message}\n // Example commands:\n // nix --extra-substituters https://example.com flake lock --update-input nixpkgs --commit-lock-file --commit-lockfile-summary \"updated flake.lock\"\n // nix flake update --commit-lock-file --commit-lockfile-summary \"updated flake.lock\"\n const nixCommandArgs: string[] = makeNixCommandArgs(\n this.nixOptions,\n this.flakeInputs,\n this.commitMessage,\n );\n\n actionsCore.debug(\n JSON.stringify({\n options: this.nixOptions,\n inputs: this.flakeInputs,\n message: this.commitMessage,\n args: nixCommandArgs,\n }),\n );\n\n const execOptions: actionsExec.ExecOptions = {};\n if (this.pathToFlakeDir !== null) {\n execOptions.cwd = this.pathToFlakeDir;\n }\n\n const exitCode = await actionsExec.exec(\"nix\", nixCommandArgs, execOptions);\n\n if (exitCode !== 0) {\n this.idslib.recordEvent(EVENT_EXECUTION_FAILURE, {\n exitCode,\n });\n actionsCore.setFailed(`non-zero exit code of ${exitCode} detected`);\n } else {\n actionsCore.info(`flake.lock file was successfully updated`);\n }\n }\n}\n\nfunction main(): void {\n const updateFlakeLock = new UpdateFlakeLockAction();\n\n updateFlakeLock.idslib.onMain(async () => {\n await updateFlakeLock.update();\n });\n\n updateFlakeLock.idslib.execute();\n}\n\nmain();\n"],"mappings":";AACO,SAAS,mBACd,YACA,aACA,eACU;AACV,QAAM,kBAAkB,YAAY,QAAQ,CAAC,UAAU;AAAA,IACrD;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,sBAAsB,gBAAgB,WAAW,IAAI,WAAW;AAEtE,SAAO,WACJ,OAAO,CAAC,SAAS,mBAAmB,CAAC,EACrC,OAAO,eAAe,EACtB,OAAO,CAAC,sBAAsB,6BAA6B,aAAa,CAAC;AAC9E;;;AChBA,YAAY,iBAAiB;AAC7B,YAAY,iBAAiB;AAC7B,SAAwB,YAAY,cAAc;AAElD,IAAM,0BAA0B;AAEhC,IAAM,wBAAN,MAA4B;AAAA,EAO1B,cAAc;AACZ,UAAM,UAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,YAAY;AAAA,IACd;AAEA,SAAK,SAAS,IAAI,WAAW,OAAO;AACpC,SAAK,gBAAgB,OAAO,UAAU,YAAY;AAClD,SAAK,cAAc,OAAO,kBAAkB,UAAU,OAAO;AAC7D,SAAK,aAAa,OAAO,kBAAkB,eAAe,OAAO;AACjE,SAAK,iBAAiB,OAAO,gBAAgB,mBAAmB;AAAA,EAClE;AAAA,EAEA,MAAM,SAAwB;AAM5B,UAAM,iBAA2B;AAAA,MAC/B,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAEA,IAAY;AAAA,MACV,KAAK,UAAU;AAAA,QACb,SAAS,KAAK;AAAA,QACd,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAEA,UAAM,cAAuC,CAAC;AAC9C,QAAI,KAAK,mBAAmB,MAAM;AAChC,kBAAY,MAAM,KAAK;AAAA,IACzB;AAEA,UAAM,WAAW,MAAkB,iBAAK,OAAO,gBAAgB,WAAW;AAE1E,QAAI,aAAa,GAAG;AAClB,WAAK,OAAO,YAAY,yBAAyB;AAAA,QAC/C;AAAA,MACF,CAAC;AACD,MAAY,sBAAU,yBAAyB,QAAQ,WAAW;AAAA,IACpE,OAAO;AACL,MAAY,iBAAK,0CAA0C;AAAA,IAC7D;AAAA,EACF;AACF;AAEA,SAAS,OAAa;AACpB,QAAM,kBAAkB,IAAI,sBAAsB;AAElD,kBAAgB,OAAO,OAAO,YAAY;AACxC,UAAM,gBAAgB,OAAO;AAAA,EAC/B,CAAC;AAED,kBAAgB,OAAO,QAAQ;AACjC;AAEA,KAAK;","names":[]}
|
3
dist/package.json
vendored
Normal file
3
dist/package.json
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
12
flake.lock
12
flake.lock
|
@ -2,16 +2,16 @@
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1696604326,
|
"lastModified": 1713537308,
|
||||||
"narHash": "sha256-YXUNI0kLEcI5g8lqGMb0nh67fY9f2YoJsILafh6zlMo=",
|
"narHash": "sha256-XtTSSIB2DA6tOv+l0FhvfDMiyCmhoRbNB+0SeInZkbk=",
|
||||||
"rev": "87828a0e03d1418e848d3dd3f3014a632e4a4f64",
|
"rev": "5c24cf2f0a12ad855f444c30b2421d044120c66f",
|
||||||
"revCount": 533189,
|
"revCount": 614481,
|
||||||
"type": "tarball",
|
"type": "tarball",
|
||||||
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.533189%2Brev-87828a0e03d1418e848d3dd3f3014a632e4a4f64/018b0dc8-e84f-7c59-b5d6-16849c3b2074/source.tar.gz"
|
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.614481%2Brev-5c24cf2f0a12ad855f444c30b2421d044120c66f/018efa00-a443-7f41-b371-ce568b5c7e9f/source.tar.gz"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"type": "tarball",
|
"type": "tarball",
|
||||||
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.533189.tar.gz"
|
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
|
|
29
flake.nix
29
flake.nix
|
@ -1,30 +1,23 @@
|
||||||
{
|
{
|
||||||
description = "update-flake-lock";
|
description = "update-flake-lock";
|
||||||
|
|
||||||
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.533189.tar.gz";
|
inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz";
|
||||||
|
|
||||||
outputs =
|
outputs = { self, nixpkgs }:
|
||||||
{ self
|
|
||||||
, nixpkgs
|
|
||||||
}:
|
|
||||||
let
|
let
|
||||||
nameValuePair = name: value: { inherit name value; };
|
supportedSystems = [ "x86_64-linux" "aarch64-darwin" "aarch64-linux" "x86_64-darwin" ];
|
||||||
genAttrs = names: f: builtins.listToAttrs (map (n: nameValuePair n (f n)) names);
|
forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f {
|
||||||
|
|
||||||
allSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
|
|
||||||
forAllSystems = f: genAttrs allSystems
|
|
||||||
(system: f {
|
|
||||||
inherit system;
|
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
});
|
});
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
devShell = forAllSystems
|
devShells = forEachSupportedSystem ({ pkgs }: {
|
||||||
({ system, pkgs, ... }:
|
default = pkgs.mkShell {
|
||||||
pkgs.stdenv.mkDerivation {
|
packages = with pkgs; [
|
||||||
name = "update-flake-lock-devshell";
|
nodejs_latest
|
||||||
buildInputs = [ pkgs.shellcheck ];
|
nodePackages_latest.pnpm
|
||||||
src = self;
|
];
|
||||||
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
47
package.json
Normal file
47
package.json
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
{
|
||||||
|
"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.10.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.8.0",
|
||||||
|
"@vercel/ncc": "^0.38.1",
|
||||||
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-import-resolver-typescript": "^3.6.1",
|
||||||
|
"eslint-plugin-github": "^4.10.2",
|
||||||
|
"eslint-plugin-import": "^2.29.1",
|
||||||
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
|
"prettier": "^3.2.5",
|
||||||
|
"tsup": "^8.0.2",
|
||||||
|
"typescript": "^5.4.5",
|
||||||
|
"vitest": "^1.6.0"
|
||||||
|
}
|
||||||
|
}
|
4477
pnpm-lock.yaml
Normal file
4477
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
12
prettier.config.cjs
Normal file
12
prettier.config.cjs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/** @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,
|
||||||
|
};
|
78
src/index.ts
Normal file
78
src/index.ts
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
import { makeNixCommandArgs } from "./nix.js";
|
||||||
|
import * as actionsCore from "@actions/core";
|
||||||
|
import * as actionsExec from "@actions/exec";
|
||||||
|
import { ActionOptions, IdsToolbox, inputs } from "detsys-ts";
|
||||||
|
|
||||||
|
const EVENT_EXECUTION_FAILURE = "execution_failure";
|
||||||
|
|
||||||
|
class UpdateFlakeLockAction {
|
||||||
|
idslib: IdsToolbox;
|
||||||
|
private commitMessage: string;
|
||||||
|
private nixOptions: string[];
|
||||||
|
private flakeInputs: string[];
|
||||||
|
private pathToFlakeDir: string | null;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
const options: ActionOptions = {
|
||||||
|
name: "update-flake-lock",
|
||||||
|
fetchStyle: "universal",
|
||||||
|
requireNix: "fail",
|
||||||
|
};
|
||||||
|
|
||||||
|
this.idslib = new IdsToolbox(options);
|
||||||
|
this.commitMessage = inputs.getString("commit-msg");
|
||||||
|
this.flakeInputs = inputs.getArrayOfStrings("inputs", "comma");
|
||||||
|
this.nixOptions = inputs.getArrayOfStrings("nix-options", "space");
|
||||||
|
this.pathToFlakeDir = inputs.getStringOrNull("path-to-flake-dir");
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = {};
|
||||||
|
if (this.pathToFlakeDir !== null) {
|
||||||
|
execOptions.cwd = this.pathToFlakeDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
const exitCode = await actionsExec.exec("nix", nixCommandArgs, execOptions);
|
||||||
|
|
||||||
|
if (exitCode !== 0) {
|
||||||
|
this.idslib.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 {
|
||||||
|
const updateFlakeLock = new UpdateFlakeLockAction();
|
||||||
|
|
||||||
|
updateFlakeLock.idslib.onMain(async () => {
|
||||||
|
await updateFlakeLock.update();
|
||||||
|
});
|
||||||
|
|
||||||
|
updateFlakeLock.idslib.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
74
src/nix.test.ts
Normal file
74
src/nix.test.ts
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
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",
|
||||||
|
"--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",
|
||||||
|
"--commit-lockfile-summary",
|
||||||
|
"just testing",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
inputs: {
|
||||||
|
nixOptions: ["--debug"],
|
||||||
|
flakeInputs: [],
|
||||||
|
commitMessage: "just testing",
|
||||||
|
},
|
||||||
|
expected: [
|
||||||
|
"--debug",
|
||||||
|
"flake",
|
||||||
|
"update",
|
||||||
|
"--commit-lock-file",
|
||||||
|
"--commit-lockfile-summary",
|
||||||
|
"just testing",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
testCases.forEach(({ inputs, expected }) => {
|
||||||
|
const args = makeNixCommandArgs(
|
||||||
|
inputs.nixOptions,
|
||||||
|
inputs.flakeInputs,
|
||||||
|
inputs.commitMessage,
|
||||||
|
);
|
||||||
|
expect(args).toStrictEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
18
src/nix.ts
Normal file
18
src/nix.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// 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,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const updateLockMechanism = flakeInputFlags.length === 0 ? "update" : "lock";
|
||||||
|
|
||||||
|
return nixOptions
|
||||||
|
.concat(["flake", updateLockMechanism])
|
||||||
|
.concat(flakeInputFlags)
|
||||||
|
.concat(["--commit-lock-file", "--commit-lockfile-summary", commitMessage]);
|
||||||
|
}
|
15
tsconfig.json
Normal file
15
tsconfig.json
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"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"]
|
||||||
|
}
|
16
tsup.config.ts
Normal file
16
tsup.config.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,23 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [[ -n "$PATH_TO_FLAKE_DIR" ]]; then
|
|
||||||
cd "$PATH_TO_FLAKE_DIR"
|
|
||||||
fi
|
|
||||||
|
|
||||||
options=()
|
|
||||||
if [[ -n "$NIX_OPTIONS" ]]; then
|
|
||||||
for option in $NIX_OPTIONS; do
|
|
||||||
options+=("${option}")
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$TARGETS" ]]; then
|
|
||||||
inputs=()
|
|
||||||
for input in $TARGETS; do
|
|
||||||
inputs+=("--update-input" "$input")
|
|
||||||
done
|
|
||||||
nix "${options[@]}" flake lock "${inputs[@]}" --commit-lock-file --commit-lockfile-summary "$COMMIT_MSG"
|
|
||||||
else
|
|
||||||
nix "${options[@]}" flake update --commit-lock-file --commit-lockfile-summary "$COMMIT_MSG"
|
|
||||||
fi
|
|
Loading…
Reference in a new issue