UNPKG

@sebastienrousseau/dotfiles

Version:

The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.

122 lines (92 loc) 5.2 kB
--- render_with_liquid: false --- # CI Dependency Pinning Policy Every external dependency the CI pipeline consumes must be pinned by 40-hex commit SHA. The policy applies to: 1. **Third-party actions**`uses: owner/action@<sha>` (already enforced via Scorecard's `Pinned-Dependencies` check at score ≥ 9). 2. **Reusable workflows in this repo**`uses: sebastienrousseau/dotfiles/.github/workflows/reusable-X.yml@<sha>` (added with [#855](https://github.com/sebastienrousseau/dotfiles/issues/855); enforced by `tools/ci/lint-reusable-pins.sh`). 3. **Container base images**`FROM image:tag@sha256:<digest>` (closed by [#886](https://github.com/sebastienrousseau/dotfiles/pull/886)). 4. **Release binaries downloaded at build time**`curl … && echo "<sha256> ..." | sha256sum -c` (closed by [#888](https://github.com/sebastienrousseau/dotfiles/pull/888)). ## Why SHA-pin reusable workflows When `ci.yml` calls a reusable via `./.github/workflows/reusable-X.yml`, GitHub resolves the reusable from the **same ref as the calling workflow at run time**. For an in-repo PR that's the PR's branch — fine. The risk is the inverse: a malicious push to `master` (or any ref the calling workflow might resolve from) can swap reusable content under a CI run, with no audit trail in the PR diff. Pinning to a 40-hex SHA freezes the reusable's content at the pinned commit. To swap the reusable, you have to bump every call site — visible in the PR diff, reviewable, revertible. ## Acceptable forms ```yaml # Acceptable — full SHA pin. uses: sebastienrousseau/dotfiles/.github/workflows/reusable-shell-lint.yml@b0615f8fb5c0f3826f58904a5567eff11b6c500e # master ``` The trailing comment is a human-readable hint at what the SHA represented when it was pinned (typically `master`, sometimes a tag like `v0.2.501`). The hint is documentation only — the SHA is what GitHub uses. ## Rejected forms ```yaml # Rejected — relative path is a mutable ref. uses: ./.github/workflows/reusable-shell-lint.yml # Rejected — branch ref is mutable. uses: sebastienrousseau/dotfiles/.github/workflows/reusable-shell-lint.yml@master # Rejected — tag ref is mutable (tags can be moved). uses: sebastienrousseau/dotfiles/.github/workflows/reusable-shell-lint.yml@v0.2.501 ``` The `lint-reusable-pins` job in `ci.yml` runs `tools/ci/lint-reusable-pins.sh` on every workflow change. The lint fails the build on any of the rejected forms above. ## Refreshing pinned SHAs `bump-reusable-pins.yml` handles this automatically. On every push to `master` that touches `.github/workflows/reusable-*.yml`, the bot scans caller workflows for stale pins and opens a PR bumping them to the new SHA. Signed with `ACTIONS_BOT_SIGNING_KEY` so the resulting commit passes `Verify Commit Signatures`. The manual recipe below stays here as a fallback — for example, if you need to bump pins before a merge to master, or if the bot's run failed and you want to short-circuit waiting for the next push trigger. ```sh # 1. Land the change to the reusable on master via a PR. # 2. After merge, capture the new master SHA: git fetch origin master PIN=$(git rev-parse origin/master) echo "$PIN" # 3. Bump every call site: find .github/workflows -name '*.yml' -exec sed -i.bak -E \ "s|(/reusable-[a-z0-9-]+\.yml@)[0-9a-f]{40}|\\1${PIN}|g" {} + rm -f .github/workflows/*.bak # 4. Verify the lint still passes: bash tools/ci/lint-reusable-pins.sh # 5. Land the bump on a follow-up PR with a single-purpose commit: git commit -am "chore(ci): bump reusable-workflow pins to ${PIN:0:10}" ``` Whether bumped by the bot or by hand, the resulting PR runs the full CI suite — a reviewer still confirms the new reusable content is intentional before merge. ## Dependabot Dependabot's `github-actions` ecosystem **does not** support same-repo reusable workflow SHA bumps as of May 2026 — it only updates references to external actions. Same-repo reusables are tracked manually via the recipe above. The Dependabot config in `.github/dependabot.yml` covers the external dimension; this document covers the in-repo one. If GitHub ships native Dependabot support for reusable workflows, delete this section and switch to `package-ecosystem: github-actions` with `directory: /.github/workflows`. Track on [github/feedback#10539](https://github.com/orgs/community/discussions/10539). ## Negative test `tests/unit/ci/test_reusable_pin_lint.sh` deliberately drops an unpinned reusable reference into a sandboxed workflow tree and asserts that `lint-reusable-pins.sh` exits non-zero with the expected error message. The test runs as part of the standard test suite — a regression in the lint catches at PR time, not at merge time. ## See also - [#855](https://github.com/sebastienrousseau/dotfiles/issues/855) — original tracking issue. - `tools/ci/lint-reusable-pins.sh` — the enforcement script. - `tests/unit/ci/test_reusable_pin_lint.sh` — the negative test. - `.github/workflows/bump-reusable-pins.yml` — the auto-bump bot. - [GitHub: pinning actions to a full-length commit SHA](https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-third-party-actions).