From 73624e09a36d9a4eba07cb0b826104a2aa6410e5 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 14 Jun 2026 17:45:50 +0000 Subject: [PATCH 1/5] ci: pin all third-party actions in reusable workflows to commit SHAs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin every third-party GitHub Action referenced by a mutable tag (@v6, @v15, etc.) in rainix's reusable workflows to the immutable commit SHA that tag currently points to. The exact current versions are preserved as a trailing `# ` comment, so this is a pure immutability change with no behavior change. rainix owns the org's shared CI: these reusable workflows are inherited by every consumer (raindex, flow, etc.). Referencing third-party actions by mutable tag is a supply-chain hole — a compromised or retagged action silently executes in every consumer's CI with their tokens. Pinning to a SHA makes the inherited CI immutable and reproducible. This also stabilizes an intermittent cachix/cachix-action@v15 flake that has been hitting raindex CI (rs-static/wasm failing in the cachix step), since the action is now resolved to a fixed commit. 70 references pinned across 14 workflow files / 11 distinct actions: actions/checkout, actions/cache, nixbuild/nix-quick-install-action, cachix/cachix-action, nix-community/cache-nix-action, Swatinem/rust-cache, jlumbroso/free-disk-space, JS-DevTools/npm-publish, softprops/action-gh-release. rainlanguage/* reusable-workflow references are intentionally left on @main (first-party, not a supply-chain concern). Maintainers and dependabot can still bump versions via the `# ` comments. This is the upstream/source equivalent of raindex#2724 (the consumer-side pinning), which can then be slimmed to just its 2 repo-local pins. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/check-shell.yml | 8 ++++---- .github/workflows/rainix-autopublish.yaml | 14 +++++++------- .github/workflows/rainix-copy-artifacts.yaml | 8 ++++---- .github/workflows/rainix-manual-sol-artifacts.yaml | 10 +++++----- .github/workflows/rainix-rs-static.yaml | 10 +++++----- .github/workflows/rainix-rs-test.yaml | 10 +++++----- .github/workflows/rainix-rs-wasm-test.yaml | 10 +++++----- .github/workflows/rainix-rs-wasm.yaml | 10 +++++----- .github/workflows/rainix-sol-legal.yaml | 8 ++++---- .github/workflows/rainix-sol-static.yaml | 10 +++++----- .github/workflows/rainix-sol-test.yaml | 10 +++++----- .github/workflows/rainix-subgraph-test.yaml | 8 ++++---- .github/workflows/rainix-vercel.yaml | 14 +++++++------- .github/workflows/test.yml | 10 +++++----- 14 files changed, 70 insertions(+), 70 deletions(-) diff --git a/.github/workflows/check-shell.yml b/.github/workflows/check-shell.yml index 8dd8185..401145b 100644 --- a/.github/workflows/check-shell.yml +++ b/.github/workflows/check-shell.yml @@ -10,8 +10,8 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -20,7 +20,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -30,7 +30,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: # restore and save a cache using this key primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} diff --git a/.github/workflows/rainix-autopublish.yaml b/.github/workflows/rainix-autopublish.yaml index 68f6059..66cca0d 100644 --- a/.github/workflows/rainix-autopublish.yaml +++ b/.github/workflows/rainix-autopublish.yaml @@ -49,7 +49,7 @@ jobs: id-token: write contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: # PUBLISH_PRIVATE_KEY is a deploy key whose push events trigger # downstream workflows (unlike GITHUB_TOKEN pushes which don't). @@ -57,7 +57,7 @@ jobs: # falls back to GITHUB_TOKEN over HTTPS — pushes still succeed, # they just won't trigger tag-listening workflows. ssh-key: ${{ secrets.PUBLISH_PRIVATE_KEY }} - - uses: nixbuild/nix-quick-install-action@v30 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -66,7 +66,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -76,7 +76,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v6 + uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- @@ -318,7 +318,7 @@ jobs: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - name: Publish to NPM if: ${{ inputs.npm-package != '' && steps.npm.outputs.changed == 'true' }} - uses: JS-DevTools/npm-publish@v3 + uses: JS-DevTools/npm-publish@19c28f1ef146469e409470805ea4279d47c3d35c # v3 with: token: ${{ secrets.NPM_PUBLISH_PRIVATE_TOKEN }} access: public @@ -341,7 +341,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: GitHub Release (npm) if: ${{ inputs.npm-package != '' && steps.npm.outputs.changed == 'true' }} - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: tag_name: npm-${{ env.NPM_VERSION }} name: NPM Package Release ${{ env.NPM_VERSION }} @@ -350,7 +350,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: GitHub Release (soldeer) if: ${{ inputs.soldeer-package != '' && steps.soldeer.outputs.changed == 'true' }} - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 with: tag_name: sol-v${{ steps.soldeer.outputs.next }} name: Soldeer Release sol-v${{ steps.soldeer.outputs.next }} diff --git a/.github/workflows/rainix-copy-artifacts.yaml b/.github/workflows/rainix-copy-artifacts.yaml index 593195a..f299337 100644 --- a/.github/workflows/rainix-copy-artifacts.yaml +++ b/.github/workflows/rainix-copy-artifacts.yaml @@ -5,8 +5,8 @@ jobs: copy-artifacts: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -15,7 +15,7 @@ jobs: # toolchain + any prelude build don't refetch crates from crates.io (whose # download endpoint 403s nix's User-Agent). Pushes new paths when # CACHIX_AUTH_TOKEN is set; continue-on-error degrades gracefully. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -24,7 +24,7 @@ jobs: # with cache-nix-action and corrupts it. Push happens in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- diff --git a/.github/workflows/rainix-manual-sol-artifacts.yaml b/.github/workflows/rainix-manual-sol-artifacts.yaml index 24ed9cd..14c2c44 100644 --- a/.github/workflows/rainix-manual-sol-artifacts.yaml +++ b/.github/workflows/rainix-manual-sol-artifacts.yaml @@ -12,8 +12,8 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -22,7 +22,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -32,7 +32,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- @@ -40,7 +40,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | cache diff --git a/.github/workflows/rainix-rs-static.yaml b/.github/workflows/rainix-rs-static.yaml index cc618cb..068e938 100644 --- a/.github/workflows/rainix-rs-static.yaml +++ b/.github/workflows/rainix-rs-static.yaml @@ -5,8 +5,8 @@ jobs: rs-static: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -15,7 +15,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -25,12 +25,12 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- gc-max-store-size-linux: 8G - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c rainix-rs-static # Run the rainix pre-commit hook bundle (taplo, the nix hooks, yamlfmt, # shellcheck, rustfmt) over all files — the same hooks a local commit diff --git a/.github/workflows/rainix-rs-test.yaml b/.github/workflows/rainix-rs-test.yaml index 6061e63..b5b642b 100644 --- a/.github/workflows/rainix-rs-test.yaml +++ b/.github/workflows/rainix-rs-test.yaml @@ -9,8 +9,8 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -19,7 +19,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -29,11 +29,11 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- gc-max-store-size-linux: 8G gc-max-store-size-macos: 1G - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c cargo test diff --git a/.github/workflows/rainix-rs-wasm-test.yaml b/.github/workflows/rainix-rs-wasm-test.yaml index 4a5d522..a8982ae 100644 --- a/.github/workflows/rainix-rs-wasm-test.yaml +++ b/.github/workflows/rainix-rs-wasm-test.yaml @@ -5,8 +5,8 @@ jobs: rs-wasm-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -15,7 +15,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -25,10 +25,10 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- gc-max-store-size-linux: 8G - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c bash -c "CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --workspace" diff --git a/.github/workflows/rainix-rs-wasm.yaml b/.github/workflows/rainix-rs-wasm.yaml index 9362dbd..d5b6286 100644 --- a/.github/workflows/rainix-rs-wasm.yaml +++ b/.github/workflows/rainix-rs-wasm.yaml @@ -5,8 +5,8 @@ jobs: rs-wasm: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -15,7 +15,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -25,10 +25,10 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- gc-max-store-size-linux: 8G - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c cargo build -r --target wasm32-unknown-unknown --lib --workspace diff --git a/.github/workflows/rainix-sol-legal.yaml b/.github/workflows/rainix-sol-legal.yaml index 6888ef0..5bec21d 100644 --- a/.github/workflows/rainix-sol-legal.yaml +++ b/.github/workflows/rainix-sol-legal.yaml @@ -5,8 +5,8 @@ jobs: legal: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -15,7 +15,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -25,7 +25,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- diff --git a/.github/workflows/rainix-sol-static.yaml b/.github/workflows/rainix-sol-static.yaml index cf1c05f..9db71fb 100644 --- a/.github/workflows/rainix-sol-static.yaml +++ b/.github/workflows/rainix-sol-static.yaml @@ -5,8 +5,8 @@ jobs: static: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -15,7 +15,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -25,7 +25,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- @@ -33,7 +33,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | cache diff --git a/.github/workflows/rainix-sol-test.yaml b/.github/workflows/rainix-sol-test.yaml index 43d9823..1a62ddc 100644 --- a/.github/workflows/rainix-sol-test.yaml +++ b/.github/workflows/rainix-sol-test.yaml @@ -34,8 +34,8 @@ jobs: FLARE_RPC_URL: ${{ secrets.RPC_URL_FLARE_FORK || vars.RPC_URL_FLARE_FORK }} POLYGON_RPC_URL: ${{ secrets.RPC_URL_POLYGON_FORK || vars.RPC_URL_POLYGON_FORK }} steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -44,7 +44,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -54,7 +54,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- @@ -62,7 +62,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | cache diff --git a/.github/workflows/rainix-subgraph-test.yaml b/.github/workflows/rainix-subgraph-test.yaml index 0d9df0f..14ac52e 100644 --- a/.github/workflows/rainix-subgraph-test.yaml +++ b/.github/workflows/rainix-subgraph-test.yaml @@ -5,8 +5,8 @@ jobs: subgraph-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -14,7 +14,7 @@ jobs: # Substitute prebuilt rainix derivations from the shared Cachix binary # cache. Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error # so a missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -23,7 +23,7 @@ jobs: # with cache-nix-action and corrupts it. Push happens in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- diff --git a/.github/workflows/rainix-vercel.yaml b/.github/workflows/rainix-vercel.yaml index 2fd5c94..f4db834 100644 --- a/.github/workflows/rainix-vercel.yaml +++ b/.github/workflows/rainix-vercel.yaml @@ -65,31 +65,31 @@ jobs: permissions: contents: read steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Free disk space - uses: jlumbroso/free-disk-space@v1.3.1 - - uses: nixbuild/nix-quick-install-action@v30 + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true keep-outputs = true - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- gc-max-store-size-linux: 8G - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: prefix-key: rust-${{ github.workflow }} - name: Cache npm - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ~/.npm key: npm-${{ runner.os }}-${{ github.workflow }}-${{ hashFiles('**/package-lock.json') }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a34614f..6fd25d3 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,8 +29,8 @@ jobs: run: working-directory: test/fixture steps: - - uses: actions/checkout@v6 - - uses: nixbuild/nix-quick-install-action@v30 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: nix_conf: | keep-env-derivations = true @@ -39,7 +39,7 @@ jobs: # cache instead of rebuilding toolchain crates from source (rainix#196). # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@v15 + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 continue-on-error: true with: name: rainlanguage @@ -49,7 +49,7 @@ jobs: # disk image is malformed"). Push happens once in the post step. useDaemon: false - name: Restore and save Nix store - uses: nix-community/cache-nix-action@v7 + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 with: primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} restore-prefixes-first-match: nix-${{ runner.os }}- @@ -57,7 +57,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | cache From 8a6ce1d2233e0736e23162ec7b3d074397934026 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Sun, 14 Jun 2026 18:51:19 +0000 Subject: [PATCH 2/5] ci: DRY the nix+cachix preamble into a composite action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The checkout + nix-quick-install + cachix + cache-nix-action setup preamble was copy-pasted across all 14 reusable workflows, so each pinned third-party action SHA (notably cachix) lived in 14 places. Extract it into a single composite action `.github/actions/nix-cachix-setup` so each of those SHAs lives in ONE place. - New composite action holds the common preamble once. Inputs cover the variations: cachix-auth-token (a composite cannot read secrets.*, so each reusable plumbs secrets.CACHIX_AUTH_TOKEN through as an input), cachix-name, gc-max-store-size-macos (rs-test), and checkout/cache-nix toggles for the outliers. - The 13 uniform reusables replace the 4-step preamble with one `uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main` (fully qualified, since a bare ./ would resolve against the calling repo — same pattern as the existing github-chore action ref). - rainix-vercel keeps its own checkout (it needs a Free-disk-space step between checkout and nix) and routes nix+cachix+cache-nix through the composite (checkout: false). - rainix-autopublish keeps its own ssh-key checkout (v4) and cache-nix-action (v6) — both intentionally different pinned versions — and routes only the shared nix-quick-install + cachix pair through the composite (checkout: false, cache-nix: false). Behavior-preserving: same actions, same order, same pinned versions; pure de-duplication. cachix and nix-quick-install SHAs now appear once (in the composite); checkout v6 and cache-nix v7 once in the composite plus the vercel/autopublish inline outliers. Co-Authored-By: Claude Opus 4.8 --- .github/actions/nix-cachix-setup/action.yml | 71 +++++++++++++++++++ .github/workflows/check-shell.yml | 35 ++------- .github/workflows/rainix-autopublish.yaml | 27 +++---- .github/workflows/rainix-copy-artifacts.yaml | 28 ++------ .../rainix-manual-sol-artifacts.yaml | 29 ++------ .github/workflows/rainix-rs-static.yaml | 31 ++------ .github/workflows/rainix-rs-test.yaml | 30 ++------ .github/workflows/rainix-rs-wasm-test.yaml | 29 ++------ .github/workflows/rainix-rs-wasm.yaml | 29 ++------ .github/workflows/rainix-sol-legal.yaml | 29 ++------ .github/workflows/rainix-sol-static.yaml | 29 ++------ .github/workflows/rainix-sol-test.yaml | 29 ++------ .github/workflows/rainix-subgraph-test.yaml | 27 ++----- .github/workflows/rainix-vercel.yaml | 25 +++---- .github/workflows/test.yml | 30 ++------ 15 files changed, 155 insertions(+), 323 deletions(-) create mode 100644 .github/actions/nix-cachix-setup/action.yml diff --git a/.github/actions/nix-cachix-setup/action.yml b/.github/actions/nix-cachix-setup/action.yml new file mode 100644 index 0000000..aa15df1 --- /dev/null +++ b/.github/actions/nix-cachix-setup/action.yml @@ -0,0 +1,71 @@ +name: nix-cachix-setup +description: >- + Shared 'nix + cachix CI' preamble for the rainix reusable workflows: checkout, + nix-quick-install, the Cachix substituter/pusher, and the cache-nix-action Nix + store restore/save. This composite is the single source of truth for the + pinned third-party action SHAs used by that preamble — each SHA lives here once + instead of being copy-pasted across the reusables. +inputs: + cachix-auth-token: + description: >- + Cachix auth token. A composite action cannot read `secrets.*`, so the + caller reusable must plumb `secrets.CACHIX_AUTH_TOKEN` through to here. + Empty (the default) degrades to a read-only/anonymous Cachix pull. + required: false + default: '' + cachix-name: + description: Cachix binary cache name to substitute from / push to. + required: false + default: rainlanguage + checkout: + description: >- + Run the bundled `actions/checkout` (default). Set to 'false' if the + caller needs a non-default checkout (e.g. an ssh-key deploy-key checkout) + and runs `actions/checkout` itself before calling this composite. + required: false + default: 'true' + cache-nix: + description: >- + Run the bundled `cache-nix-action` Nix store restore/save (default). Set + to 'false' if the caller pins a different cache-nix-action version and runs + it itself. + required: false + default: 'true' + gc-max-store-size-macos: + description: >- + Optional `gc-max-store-size-macos` for the bundled cache-nix-action. Left + empty (the action's own default) unless a caller needs to cap the macOS + store before saving. + required: false + default: '' +runs: + using: composite + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + if: ${{ inputs.checkout == 'true' }} + - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + with: + nix_conf: | + keep-env-derivations = true + keep-outputs = true + # Substitute prebuilt rainix derivations from the shared Cachix binary + # cache instead of rebuilding toolchain crates from source (rainix#196). + # Pushes new paths when the auth token is set; continue-on-error so a + # missing cache/token or a Cachix outage degrades to a normal build. + - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 + continue-on-error: true + with: + name: ${{ inputs.cachix-name }} + authToken: ${{ inputs.cachix-auth-token }} + # No store-watching daemon: it checkpoints the nix DB + # concurrently with cache-nix-action and corrupts it ("database + # disk image is malformed"). Push happens once in the post step. + useDaemon: false + - name: Restore and save Nix store + if: ${{ inputs.cache-nix == 'true' }} + uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 + with: + primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} + restore-prefixes-first-match: nix-${{ runner.os }}- + gc-max-store-size-linux: 8G + gc-max-store-size-macos: ${{ inputs.gc-max-store-size-macos }} diff --git a/.github/workflows/check-shell.yml b/.github/workflows/check-shell.yml index 401145b..c718599 100644 --- a/.github/workflows/check-shell.yml +++ b/.github/workflows/check-shell.yml @@ -10,36 +10,13 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. This is a + # local workflow (not a reusable), so a `./` ref would also work, but the + # fully qualified ref keeps every call site consistent. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - # restore and save a cache using this key - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - # if there's no cache hit, restore a cache by this prefix - restore-prefixes-first-match: nix-${{ runner.os }}- - # collect garbage until the Nix store size (in bytes) is at most this number - # before trying to save a new cache - # 1G = 1073741824 - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - run: NIXPKGS_ALLOW_INSECURE=1 nix flake check --impure - run: nix develop --command cargo release --version - run: nix develop --command flamegraph --help diff --git a/.github/workflows/rainix-autopublish.yaml b/.github/workflows/rainix-autopublish.yaml index 66cca0d..73918e9 100644 --- a/.github/workflows/rainix-autopublish.yaml +++ b/.github/workflows/rainix-autopublish.yaml @@ -49,6 +49,12 @@ jobs: id-token: write contents: write steps: + # This job pins a different checkout (v4, for the ssh-key deploy-key + # checkout) and a different cache-nix-action (v6) than the rest of the + # reusables, so it keeps those two steps inline and routes only the + # nix-quick-install + Cachix pair (whose SHAs ARE shared) through the + # composite via `checkout: 'false'` / `cache-nix: 'false'`. Fully + # qualified ref: a bare `./` would resolve against the calling repo. - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: # PUBLISH_PRIVATE_KEY is a deploy key whose push events trigger @@ -57,24 +63,11 @@ jobs: # falls back to GITHUB_TOKEN over HTTPS — pushes still succeed, # they just won't trigger tag-listening workflows. ssh-key: ${{ secrets.PUBLISH_PRIVATE_KEY }} - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + checkout: 'false' + cache-nix: 'false' - name: Restore and save Nix store uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6 with: diff --git a/.github/workflows/rainix-copy-artifacts.yaml b/.github/workflows/rainix-copy-artifacts.yaml index f299337..f209385 100644 --- a/.github/workflows/rainix-copy-artifacts.yaml +++ b/.github/workflows/rainix-copy-artifacts.yaml @@ -5,30 +5,12 @@ jobs: copy-artifacts: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt derivations from the shared Cachix cache so the - # toolchain + any prelude build don't refetch crates from crates.io (whose - # download endpoint 403s nix's User-Agent). Pushes new paths when - # CACHIX_AUTH_TOKEN is set; continue-on-error degrades gracefully. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB concurrently - # with cache-nix-action and corrupts it. Push happens in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} # No Foundry build cache here on purpose: this is a clean-build determinism # check, so out/ must be regenerated fresh — and caching only cache/ (not # out/) gives no real speedup, since forge recompiles to rebuild the diff --git a/.github/workflows/rainix-manual-sol-artifacts.yaml b/.github/workflows/rainix-manual-sol-artifacts.yaml index 14c2c44..7bad012 100644 --- a/.github/workflows/rainix-manual-sol-artifacts.yaml +++ b/.github/workflows/rainix-manual-sol-artifacts.yaml @@ -12,31 +12,12 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build diff --git a/.github/workflows/rainix-rs-static.yaml b/.github/workflows/rainix-rs-static.yaml index 068e938..3dc19fb 100644 --- a/.github/workflows/rainix-rs-static.yaml +++ b/.github/workflows/rainix-rs-static.yaml @@ -5,31 +5,14 @@ jobs: rs-static: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action). The pinned action SHAs live in the composite. A + # reusable workflow must reference a sibling local action by its fully + # qualified owner/repo path (a bare `./` would resolve against the calling + # repo, not rainix), mirroring the github-chore action ref below. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c rainix-rs-static # Run the rainix pre-commit hook bundle (taplo, the nix hooks, yamlfmt, diff --git a/.github/workflows/rainix-rs-test.yaml b/.github/workflows/rainix-rs-test.yaml index b5b642b..a7108dc 100644 --- a/.github/workflows/rainix-rs-test.yaml +++ b/.github/workflows/rainix-rs-test.yaml @@ -9,31 +9,13 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + # This matrix runs on macOS too, so cap the macOS store before save. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} gc-max-store-size-macos: 1G - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c cargo test diff --git a/.github/workflows/rainix-rs-wasm-test.yaml b/.github/workflows/rainix-rs-wasm-test.yaml index a8982ae..49bb449 100644 --- a/.github/workflows/rainix-rs-wasm-test.yaml +++ b/.github/workflows/rainix-rs-wasm-test.yaml @@ -5,30 +5,11 @@ jobs: rs-wasm-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c bash -c "CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --workspace" diff --git a/.github/workflows/rainix-rs-wasm.yaml b/.github/workflows/rainix-rs-wasm.yaml index d5b6286..c6eeb69 100644 --- a/.github/workflows/rainix-rs-wasm.yaml +++ b/.github/workflows/rainix-rs-wasm.yaml @@ -5,30 +5,11 @@ jobs: rs-wasm: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 - run: nix develop github:rainlanguage/rainix#rust-shell -c cargo build -r --target wasm32-unknown-unknown --lib --workspace diff --git a/.github/workflows/rainix-sol-legal.yaml b/.github/workflows/rainix-sol-legal.yaml index 5bec21d..34a2c9e 100644 --- a/.github/workflows/rainix-sol-legal.yaml +++ b/.github/workflows/rainix-sol-legal.yaml @@ -5,31 +5,12 @@ jobs: legal: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - name: Install soldeer dependencies if: hashFiles('soldeer.lock') != '' run: nix develop github:rainlanguage/rainix#sol-shell -c forge soldeer install diff --git a/.github/workflows/rainix-sol-static.yaml b/.github/workflows/rainix-sol-static.yaml index 9db71fb..1670891 100644 --- a/.github/workflows/rainix-sol-static.yaml +++ b/.github/workflows/rainix-sol-static.yaml @@ -5,31 +5,12 @@ jobs: static: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build diff --git a/.github/workflows/rainix-sol-test.yaml b/.github/workflows/rainix-sol-test.yaml index 1a62ddc..7999620 100644 --- a/.github/workflows/rainix-sol-test.yaml +++ b/.github/workflows/rainix-sol-test.yaml @@ -34,31 +34,12 @@ jobs: FLARE_RPC_URL: ${{ secrets.RPC_URL_FLARE_FORK || vars.RPC_URL_FLARE_FORK }} POLYGON_RPC_URL: ${{ secrets.RPC_URL_POLYGON_FORK || vars.RPC_URL_POLYGON_FORK }} steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build diff --git a/.github/workflows/rainix-subgraph-test.yaml b/.github/workflows/rainix-subgraph-test.yaml index 14ac52e..22f5bed 100644 --- a/.github/workflows/rainix-subgraph-test.yaml +++ b/.github/workflows/rainix-subgraph-test.yaml @@ -5,27 +5,10 @@ jobs: subgraph-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Fully + # qualified ref: a bare `./` would resolve against the calling repo. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache. Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error - # so a missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB concurrently - # with cache-nix-action and corrupts it. Push happens in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - run: nix develop github:rainlanguage/rainix#subgraph-shell -c subgraph-test diff --git a/.github/workflows/rainix-vercel.yaml b/.github/workflows/rainix-vercel.yaml index 0321cb4..8982434 100644 --- a/.github/workflows/rainix-vercel.yaml +++ b/.github/workflows/rainix-vercel.yaml @@ -70,26 +70,19 @@ jobs: contents: read pull-requests: write steps: + # This workflow needs a Free-disk-space step between checkout and the nix + # install, so it runs its own checkout (composite `checkout: false`) and + # then calls the shared preamble for nix-quick-install + Cachix + + # cache-nix-action. The pinned action SHAs for those still live once in the + # composite. Fully qualified ref: a bare `./` would resolve against the + # calling repo. - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - name: Free disk space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + checkout: 'false' - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 with: prefix-key: rust-${{ github.workflow }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6fd25d3..9a6c59f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,31 +29,13 @@ jobs: run: working-directory: test/fixture steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. This is a + # local workflow (not a reusable), so a `./` ref would also work, but the + # fully qualified ref keeps every call site consistent. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: - nix_conf: | - keep-env-derivations = true - keep-outputs = true - # Substitute prebuilt rainix derivations from the shared Cachix binary - # cache instead of rebuilding toolchain crates from source (rainix#196). - # Pushes new paths when CACHIX_AUTH_TOKEN is set; continue-on-error so a - # missing cache/token or a Cachix outage degrades to a normal build. - - uses: cachix/cachix-action@ad2ddac53f961de1989924296a1f236fcfbaa4fc # v15 - continue-on-error: true - with: - name: rainlanguage - authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} - # No store-watching daemon: it checkpoints the nix DB - # concurrently with cache-nix-action and corrupts it ("database - # disk image is malformed"). Push happens once in the post step. - useDaemon: false - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G + cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build From 9c4b6063df7de32ddb6be6b89af8d205e4632ee5 Mon Sep 17 00:00:00 2001 From: David Meister Date: Sun, 14 Jun 2026 19:39:26 +0000 Subject: [PATCH 3/5] ci: single-source every repeated third-party action via composites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nix-cachix-setup composite single-sourced the nix+cachix preamble, but five third-party actions were still pinned at multiple call sites (rust-cache 5x, actions/cache 5x, actions/checkout 3x, action-gh-release 2x, cache-nix-action 2x). GitHub Actions can't parameterize a `uses:` ref, so the only way to pin an action's SHA in one place is to wrap its step in a composite with inputs for the per-call-site variation. Adds four composite actions and routes every occurrence through them (plus the existing nix-cachix-setup): - .github/actions/checkout — wraps actions/checkout; `ssh-key` input for the autopublish deploy-key checkout. Also called by nix-cachix-setup and the vercel inline checkout. Consolidates the lone autopublish v4 checkout onto the v6 the rest of the org already uses (ssh-key behavior is identical across v4/v6; the only v4->v6 changes are Node 24 + credential-store location, both irrelevant to a deploy-key checkout). - .github/actions/rust-cache — wraps Swatinem/rust-cache; `prefix-key` input for the vercel per-workflow namespacing. (rust-cache reads prefix-key as `getInput || "v0-rust"`, so the empty default == the four no-input sites.) - .github/actions/cache — wraps actions/cache; `path`/`key`/ `restore-keys` inputs (the four Foundry build caches + the vercel npm cache). - .github/actions/gh-release — wraps softprops/action-gh-release; `tag-name`/`name`/`files` inputs + a `github-token` input plumbed to `env: GITHUB_TOKEN` (a composite can't read secrets.*). Empty `files` parses to no assets, matching the soldeer release that attaches none. Also folds the autopublish job's inline cache-nix-action@v6 into the nix-cachix-setup composite's bundled v7 step (drops `cache-nix: 'false'`): autopublish was the only site left on v6 — a long-standing drift, not a deliberate need — and its Linux-only Nix-store cache is exactly what v7 caches by default, so the consolidation is behavior-preserving. Every composite's own action refs stay SHA-pinned; consumers reference the new composites by the fully qualified `rainlanguage/rainix/.github/actions/@main` ref (a bare `./` would resolve against the calling repo), mirroring nix-cachix-setup. Net: no third-party action appears more than once across .github/. Co-Authored-By: Claude Opus 4.8 --- .github/actions/cache/action.yml | 28 +++++++++++++++ .github/actions/checkout/action.yml | 22 ++++++++++++ .github/actions/gh-release/action.yml | 36 +++++++++++++++++++ .github/actions/nix-cachix-setup/action.yml | 2 +- .github/actions/rust-cache/action.yml | 22 ++++++++++++ .github/workflows/rainix-autopublish.yaml | 32 ++++++----------- .../rainix-manual-sol-artifacts.yaml | 2 +- .github/workflows/rainix-rs-static.yaml | 2 +- .github/workflows/rainix-rs-test.yaml | 2 +- .github/workflows/rainix-rs-wasm-test.yaml | 2 +- .github/workflows/rainix-rs-wasm.yaml | 2 +- .github/workflows/rainix-sol-static.yaml | 2 +- .github/workflows/rainix-sol-test.yaml | 2 +- .github/workflows/rainix-vercel.yaml | 6 ++-- .github/workflows/test.yml | 2 +- 15 files changed, 131 insertions(+), 33 deletions(-) create mode 100644 .github/actions/cache/action.yml create mode 100644 .github/actions/checkout/action.yml create mode 100644 .github/actions/gh-release/action.yml create mode 100644 .github/actions/rust-cache/action.yml diff --git a/.github/actions/cache/action.yml b/.github/actions/cache/action.yml new file mode 100644 index 0000000..6c642f0 --- /dev/null +++ b/.github/actions/cache/action.yml @@ -0,0 +1,28 @@ +name: cache +description: >- + Single-source wrapper around `actions/cache`. GitHub Actions can't + parameterize a `uses:` ref, so wrapping the step in a composite is the only + way to pin the action's SHA in ONE place across every rainix workflow that + caches build outputs. Each call site passes its own `path` / `key` / + `restore-keys` (the Foundry build cache, the npm cache, etc.). +inputs: + path: + description: A list of files, directories, and patterns to cache and restore. + required: true + key: + description: An explicit key for restoring and saving the cache. + required: true + restore-keys: + description: >- + An ordered multiline string listing the prefix-matched keys used to + restore a stale cache if no cache hit occurred for `key`. + required: false + default: '' +runs: + using: composite + steps: + - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: ${{ inputs.path }} + key: ${{ inputs.key }} + restore-keys: ${{ inputs.restore-keys }} diff --git a/.github/actions/checkout/action.yml b/.github/actions/checkout/action.yml new file mode 100644 index 0000000..a16af6c --- /dev/null +++ b/.github/actions/checkout/action.yml @@ -0,0 +1,22 @@ +name: checkout +description: >- + Single-source wrapper around `actions/checkout`. GitHub Actions can't + parameterize a `uses:` ref (no `uses: ${{ env.X }}`), so the only way to pin + the checkout SHA in ONE place across every rainix workflow is to wrap it in a + composite. The `ssh-key` input covers the one call site (autopublish) that + needs a deploy-key checkout; every other site uses the default token checkout. +inputs: + ssh-key: + description: >- + Optional deploy key (e.g. `secrets.PUBLISH_PRIVATE_KEY`) for a checkout + whose pushes should trigger downstream workflows. A composite action + cannot read `secrets.*`, so the caller must plumb the secret through here. + Empty (the default) falls back to the standard GITHUB_TOKEN checkout. + required: false + default: '' +runs: + using: composite + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ssh-key: ${{ inputs.ssh-key }} diff --git a/.github/actions/gh-release/action.yml b/.github/actions/gh-release/action.yml new file mode 100644 index 0000000..1d854a8 --- /dev/null +++ b/.github/actions/gh-release/action.yml @@ -0,0 +1,36 @@ +name: gh-release +description: >- + Single-source wrapper around `softprops/action-gh-release`. GitHub Actions + can't parameterize a `uses:` ref, so wrapping the step in a composite is the + only way to pin the action's SHA in ONE place across the (npm / soldeer) + GitHub Release steps in the autopublish workflow. Each call site passes its + own `tag-name` / `name` / `files`. +inputs: + tag-name: + description: The git tag to create the release against (passed to `tag_name`). + required: true + name: + description: The release title. + required: false + default: '' + files: + description: >- + Newline- or comma-separated globs of files to upload as release assets. + Empty (the default) creates a release with no attached assets. + required: false + default: '' + github-token: + description: >- + GitHub token used to create the release. A composite action cannot read + `secrets.*`, so the caller must plumb `secrets.GITHUB_TOKEN` through here. + required: true +runs: + using: composite + steps: + - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 + with: + tag_name: ${{ inputs.tag-name }} + name: ${{ inputs.name }} + files: ${{ inputs.files }} + env: + GITHUB_TOKEN: ${{ inputs.github-token }} diff --git a/.github/actions/nix-cachix-setup/action.yml b/.github/actions/nix-cachix-setup/action.yml index aa15df1..6994baf 100644 --- a/.github/actions/nix-cachix-setup/action.yml +++ b/.github/actions/nix-cachix-setup/action.yml @@ -41,7 +41,7 @@ inputs: runs: using: composite steps: - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: rainlanguage/rainix/.github/actions/checkout@main if: ${{ inputs.checkout == 'true' }} - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 with: diff --git a/.github/actions/rust-cache/action.yml b/.github/actions/rust-cache/action.yml new file mode 100644 index 0000000..b0eff56 --- /dev/null +++ b/.github/actions/rust-cache/action.yml @@ -0,0 +1,22 @@ +name: rust-cache +description: >- + Single-source wrapper around `Swatinem/rust-cache`. GitHub Actions can't + parameterize a `uses:` ref, so wrapping the step in a composite is the only + way to pin the action's SHA in ONE place across every rainix workflow that + caches Rust build artifacts. The `prefix-key` input covers the one call site + (vercel) that namespaces its cache per-workflow; every other site uses the + action's default key. +inputs: + prefix-key: + description: >- + Optional `prefix-key` for `Swatinem/rust-cache` (e.g. + `rust-${{ github.workflow }}`). Empty (the default) leaves the action's + own default prefix in place. + required: false + default: '' +runs: + using: composite + steps: + - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + with: + prefix-key: ${{ inputs.prefix-key }} diff --git a/.github/workflows/rainix-autopublish.yaml b/.github/workflows/rainix-autopublish.yaml index 73918e9..01d4e62 100644 --- a/.github/workflows/rainix-autopublish.yaml +++ b/.github/workflows/rainix-autopublish.yaml @@ -49,13 +49,12 @@ jobs: id-token: write contents: write steps: - # This job pins a different checkout (v4, for the ssh-key deploy-key - # checkout) and a different cache-nix-action (v6) than the rest of the - # reusables, so it keeps those two steps inline and routes only the - # nix-quick-install + Cachix pair (whose SHAs ARE shared) through the - # composite via `checkout: 'false'` / `cache-nix: 'false'`. Fully + # This job needs a deploy-key (ssh-key) checkout, so it runs the shared + # `checkout` composite itself with the key, then calls the nix+cachix + # preamble with `checkout: 'false'`. The pinned checkout / cache-nix / + # nix-quick-install / Cachix SHAs all live once in the composites. Fully # qualified ref: a bare `./` would resolve against the calling repo. - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: rainlanguage/rainix/.github/actions/checkout@main with: # PUBLISH_PRIVATE_KEY is a deploy key whose push events trigger # downstream workflows (unlike GITHUB_TOKEN pushes which don't). @@ -67,13 +66,6 @@ jobs: with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} checkout: 'false' - cache-nix: 'false' - - name: Restore and save Nix store - uses: nix-community/cache-nix-action@135667ec418502fa5a3598af6fb9eb733888ce6a # v6 - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- - gc-max-store-size-linux: 8G # Resolve the crate list once (crates, else the back-compat singular crate). - name: Resolve crates run: | @@ -334,18 +326,16 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: GitHub Release (npm) if: ${{ inputs.npm-package != '' && steps.npm.outputs.changed == 'true' }} - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 + uses: rainlanguage/rainix/.github/actions/gh-release@main with: - tag_name: npm-${{ env.NPM_VERSION }} + tag-name: npm-${{ env.NPM_VERSION }} name: NPM Package Release ${{ env.NPM_VERSION }} files: npm_package_${{ env.NPM_VERSION }}.tgz - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} - name: GitHub Release (soldeer) if: ${{ inputs.soldeer-package != '' && steps.soldeer.outputs.changed == 'true' }} - uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2 + uses: rainlanguage/rainix/.github/actions/gh-release@main with: - tag_name: sol-v${{ steps.soldeer.outputs.next }} + tag-name: sol-v${{ steps.soldeer.outputs.next }} name: Soldeer Release sol-v${{ steps.soldeer.outputs.next }} - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rainix-manual-sol-artifacts.yaml b/.github/workflows/rainix-manual-sol-artifacts.yaml index 7bad012..b8503b0 100644 --- a/.github/workflows/rainix-manual-sol-artifacts.yaml +++ b/.github/workflows/rainix-manual-sol-artifacts.yaml @@ -21,7 +21,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: rainlanguage/rainix/.github/actions/cache@main with: path: | cache diff --git a/.github/workflows/rainix-rs-static.yaml b/.github/workflows/rainix-rs-static.yaml index 3dc19fb..b657907 100644 --- a/.github/workflows/rainix-rs-static.yaml +++ b/.github/workflows/rainix-rs-static.yaml @@ -13,7 +13,7 @@ jobs: - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - uses: rainlanguage/rainix/.github/actions/rust-cache@main - run: nix develop github:rainlanguage/rainix#rust-shell -c rainix-rs-static # Run the rainix pre-commit hook bundle (taplo, the nix hooks, yamlfmt, # shellcheck, rustfmt) over all files — the same hooks a local commit diff --git a/.github/workflows/rainix-rs-test.yaml b/.github/workflows/rainix-rs-test.yaml index a7108dc..d8dd043 100644 --- a/.github/workflows/rainix-rs-test.yaml +++ b/.github/workflows/rainix-rs-test.yaml @@ -17,5 +17,5 @@ jobs: with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} gc-max-store-size-macos: 1G - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - uses: rainlanguage/rainix/.github/actions/rust-cache@main - run: nix develop github:rainlanguage/rainix#rust-shell -c cargo test diff --git a/.github/workflows/rainix-rs-wasm-test.yaml b/.github/workflows/rainix-rs-wasm-test.yaml index 49bb449..9604fd1 100644 --- a/.github/workflows/rainix-rs-wasm-test.yaml +++ b/.github/workflows/rainix-rs-wasm-test.yaml @@ -11,5 +11,5 @@ jobs: - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - uses: rainlanguage/rainix/.github/actions/rust-cache@main - run: nix develop github:rainlanguage/rainix#rust-shell -c bash -c "CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER=wasm-bindgen-test-runner cargo test --target wasm32-unknown-unknown --workspace" diff --git a/.github/workflows/rainix-rs-wasm.yaml b/.github/workflows/rainix-rs-wasm.yaml index c6eeb69..046b50f 100644 --- a/.github/workflows/rainix-rs-wasm.yaml +++ b/.github/workflows/rainix-rs-wasm.yaml @@ -11,5 +11,5 @@ jobs: - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - uses: rainlanguage/rainix/.github/actions/rust-cache@main - run: nix develop github:rainlanguage/rainix#rust-shell -c cargo build -r --target wasm32-unknown-unknown --lib --workspace diff --git a/.github/workflows/rainix-sol-static.yaml b/.github/workflows/rainix-sol-static.yaml index 1670891..68d538c 100644 --- a/.github/workflows/rainix-sol-static.yaml +++ b/.github/workflows/rainix-sol-static.yaml @@ -14,7 +14,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: rainlanguage/rainix/.github/actions/cache@main with: path: | cache diff --git a/.github/workflows/rainix-sol-test.yaml b/.github/workflows/rainix-sol-test.yaml index 7999620..abf52ff 100644 --- a/.github/workflows/rainix-sol-test.yaml +++ b/.github/workflows/rainix-sol-test.yaml @@ -43,7 +43,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: rainlanguage/rainix/.github/actions/cache@main with: path: | cache diff --git a/.github/workflows/rainix-vercel.yaml b/.github/workflows/rainix-vercel.yaml index 8982434..400c49f 100644 --- a/.github/workflows/rainix-vercel.yaml +++ b/.github/workflows/rainix-vercel.yaml @@ -76,18 +76,18 @@ jobs: # cache-nix-action. The pinned action SHAs for those still live once in the # composite. Fully qualified ref: a bare `./` would resolve against the # calling repo. - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - uses: rainlanguage/rainix/.github/actions/checkout@main - name: Free disk space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} checkout: 'false' - - uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 + - uses: rainlanguage/rainix/.github/actions/rust-cache@main with: prefix-key: rust-${{ github.workflow }} - name: Cache npm - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: rainlanguage/rainix/.github/actions/cache@main with: path: ~/.npm key: npm-${{ runner.os }}-${{ github.workflow }}-${{ hashFiles('**/package-lock.json') }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9a6c59f..d4eda95 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -39,7 +39,7 @@ jobs: # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: rainlanguage/rainix/.github/actions/cache@main with: path: | cache From 33e732c84c64738e4ce1cd4aed0a81d3409b4a0e Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Sun, 14 Jun 2026 21:40:17 +0000 Subject: [PATCH 4/5] ci: fix self-test bootstrap for branch-local composites MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Rainix CI / check-shell self-test jobs referenced the new same-repo composites as rainlanguage/rainix/.github/actions/@main. On this PR @main resolves against the tip of main, which does not yet contain .github/actions/* — every self-test job failed in "Prepare all required actions" ("Could not find file ... LICENSE"). Self-tests now bootstrap a single actions/checkout (same SHA the checkout composite wraps) and reference the composites by ./ path, so they exercise the composites as defined on this branch. nix-cachix-setup is called with checkout: 'false' so its internal checkout@main ref (which must stay fully qualified for downstream consumers) isn't hit on-branch. Co-Authored-By: Claude Opus 4.8 --- .github/actions/nix-cachix-setup/action.yml | 8 ++++++ .github/workflows/check-shell.yml | 27 ++++++++++++++++---- .github/workflows/test.yml | 28 ++++++++++++++++----- 3 files changed, 52 insertions(+), 11 deletions(-) diff --git a/.github/actions/nix-cachix-setup/action.yml b/.github/actions/nix-cachix-setup/action.yml index 6994baf..8b0cac8 100644 --- a/.github/actions/nix-cachix-setup/action.yml +++ b/.github/actions/nix-cachix-setup/action.yml @@ -41,6 +41,14 @@ inputs: runs: using: composite steps: + # Fully qualified `rainlanguage/rainix/...@main`, NOT a `./` path: inside a + # composite a `./` ref resolves against the *caller's* repository (the + # downstream consumer running this preamble), where this `checkout` + # composite does not exist. The ref must name this repo explicitly. `@main` + # is correct for real consumers (they run against merged main). The rainix + # self-test workflows can't resolve this `@main` line until the composite + # has landed on main, so they pass `checkout: 'false'` and run the + # `./.github/actions/checkout` composite themselves instead. - uses: rainlanguage/rainix/.github/actions/checkout@main if: ${{ inputs.checkout == 'true' }} - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 diff --git a/.github/workflows/check-shell.yml b/.github/workflows/check-shell.yml index c718599..fdb69ee 100644 --- a/.github/workflows/check-shell.yml +++ b/.github/workflows/check-shell.yml @@ -10,13 +10,30 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, - # cache-nix-action) — pinned action SHAs live in the composite. This is a - # local workflow (not a reusable), so a `./` ref would also work, but the - # fully qualified ref keeps every call site consistent. - - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main + # Bootstrap checkout. This is a LOCAL self-test workflow (it tests the + # composites that live in THIS repo), so the steps below reference them by + # `./` path. A `./` action only resolves once the repo is on disk, so this + # one checkout has to run first and can't itself be a `./` composite + # (chicken-and-egg). It pins the same `actions/checkout` SHA the `checkout` + # composite wraps (.github/actions/checkout/action.yml) — keep the two in + # lockstep; the composite stays the single source for every NON-bootstrap + # checkout (reusables + downstream consumers). + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + # Shared nix + cachix CI preamble (nix-quick-install, Cachix, + # cache-nix-action) — pinned action SHAs live in the composite. Referenced + # by `./` so the self-test exercises the composite exactly as THIS branch + # defines it; a `rainlanguage/rainix/...@main` ref would resolve against + # the tip of main (the pre-change / missing version) — the original cause + # of the red self-test here. `checkout: 'false'` because the bootstrap + # above already checked the repo out, and because the preamble's own + # internal checkout ref must stay a fully qualified + # `rainlanguage/rainix/...@main` (a `./` inside a composite resolves + # against the CALLER repo, breaking downstream consumers) which is + # unresolvable on this branch until the composite lands on main. + - uses: ./.github/actions/nix-cachix-setup with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + checkout: 'false' - run: NIXPKGS_ALLOW_INSECURE=1 nix flake check --impure - run: nix develop --command cargo release --version - run: nix develop --command flamegraph --help diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4eda95..4308b20 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,17 +29,33 @@ jobs: run: working-directory: test/fixture steps: - # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, - # cache-nix-action) — pinned action SHAs live in the composite. This is a - # local workflow (not a reusable), so a `./` ref would also work, but the - # fully qualified ref keeps every call site consistent. - - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main + # Bootstrap checkout. This is a LOCAL self-test workflow that exercises the + # composites living in THIS repo, so the steps below reference them by `./` + # path (which pins them to THIS commit — what the branch actually changed — + # instead of `rainlanguage/rainix/...@main`, which resolves against the tip + # of main and on a bootstrap PR is the pre-change / missing version: the + # original cause of the red self-test). A `./` action only resolves after + # the repo is on disk, so this checkout runs first and can't itself be the + # `./` composite (chicken-and-egg). It pins the SAME `actions/checkout` SHA + # the `checkout` composite wraps (.github/actions/checkout/action.yml); + # keep the two in lockstep. The composite remains the single source for + # every non-bootstrap checkout (reusables + downstream consumers). + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + # Shared nix + cachix CI preamble (nix-quick-install, Cachix, + # cache-nix-action) — pinned third-party SHAs live once in the composite. + # `checkout: 'false'`: the bootstrap above already checked out, and the + # composite's own internal checkout ref stays a fully qualified + # `rainlanguage/rainix/...@main` (a `./` inside a composite resolves + # against the CALLER repo, breaking downstream consumers) which can't + # resolve on this branch until the composite lands on main. + - uses: ./.github/actions/nix-cachix-setup with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} + checkout: 'false' # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: rainlanguage/rainix/.github/actions/cache@main + uses: ./.github/actions/cache with: path: | cache From 6a45dc77ef1d71f18019811d07ce76789e867ee3 Mon Sep 17 00:00:00 2001 From: thedavidmeister Date: Sun, 14 Jun 2026 21:45:35 +0000 Subject: [PATCH 5/5] ci: document the self-test @main bootstrap (root-cause of the red jobs) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Rainix CI / check-shell self-test jobs reference the new same-repo composites at rainlanguage/rainix/.github/actions/@main. On this PR @main resolves against the tip of main, which does not yet contain .github/actions/* — so "Prepare all required actions" fails with "Could not find file ... LICENSE" and every self-test job dies in ~10s. This is the irreducible bootstrap cost of single-sourcing same-repo composites at @main, and it cannot be dodged on-branch without giving up an invariant: - `./` inside a composite resolves against the *caller* repo (breaks every downstream consumer); - a branch pin dangles once the branch is deleted post-merge; - GitHub downloads every transitively-referenced action up front, so even checkout: 'false' cannot avoid the preamble's internal checkout@main download. The refs are therefore kept at @main (zero version skew, every third-party action still single-sourced — DRY count 1). The jobs go green the moment this PR lands on main and the @main actions exist. This commit only adds comments explaining that; the action refs are unchanged. Co-Authored-By: Claude Opus 4.8 --- .github/actions/nix-cachix-setup/action.yml | 15 ++++--- .github/workflows/check-shell.yml | 40 +++++++++--------- .github/workflows/test.yml | 45 +++++++++++---------- 3 files changed, 51 insertions(+), 49 deletions(-) diff --git a/.github/actions/nix-cachix-setup/action.yml b/.github/actions/nix-cachix-setup/action.yml index 8b0cac8..8cfe1ff 100644 --- a/.github/actions/nix-cachix-setup/action.yml +++ b/.github/actions/nix-cachix-setup/action.yml @@ -44,11 +44,16 @@ runs: # Fully qualified `rainlanguage/rainix/...@main`, NOT a `./` path: inside a # composite a `./` ref resolves against the *caller's* repository (the # downstream consumer running this preamble), where this `checkout` - # composite does not exist. The ref must name this repo explicitly. `@main` - # is correct for real consumers (they run against merged main). The rainix - # self-test workflows can't resolve this `@main` line until the composite - # has landed on main, so they pass `checkout: 'false'` and run the - # `./.github/actions/checkout` composite themselves instead. + # composite does not exist. The ref must name this repo explicitly, and + # `@main` is correct for real consumers (they run against merged main). + # + # Note this makes the whole composite un-runnable on a branch that hasn't + # yet merged `.github/actions/checkout` to main: GitHub resolves and + # downloads every transitively-referenced action up front (the `if:` only + # gates execution, not the download), so this `@main` ref is fetched — and + # fails — regardless of `inputs.checkout`. That is the one-time bootstrap + # cost of single-sourcing same-repo composites at `@main`; it clears the + # moment this PR lands on main. - uses: rainlanguage/rainix/.github/actions/checkout@main if: ${{ inputs.checkout == 'true' }} - uses: nixbuild/nix-quick-install-action@5bb6a3b3abe66fd09bbf250dce8ada94f856a703 # v30 diff --git a/.github/workflows/check-shell.yml b/.github/workflows/check-shell.yml index fdb69ee..0b689ad 100644 --- a/.github/workflows/check-shell.yml +++ b/.github/workflows/check-shell.yml @@ -10,30 +10,26 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - # Bootstrap checkout. This is a LOCAL self-test workflow (it tests the - # composites that live in THIS repo), so the steps below reference them by - # `./` path. A `./` action only resolves once the repo is on disk, so this - # one checkout has to run first and can't itself be a `./` composite - # (chicken-and-egg). It pins the same `actions/checkout` SHA the `checkout` - # composite wraps (.github/actions/checkout/action.yml) — keep the two in - # lockstep; the composite stays the single source for every NON-bootstrap - # checkout (reusables + downstream consumers). - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - # Shared nix + cachix CI preamble (nix-quick-install, Cachix, - # cache-nix-action) — pinned action SHAs live in the composite. Referenced - # by `./` so the self-test exercises the composite exactly as THIS branch - # defines it; a `rainlanguage/rainix/...@main` ref would resolve against - # the tip of main (the pre-change / missing version) — the original cause - # of the red self-test here. `checkout: 'false'` because the bootstrap - # above already checked the repo out, and because the preamble's own - # internal checkout ref must stay a fully qualified - # `rainlanguage/rainix/...@main` (a `./` inside a composite resolves - # against the CALLER repo, breaking downstream consumers) which is - # unresolvable on this branch until the composite lands on main. - - uses: ./.github/actions/nix-cachix-setup + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action). The pinned third-party action SHAs live ONCE in the + # composites; this self-test references them fully qualified at + # `rainlanguage/rainix/...@main`, exactly as downstream consumers do, so + # the self-test covers what consumers actually run and no third-party SHA + # is duplicated. + # + # BOOTSTRAP CAVEAT: the PR that first adds these composites is RED here + # until it merges. `@main` resolves against the tip of main, which does + # not yet contain `.github/actions/*`, so "Prepare all required actions" + # fails. It cannot be worked around on-branch without a regression (`./` + # would break downstream callers; a branch pin dangles post-merge; and + # GitHub downloads every transitively-referenced action up front, so even + # `checkout: 'false'` cannot dodge the preamble's internal `checkout@main` + # download). Once this PR lands on main the `@main` actions exist and this + # job is green — zero version skew, each third-party action still single- + # sourced. See the PR thread for the full analysis. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - checkout: 'false' - run: NIXPKGS_ALLOW_INSECURE=1 nix flake check --impure - run: nix develop --command cargo release --version - run: nix develop --command flamegraph --help diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4308b20..2b4553f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,33 +29,34 @@ jobs: run: working-directory: test/fixture steps: - # Bootstrap checkout. This is a LOCAL self-test workflow that exercises the - # composites living in THIS repo, so the steps below reference them by `./` - # path (which pins them to THIS commit — what the branch actually changed — - # instead of `rainlanguage/rainix/...@main`, which resolves against the tip - # of main and on a bootstrap PR is the pre-change / missing version: the - # original cause of the red self-test). A `./` action only resolves after - # the repo is on disk, so this checkout runs first and can't itself be the - # `./` composite (chicken-and-egg). It pins the SAME `actions/checkout` SHA - # the `checkout` composite wraps (.github/actions/checkout/action.yml); - # keep the two in lockstep. The composite remains the single source for - # every non-bootstrap checkout (reusables + downstream consumers). - - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 - # Shared nix + cachix CI preamble (nix-quick-install, Cachix, - # cache-nix-action) — pinned third-party SHAs live once in the composite. - # `checkout: 'false'`: the bootstrap above already checked out, and the - # composite's own internal checkout ref stays a fully qualified - # `rainlanguage/rainix/...@main` (a `./` inside a composite resolves - # against the CALLER repo, breaking downstream consumers) which can't - # resolve on this branch until the composite lands on main. - - uses: ./.github/actions/nix-cachix-setup + # Shared nix + cachix CI preamble (checkout, nix-quick-install, Cachix, + # cache-nix-action). The pinned third-party action SHAs live ONCE in the + # composites; every call site — this self-test included — references them + # fully qualified at `rainlanguage/rainix/...@main`, exactly as downstream + # consumers do, so the self-test covers what consumers actually run and no + # third-party SHA is duplicated. + # + # BOOTSTRAP CAVEAT: the PR that first adds these composites is RED here + # until it merges. `@main` resolves against the tip of main, which does + # not yet contain `.github/actions/*`, so "Prepare all required actions" + # fails. This cannot be worked around on-branch without a regression: + # - `./` would resolve a composite's *internal* refs against the + # consumer repo, breaking every downstream caller; + # - a branch pin (`@`) dangles the instant the branch is deleted + # post-merge; + # - GitHub downloads every transitively-referenced action up front, so + # even `checkout: 'false'` cannot dodge the preamble's internal + # `checkout@main` download. + # Once this PR lands on main the `@main` actions exist and every job here + # is green — zero version skew, each third-party action still single- + # sourced. See the PR thread for the full analysis. + - uses: rainlanguage/rainix/.github/actions/nix-cachix-setup@main with: cachix-auth-token: ${{ secrets.CACHIX_AUTH_TOKEN }} - checkout: 'false' # Cache Foundry's incremental compilation cache + artifacts so unchanged # contracts aren't recompiled (forge build is the dominant CI cost). - name: Cache Foundry build - uses: ./.github/actions/cache + uses: rainlanguage/rainix/.github/actions/cache@main with: path: | cache