From d1870f90ac29f6f4a8aceb99ebce4f99453c960a Mon Sep 17 00:00:00 2001 From: Joichiro Hayashi Date: Thu, 24 Sep 2026 17:42:06 +0900 Subject: [PATCH 1/3] ci: pin actions by SHA, lint workflows, publish via OIDC --- .github/workflows/ci.yml | 16 +++- .github/workflows/docs.yml | 6 +- .github/workflows/release.yml | 25 +++--- mise.lock | 139 ++++++++++++++++++++++++++++++++++ mise.toml | 4 + vite.config.ts | 1 + 6 files changed, 174 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d8451f..666c181 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,9 +13,9 @@ jobs: ci: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 - - uses: voidzero-dev/setup-vp@v1.18.0 + - uses: voidzero-dev/setup-vp@1b32467adbe183473499fd9d5d372c3ed9641754 # v1.18.0 with: node-version: "24" cache: true @@ -33,3 +33,15 @@ jobs: - run: vp run type-perf - run: vp run ts-compatibility + + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + + # The versions pinned in mise.toml, so CI lints with the ones the hook runs. + - uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3.6.3 + with: + install_args: actionlint shellcheck + + - run: actionlint diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 57fa797..cba5558 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -31,15 +31,15 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 - - uses: voidzero-dev/setup-vp@v1.18.0 + - uses: voidzero-dev/setup-vp@1b32467adbe183473499fd9d5d372c3ed9641754 # v1.18.0 with: node-version: "24" cache: true # mdbook and mdbook-linkcheck2, pinned in mise.toml. - - uses: jdx/mise-action@v3 + - uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3.6.3 - run: vp install diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 47cc826..0451aa2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,20 +9,20 @@ jobs: runs-on: ubuntu-latest permissions: contents: write # the release is created below - id-token: write # npm provenance + id-token: write # npm trusted publishing and provenance steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: fetch-depth: 0 # needed to check the tag is an ancestor of main - - uses: voidzero-dev/setup-vp@v1.18.0 + - uses: voidzero-dev/setup-vp@1b32467adbe183473499fd9d5d372c3ed9641754 # v1.18.0 with: node-version: "24" cache: true registry-url: "https://registry.npmjs.org" # setup-vp puts `vp` on PATH but not pnpm, which the publish step needs. - - uses: pnpm/action-setup@v4 + - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0 with: version: 11.25.0 @@ -50,10 +50,9 @@ jobs: pkg="$(node -p "require('./package.json').version")" test "$tag" = "$pkg" || { echo "tag $tag != package.json $pkg"; exit 1; } - # --no-git-checks: the tag is checked out detached, not on the publish branch. + # No token: npm trusts this workflow through OIDC. --no-git-checks: the tag is checked out + # detached, not on the publish branch. - run: pnpm publish --provenance --no-git-checks - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} # Last: a release pointing at a version npm rejected would be a lie. The notes come from the # PRs merged since the previous tag, grouped by `.github/release.yml`. @@ -72,15 +71,15 @@ jobs: concurrency: group: gh-pages # two releases must not push the site at once steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 - - uses: voidzero-dev/setup-vp@v1.18.0 + - uses: voidzero-dev/setup-vp@1b32467adbe183473499fd9d5d372c3ed9641754 # v1.18.0 with: node-version: "24" cache: true # mdbook and mdbook-linkcheck2, pinned in mise.toml. - - uses: jdx/mise-action@v3 + - uses: jdx/mise-action@5228313ee0372e111a38da051671ca30fc5a96db # v3.6.3 - run: vp install @@ -88,9 +87,11 @@ jobs: - name: Check out the published site run: | - git fetch --quiet origin gh-pages && - git worktree add site FETCH_HEAD || + if git fetch --quiet origin gh-pages; then + git worktree add site FETCH_HEAD + else git worktree add --orphan -b gh-pages site + fi - name: Add this version run: | diff --git a/mise.lock b/mise.lock index 0ace251..aedef2a 100644 --- a/mise.lock +++ b/mise.lock @@ -2,6 +2,53 @@ lockfile_version = 1 +[[tools.actionlint]] +version = "1.7.12" +backend = "aqua:rhysd/actionlint" +specifiers = ["1.7.12"] + +[tools.actionlint."platforms.linux-arm64"] +checksum = "sha256:325e971b6ba9bfa504672e29be93c24981eeb1c07576d730e9f7c8805afff0c6" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924897" +provenance = "github-attestations" + +[tools.actionlint."platforms.linux-arm64-musl"] +checksum = "sha256:325e971b6ba9bfa504672e29be93c24981eeb1c07576d730e9f7c8805afff0c6" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924897" +provenance = "github-attestations" + +[tools.actionlint."platforms.linux-x64"] +checksum = "sha256:8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924896" +provenance = "github-attestations" + +[tools.actionlint."platforms.linux-x64-musl"] +checksum = "sha256:8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924896" +provenance = "github-attestations" + +[tools.actionlint."platforms.macos-arm64"] +checksum = "sha256:aba9ced2dee8d27fecca3dc7feb1a7f9a52caefa1eb46f3271ea66b6e0e6953f" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924893" +provenance = "github-attestations" + +[tools.actionlint."platforms.macos-x64"] +checksum = "sha256:5b44c3bc2255115c9b69e30efc0fecdf498fdb63c5d58e17084fd5f16324c644" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_darwin_amd64.tar.gz" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924880" +provenance = "github-attestations" + +[tools.actionlint."platforms.windows-x64"] +checksum = "sha256:6e7241b51e6817ea6a047693d8e6fed13b31819c9a0dd6c5a726e1592d22f6e9" +url = "https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_windows_amd64.zip" +url_api = "https://api.github.com/repos/rhysd/actionlint/releases/assets/384924919" +provenance = "github-attestations" + [[tools."cargo:mdbook-linkcheck2"]] version = "0.13.0" backend = "cargo:mdbook-linkcheck2" @@ -20,6 +67,11 @@ checksum = "sha256:17753132aaf80cf59ec109d9b776bd5cf7a75edd5cfa7f08dffb35cf22b6d url = "https://github.com/marxin/mdbook-linkcheck2/releases/download/v0.13.0/mdbook-linkcheck2-x86_64-unknown-linux-gnu.tar.gz" url_api = "https://api.github.com/repos/marxin/mdbook-linkcheck2/releases/assets/516544325" +[tools."github:marxin/mdbook-linkcheck2"."platforms.linux-x64-musl"] +checksum = "sha256:17753132aaf80cf59ec109d9b776bd5cf7a75edd5cfa7f08dffb35cf22b6d21d" +url = "https://github.com/marxin/mdbook-linkcheck2/releases/download/v0.13.0/mdbook-linkcheck2-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/marxin/mdbook-linkcheck2/releases/assets/516544325" + [[tools.mdbook]] version = "0.5.4" backend = "aqua:rust-lang/mdBook" @@ -85,3 +137,90 @@ url = "https://nodejs.org/dist/v24.21.0/node-v24.21.0-darwin-x64.tar.gz" [tools.node."platforms.windows-x64"] checksum = "sha256:158f7685b44de51f6c0df1d153526cbcd3e1bc739a8dfc607721cef75de9e541" url = "https://nodejs.org/dist/v24.21.0/node-v24.21.0-win-x64.zip" + +[[tools.pinact]] +version = "5.0.0" +backend = "aqua:suzuki-shunsuke/pinact" +specifiers = ["5.0.0"] + +[tools.pinact."platforms.linux-arm64"] +checksum = "sha256:d28ca5e9ddd7950da4a808288f8a83f84fc3ca40e86bab970f3adeef33578c0b" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638070" +provenance = "github-attestations" + +[tools.pinact."platforms.linux-arm64-musl"] +checksum = "sha256:d28ca5e9ddd7950da4a808288f8a83f84fc3ca40e86bab970f3adeef33578c0b" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638070" +provenance = "github-attestations" + +[tools.pinact."platforms.linux-x64"] +checksum = "sha256:d005bbb85da80dacdc07816f24a5da723a9f6d1e9f3d3e7e73df33f9caa1358f" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638065" +provenance = "github-attestations" + +[tools.pinact."platforms.linux-x64-musl"] +checksum = "sha256:d005bbb85da80dacdc07816f24a5da723a9f6d1e9f3d3e7e73df33f9caa1358f" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638065" +provenance = "github-attestations" + +[tools.pinact."platforms.macos-arm64"] +checksum = "sha256:3437ebfc9db720e431e86fd03ed19173b88dcb80b0f177d11a892126108661b5" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_darwin_arm64.tar.gz" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638064" +provenance = "github-attestations" + +[tools.pinact."platforms.macos-x64"] +checksum = "sha256:da5532bd185a9d3a16a1f93774f835574e0c50bc74c2085b9917b9df3e9fbbaa" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_darwin_amd64.tar.gz" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638050" +provenance = "github-attestations" + +[tools.pinact."platforms.windows-x64"] +checksum = "sha256:df2f590f24c2bfe65a35010bffb4369ba0792c9afaf7fb324b2330895a37d19f" +url = "https://github.com/suzuki-shunsuke/pinact/releases/download/v5.0.0/pinact_windows_amd64.zip" +url_api = "https://api.github.com/repos/suzuki-shunsuke/pinact/releases/assets/558638100" +provenance = "github-attestations" + +[[tools.shellcheck]] +version = "0.11.0" +backend = "aqua:koalaman/shellcheck" +specifiers = ["0.11.0"] + +[tools.shellcheck."platforms.linux-arm64"] +checksum = "sha256:12b331c1d2db6b9eb13cfca64306b1b157a86eb69db83023e261eaa7e7c14588" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.aarch64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056934" + +[tools.shellcheck."platforms.linux-arm64-musl"] +checksum = "sha256:12b331c1d2db6b9eb13cfca64306b1b157a86eb69db83023e261eaa7e7c14588" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.aarch64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056934" + +[tools.shellcheck."platforms.linux-x64"] +checksum = "sha256:8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056942" + +[tools.shellcheck."platforms.linux-x64-musl"] +checksum = "sha256:8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056942" + +[tools.shellcheck."platforms.macos-arm64"] +checksum = "sha256:56affdd8de5527894dca6dc3d7e0a99a873b0f004d7aabc30ae407d3f48b0a79" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.darwin.aarch64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056932" + +[tools.shellcheck."platforms.macos-x64"] +checksum = "sha256:3c89db4edcab7cf1c27bff178882e0f6f27f7afdf54e859fa041fca10febe4c6" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.darwin.x86_64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056930" + +[tools.shellcheck."platforms.windows-x64"] +checksum = "sha256:8a4e35ab0b331c85d73567b12f2a444df187f483e5079ceffa6bda1faa2e740e" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.zip" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056944" diff --git a/mise.toml b/mise.toml index 0f70714..81450ff 100644 --- a/mise.toml +++ b/mise.toml @@ -4,6 +4,10 @@ mdbook = "0.5.4" # Upstream ships a linux-x64 binary only, and the source build takes minutes. "github:marxin/mdbook-linkcheck2" = { version = "0.13.0", os = ["linux/x64"] } "cargo:mdbook-linkcheck2" = { version = "0.13.0", os = ["macos", "linux/arm64"] } +pinact = "5.0.0" +actionlint = "1.7.12" +# actionlint runs it over each `run:` script. +shellcheck = "0.11.0" [settings] lockfile = true diff --git a/vite.config.ts b/vite.config.ts index a3747db..d4c3391 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -5,6 +5,7 @@ import lint from "./oxlint.config.ts"; export default defineConfig({ staged: { "*": "vp check --fix", + ".github/workflows/*.yml": "actionlint", }, pack: { // Named, so the import path is the name a user writes rather than where the file sits. From c2b00bb8dd1a559309281f1aa17748c286406a14 Mon Sep 17 00:00:00 2001 From: Joichiro Hayashi Date: Thu, 24 Sep 2026 17:46:11 +0900 Subject: [PATCH 2/3] chore: switch to main in push-tag instead of refusing --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ca1a7a4..3587936 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "prepublishOnly": "vp run build", "prepare": "vp config && vp fmt AGENTS.md", "bump-version": "git branch --show-current | grep -qxv main || { echo 'run this on a branch, not main'; exit 1; }; bumpp --no-tag", - "push-tag": "git branch --show-current | grep -qx main || { echo 'run this on main'; exit 1; }; git diff --quiet HEAD -- || { echo 'tracked files differ from HEAD; commit them before tagging'; exit 1; }; git tag v$npm_package_version && git push origin v$npm_package_version" + "push-tag": "git diff --quiet HEAD -- || { echo 'tracked files differ from HEAD; commit them before tagging'; exit 1; }; git switch main && git pull --ff-only && tag=v$(node -p \"require('./package.json').version\") && git tag $tag && git push origin $tag" }, "devDependencies": { "@types/node": "^26.5.0", From f7f65bcfc424fdba0ed38ca3601ecce82399e51b Mon Sep 17 00:00:00 2001 From: Joichiro Hayashi Date: Thu, 24 Sep 2026 17:50:38 +0900 Subject: [PATCH 3/3] chore: cut the release branch and open its PR in bump-version --- package.json | 2 +- scripts/bump-version.sh | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100755 scripts/bump-version.sh diff --git a/package.json b/package.json index 3587936..5caac51 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "type-perf": "node scripts/type-perf/index.ts", "prepublishOnly": "vp run build", "prepare": "vp config && vp fmt AGENTS.md", - "bump-version": "git branch --show-current | grep -qxv main || { echo 'run this on a branch, not main'; exit 1; }; bumpp --no-tag", + "bump-version": "scripts/bump-version.sh", "push-tag": "git diff --quiet HEAD -- || { echo 'tracked files differ from HEAD; commit them before tagging'; exit 1; }; git switch main && git pull --ff-only && tag=v$(node -p \"require('./package.json').version\") && git tag $tag && git push origin $tag" }, "devDependencies": { diff --git a/scripts/bump-version.sh b/scripts/bump-version.sh new file mode 100755 index 0000000..82f235d --- /dev/null +++ b/scripts/bump-version.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env sh +# Bumps the version on a release branch cut from the latest main, and opens its PR. +set -eu + +git diff --quiet HEAD -- || { echo 'tracked files differ from HEAD; commit them first'; exit 1; } + +git switch main +git pull --ff-only + +# bumpp only picks the version; the branch is named after it, so it is cut afterwards. +bumpp --no-commit --no-tag --no-push +version="$(node -p "require('./package.json').version")" + +git switch -c "chore/release-$version" +git commit -am "chore: release v$version" +git push -u origin HEAD +gh pr create --fill --label skip-changelog