From c1fdf8ab673f4b4847c87ef0dce594052a31c1b5 Mon Sep 17 00:00:00 2001 From: fym998 <61316972+fym998@users.noreply.github.com> Date: Sun, 27 Jul 2025 22:13:30 +0800 Subject: [PATCH 1/4] Use `nix flake update [inputs...]` --- src/index.ts | 5 +++-- src/nix.ts | 10 ++-------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/index.ts b/src/index.ts index fd80134..dcd674b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,6 +3,7 @@ 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 { @@ -33,9 +34,9 @@ class UpdateFlakeLockAction extends DetSysAction { async update(): Promise { // 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} + // nix ${maybe nix options} flake update ${maybe inputs} --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 --extra-substituters https://example.com flake update 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, diff --git a/src/nix.ts b/src/nix.ts index e3d829a..042b0e1 100644 --- a/src/nix.ts +++ b/src/nix.ts @@ -4,10 +4,6 @@ export function makeNixCommandArgs( 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 @@ -21,11 +17,9 @@ export function makeNixCommandArgs( commitMessage, ]; - const updateLockMechanism = flakeInputFlags.length === 0 ? "update" : "lock"; - return nixOptions - .concat(["flake", updateLockMechanism]) - .concat(flakeInputFlags) + .concat(["flake", "update"]) + .concat(flakeInputs) .concat(["--commit-lock-file"]) .concat(lockfileSummaryFlags); } From 2cbe601b3b63ccc458ffef5dcbd0b5d67d2d92e7 Mon Sep 17 00:00:00 2001 From: fym998 <61316972+fym998@users.noreply.github.com> Date: Thu, 31 Jul 2025 11:49:33 +0800 Subject: [PATCH 2/4] feat: Add multiple flakes support --- action.yml | 22 ++++++++++---- src/index.ts | 78 +++++++++++++++++++++++++++---------------------- src/nix.test.ts | 26 ++++++++++++++--- src/nix.ts | 13 ++++----- 4 files changed, 88 insertions(+), 51 deletions(-) diff --git a/action.yml b/action.yml index 2ed0d92..0726c6c 100644 --- a/action.yml +++ b/action.yml @@ -5,6 +5,10 @@ inputs: description: "A space-separated list of inputs to update. Leave empty to update all inputs." required: false default: "" + flakes: + description: "Flakes to update, one per line. If not provided, the action will look for a `flake.nix` file in the root of the repository." + required: false + default: "" token: description: "GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT)" required: false @@ -12,7 +16,6 @@ inputs: commit-msg: 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 @@ -33,9 +36,7 @@ inputs: default: | 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 @@ -140,6 +141,10 @@ 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: Get pre-update commit hash + id: pre-update + shell: bash + run: echo "value=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT - name: Run update-flake-lock shell: bash run: node "$GITHUB_ACTION_PATH/dist/index.js" @@ -149,6 +154,7 @@ runs: INPUT_BASE: ${{ inputs.base }} INPUT_BRANCH: ${{ inputs.branch }} INPUT_COMMIT-MSG: ${{ inputs.commit-msg }} + INPUT_FLAKES: ${{ inputs.flakes }} INPUT_GIT-AUTHOR-EMAIL: ${{ inputs.git-author-email }} INPUT_GIT-AUTHOR-NAME: ${{ inputs.git-author-name }} INPUT_GIT-COMMITTER-EMAIL: ${{ inputs.git-committer-email }} @@ -179,11 +185,17 @@ runs: shell: bash run: | DELIMITER=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) - COMMIT_MESSAGE="$(git log --format=%b -n 1)" + COMMIT_MESSAGE=$(git log --pretty=format:"\`\`\`\ + + %B\ + \`\`\`\ + + " ${{ steps.pre-update.outputs.value }}..HEAD) echo "GIT_COMMIT_MESSAGE<<$DELIMITER" >> $GITHUB_ENV echo "$COMMIT_MESSAGE" >> $GITHUB_ENV echo "$DELIMITER" >> $GITHUB_ENV - echo "GIT_COMMIT_MESSAGE is: ${COMMIT_MESSAGE}" + echo "GIT_COMMIT_MESSAGE is:" + echo "${COMMIT_MESSAGE}" - name: Interpolate PR Body uses: pedrolamas/handlebars-action@2995d7eadacbc8f2f6ab8431a01d84a5fa3b8bb4 # v2.4.0 with: diff --git a/src/index.ts b/src/index.ts index dcd674b..186204a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,14 +3,13 @@ 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 commitMessage: string | null; private nixOptions: string[]; private flakeInputs: string[]; - private pathToFlakeDir: string | null; + private flakes: string[]; constructor() { super({ @@ -19,10 +18,12 @@ class UpdateFlakeLockAction extends DetSysAction { requireNix: "fail", }); - this.commitMessage = inputs.getString("commit-msg"); + this.commitMessage = inputs.getStringOrNull("commit-msg"); this.flakeInputs = inputs.getArrayOfStrings("inputs", "space"); this.nixOptions = inputs.getArrayOfStrings("nix-options", "space"); - this.pathToFlakeDir = inputs.getStringOrNull("path-to-flake-dir"); + this.flakes = actionsCore + .getMultilineInput("flakes") + .concat(inputs.getStringOrNull("path-to-flake-dir") ?? []); } async main(): Promise { @@ -33,40 +34,47 @@ class UpdateFlakeLockAction extends DetSysAction { async post(): Promise {} async update(): Promise { - // Nix command of this form: - // nix ${maybe nix options} flake update ${maybe inputs} --commit-lock-file --commit-lockfile-summary ${commit message} - // Example commands: - // nix --extra-substituters https://example.com flake update 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, - ); + for (const flake of this.flakes.length > 0 ? this.flakes : [null]) { + // Nix command of this form: + // nix ${maybe nix options} flake update ${maybe --flake flake} ${maybe inputs} --commit-lock-file ${maybe --commit-lockfile-summary commit message} + // Example commands: + // nix --extra-substituters https://example.com flake update nixpkgs --commit-lock-file --commit-lockfile-summary "updated flake.lock" + // nix flake update --flake flake-dir/ --commit-lock-file + const nixCommandArgs: string[] = makeNixCommandArgs( + this.nixOptions, + flake, + this.flakeInputs, + this.commitMessage, + ); - actionsCore.debug( - JSON.stringify({ - options: this.nixOptions, - inputs: this.flakeInputs, - message: this.commitMessage, - args: nixCommandArgs, - }), - ); + actionsCore.debug( + JSON.stringify({ + options: this.nixOptions, + flake, + inputs: this.flakeInputs, + message: this.commitMessage, + args: nixCommandArgs, + }), + ); - const execOptions: actionsExec.ExecOptions = { - cwd: this.pathToFlakeDir !== null ? this.pathToFlakeDir : undefined, - ignoreReturnCode: true, - }; + const execOptions: actionsExec.ExecOptions = { + ignoreReturnCode: true, + }; - const exitCode = await actionsExec.exec("nix", nixCommandArgs, execOptions); + 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`); + 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`); + } } } } diff --git a/src/nix.test.ts b/src/nix.test.ts index ebc7640..b2fa869 100644 --- a/src/nix.test.ts +++ b/src/nix.test.ts @@ -4,17 +4,34 @@ import { expect, test } from "vitest"; type TestCase = { inputs: { nixOptions: string[]; + flake: string | null; flakeInputs: string[]; - commitMessage: string; + commitMessage: string | null; }; expected: string[]; }; test("Nix command arguments", () => { const testCases: TestCase[] = [ + { + inputs: { + nixOptions: [], + flake: "flake-url", + flakeInputs: [], + commitMessage: null, + }, + expected: [ + "flake", + "update", + "--flake", + "flake-url", + "--commit-lock-file", + ], + }, { inputs: { nixOptions: ["--log-format", "raw"], + flake: null, flakeInputs: [], commitMessage: "just testing", }, @@ -32,15 +49,14 @@ test("Nix command arguments", () => { { inputs: { nixOptions: [], + flake: null, flakeInputs: ["nixpkgs", "rust-overlay"], commitMessage: "just testing", }, expected: [ "flake", - "lock", - "--update-input", + "update", "nixpkgs", - "--update-input", "rust-overlay", "--commit-lock-file", "--option", @@ -51,6 +67,7 @@ test("Nix command arguments", () => { { inputs: { nixOptions: ["--debug"], + flake: null, flakeInputs: [], commitMessage: "just testing", }, @@ -69,6 +86,7 @@ test("Nix command arguments", () => { testCases.forEach(({ inputs, expected }) => { const args = makeNixCommandArgs( inputs.nixOptions, + inputs.flake, inputs.flakeInputs, inputs.commitMessage, ); diff --git a/src/nix.ts b/src/nix.ts index 042b0e1..c32795d 100644 --- a/src/nix.ts +++ b/src/nix.ts @@ -1,24 +1,23 @@ // Build the Nix args out of inputs from the Actions environment export function makeNixCommandArgs( nixOptions: string[], + flake: string | null, flakeInputs: string[], - commitMessage: string, + commitMessage: string | null, ): string[] { - // 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