diff --git a/action.yml b/action.yml index 706709a..972047d 100644 --- a/action.yml +++ b/action.yml @@ -9,6 +9,12 @@ inputs: description: "GITHUB_TOKEN or a `repo` scoped Personal Access Token (PAT)" required: false default: ${{ github.token }} + commit-msg-template: + description: | + The commit message template to use. Variable: `flake_input`. + required: false + default: | + flake.lock: Updated {{ flake_input }} commit-msg: description: "The message provided with the commit" required: false diff --git a/package.json b/package.json index c707b74..2b10f3b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,8 @@ "dependencies": { "@actions/core": "^1.10.1", "@actions/exec": "^1.1.1", - "detsys-ts": "github:DeterminateSystems/detsys-ts" + "detsys-ts": "github:DeterminateSystems/detsys-ts", + "handlebars": "^4.7.8" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2559c91..c9e2618 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ dependencies: detsys-ts: specifier: github:DeterminateSystems/detsys-ts version: github.com/DeterminateSystems/detsys-ts/fe64ba33b4bdeec0991bb65ae00420bf68b9954c + handlebars: + specifier: ^4.7.8 + version: 4.7.8 devDependencies: '@trivago/prettier-plugin-sort-imports': @@ -2680,6 +2683,19 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: false + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} dev: true @@ -3229,7 +3245,6 @@ packages: /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: true /minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} @@ -3271,6 +3286,10 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + /node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -3802,6 +3821,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: false + /source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} @@ -4154,6 +4178,14 @@ packages: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} dev: true + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -4407,6 +4439,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} diff --git a/src/index.ts b/src/index.ts index 3871ac8..fbb0fa1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import { makeNixCommandArgs } from "./nix.js"; +import { renderCommitMessage } from "./template.js"; import * as actionsCore from "@actions/core"; import * as actionsExec from "@actions/exec"; import { DetSysAction, inputs } from "detsys-ts"; @@ -12,6 +13,7 @@ const EVENT_EXECUTION_FAILURE = "execution_failure"; class UpdateFlakeLockAction extends DetSysAction { private commitMessage: string; + private commitMessageTemplate: string; private nixOptions: string[]; private flakeInputs: string[]; private pathToFlakeDir: string | null; @@ -26,6 +28,7 @@ class UpdateFlakeLockAction extends DetSysAction { }); this.commitMessage = inputs.getString("commit-msg"); + this.commitMessageTemplate = inputs.getString("commit-msg-template"); this.flakeInputs = inputs.getArrayOfStrings("inputs", "space"); this.nixOptions = inputs.getArrayOfStrings("nix-options", "space"); this.pathToFlakeDir = inputs.getStringOrNull("path-to-flake-dir"); @@ -57,6 +60,12 @@ class UpdateFlakeLockAction extends DetSysAction { actionsCore.debug(`Running flake lock update in directory \`${flakeDir}\``); + const flakeDotLock = `${flakeDir}/flake.lock`; + const commitMessage = + this.commitMessage !== "" + ? this.commitMessage + : renderCommitMessage(this.commitMessageTemplate, flakeDotLock); + // 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: @@ -65,7 +74,7 @@ class UpdateFlakeLockAction extends DetSysAction { const nixCommandArgs: string[] = makeNixCommandArgs( this.nixOptions, this.flakeInputs, - this.commitMessage, + commitMessage, ); actionsCore.debug( diff --git a/src/template.test.ts b/src/template.test.ts new file mode 100644 index 0000000..e586d64 --- /dev/null +++ b/src/template.test.ts @@ -0,0 +1,31 @@ +import { renderCommitMessage } from "./template.js"; +import { describe, expect, test } from "vitest"; + +describe("templating", () => { + test("commit message", () => { + type TestCase = { + template: string; + flakeDotLock: string; + expected: string; + }; + + const testCases: TestCase[] = [ + { + template: "Updating lockfile at {{ flake_dot_lock }}", + flakeDotLock: "./flake.lock", + expected: "Updating lockfile at ./flake.lock", + }, + { + template: + "Here I go doing some updating of my pristine flake.lock at {{ flake_dot_lock }}", + flakeDotLock: "subflake/flake.lock", + expected: + "Here I go doing some updating of my pristine flake.lock at subflake/flake.lock", + }, + ]; + + testCases.forEach(({ template, flakeDotLock, expected }) => { + expect(renderCommitMessage(template, flakeDotLock)).toEqual(expected); + }); + }); +}); diff --git a/src/template.ts b/src/template.ts new file mode 100644 index 0000000..a50c68c --- /dev/null +++ b/src/template.ts @@ -0,0 +1,13 @@ +import Handlebars from "handlebars"; + +export function renderCommitMessage( + template: string, + flakeDotLock: string, +): string { + return render(template, { flake_dot_lock: flakeDotLock }); +} + +function render(template: string, inputs: Record): string { + const tpl = Handlebars.compile(template); + return tpl(inputs); +}