Skip to content

chore(ci): add pinact pre-commit hook to enforce SHA-pinned actions - #2509

Merged
ralphbean merged 3 commits into
mainfrom
chore/pinact-precommit-hook
Jun 24, 2026
Merged

chore(ci): add pinact pre-commit hook to enforce SHA-pinned actions#2509
ralphbean merged 3 commits into
mainfrom
chore/pinact-precommit-hook

Conversation

@ralphbean

Copy link
Copy Markdown
Member

Summary

  • Add a pre-commit hook that runs pinact run --fix=false --no-api to verify all GitHub Actions references use full-length commit SHAs
  • Install pinact (v4.1.0, checksum-verified) in the CI lint workflow

The --no-api flag ensures the check is purely syntactic (40-char SHA presence) — it won't break when new action versions are released upstream.

Dependencies

Test plan

  • pre-commit run pinact --all-files passes locally
  • CI lint job passes with pinact installed

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown

Site preview

Preview: https://fc1a979b-site.fullsend-ai.workers.dev

Commit: 75b0606ee8f8e09a1434cb9aa988028f9e6dbcd8

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 2:56 PM UTC · Completed 3:08 PM UTC
Commit: f64eecd · View workflow run →

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .github/workflows/renovate.yml, .pre-commit-config.yaml — All changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.
Previous run

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .github/workflows/renovate.yml, .pre-commit-config.yaml — All changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [logic error / coverage gap] .pre-commit-config.yaml:63 — The pinact pre-commit hook's files regex only matches .github/workflows/ and internal/scaffold/fullsend-repo/.github/workflows/, but .pinact.yaml also configures pinact to scan .github/actions/*/action.yml (line 8). At least one composite action (.github/actions/setup-gcp/action.yml) contains an external uses: reference (google-github-actions/auth@...). Edits to composite actions under .github/actions/ will not trigger the pre-commit hook, so unpinned action references could be introduced without the hook catching them.
    Remediation: Add |\.github/actions/ to the files regex in the pinact pre-commit hook definition so it matches all paths that .pinact.yaml covers.

Labels: PR enforces SHA-pinning of GitHub Actions as a supply chain security hardening measure.

Previous run (2)

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .github/workflows/renovate.yml, .pre-commit-config.yaml — All changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [error handling / runtime mechanism] Makefile — The bootstrap target installs every other language: system tool used by pre-commit hooks (lychee, actionlint, gitleaks, ruff, ty, pre-commit itself) but does not install pinact. After running make bootstrap && pre-commit run --all-files on a fresh checkout, the new pinact hook will fail with "command not found". The PR body notes dependency on feat(scaffold): auto-detect and install pre-commit tool dependencies #1055 for auto-detection, but until that lands, local dev is broken for the pinact hook.
    Remediation: Add a pinact installation step to the bootstrap target in the Makefile, mirroring the pattern used for lychee (curl, sha256sum verify, tar extract to $BOOTSTRAP_BIN_DIR).

  • [logic error / coverage gap] .pre-commit-config.yaml:63 — The pinact pre-commit hook's files regex only matches .github/workflows/ and internal/scaffold/fullsend-repo/.github/workflows/, but .pinact.yaml also configures pinact to scan .github/actions/*/action.yml. There are four composite action directories under .github/actions/ (check-e2e-authorization, mint-token, setup-gcp, validate-enrollment). Edits to those files will not trigger the pre-commit hook, so unpinned action references could be introduced without the hook catching them.
    Remediation: Add |\.github/actions/ to the files regex in the pinact pre-commit hook definition so it matches all paths that .pinact.yaml covers.

Previous run (3)

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .pre-commit-config.yaml — Both changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [error handling / runtime mechanism] Makefile — The bootstrap target installs every other language: system tool used by pre-commit hooks (lychee, actionlint, gitleaks, ruff, ty, pre-commit itself) but does not install pinact. After running make bootstrap && pre-commit run --all-files on a fresh checkout, the new pinact hook will fail with "command not found". The PR body notes dependency on feat(scaffold): auto-detect and install pre-commit tool dependencies #1055 for auto-detection, but until that lands, local dev is broken for the pinact hook.
    Remediation: Add a pinact installation step to the bootstrap target in the Makefile, mirroring the pattern used for lychee (curl, sha256sum verify, tar extract to $BOOTSTRAP_BIN_DIR).
Previous run (4)

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .pre-commit-config.yaml — Both changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [error handling / runtime mechanism] Makefile — The bootstrap target installs every other language: system tool used by pre-commit hooks (lychee, actionlint, gitleaks, ruff, ty, pre-commit itself) but does not install pinact. After running make bootstrap && pre-commit run --all-files on a fresh checkout, the new pinact hook will fail with "command not found". The PR body notes dependency on feat(scaffold): auto-detect and install pre-commit tool dependencies #1055 for auto-detection, but until that lands, local dev is broken for the pinact hook.
    Remediation: Add a pinact installation step to the bootstrap target in the Makefile, mirroring the pattern used for lychee (curl, sha256sum verify, tar extract to $BOOTSTRAP_BIN_DIR).
Previous run

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .pre-commit-config.yaml — Both changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [error handling / runtime mechanism] Makefile — The bootstrap target installs every other language: system tool used by pre-commit hooks (lychee, actionlint, gitleaks, ruff, ty, pre-commit itself) but does not install pinact. After running make bootstrap && pre-commit run --all-files on a fresh checkout, the pinact hook will fail with "command not found". The PR body notes dependency on feat(scaffold): auto-detect and install pre-commit tool dependencies #1055 for auto-detection, but until that lands, local dev is broken.
    Remediation: Add a pinact install step to the bootstrap target in the Makefile, mirroring the curl+checksum+tar pattern used for lychee.

  • [incomplete-implementation] .pre-commit-config.yaml:60 — The pinact hook enforces SHA-pinned actions, but the repository is not yet SHA-pinned. Only sandbox-images.yml uses SHA-pinned actions; the other 15 workflow files contain 56 semver-pinned action references. Enabling this hook without first SHA-pinning will cause immediate pre-commit failures on any workflow file change.
    Remediation: Ensure PR chore(ci): pin all GitHub Actions to full-length commit SHAs #2508 (SHA-pinning the actions) merges before this PR, or adjust sequencing so the enforcement hook is added only after the repository is compliant.


Labels: PR modifies CI workflow and pre-commit configuration for SHA-pinning enforcement.

Previous run (5)

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .pre-commit-config.yaml — Both changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [error handling / runtime mechanism] Makefile — The bootstrap target installs every other language: system tool used by pre-commit hooks (lychee, actionlint, gitleaks, ruff, ty, pre-commit itself) but does not install pinact. After running make bootstrap && pre-commit run --all-files on a fresh checkout, the new pinact hook will fail with "command not found". The PR body notes dependency on feat(scaffold): auto-detect and install pre-commit tool dependencies #1055 for auto-detection, but until that lands, local dev is broken for the pinact hook.
    Remediation: Add a pinact installation step to the bootstrap target in the Makefile, mirroring the pattern used for lychee (curl, sha256sum verify, tar extract to $BOOTSTRAP_BIN_DIR).

Low

  • [installation-consistency] .github/workflows/lint.yml:39 — The pinact tar command uses tar xzf /tmp/pinact.tar.gz -C /usr/local/bin pinact which differs from the lychee installation pattern tar xzf /tmp/lychee.tar.gz -C /usr/local/bin --strip-components=1 lychee-x86_64-unknown-linux-gnu/lychee. This is correct behavior since the upstream tarballs have different internal structures — not an actual inconsistency.
Previous run (6)

Review

Findings

High

  • [protected-path] .github/workflows/lint.yml, .pre-commit-config.yaml — Both changed files are under protected paths (.github/, .pre-commit-config.yaml). The PR has no linked issue providing justification for modifying governance/infrastructure files. Human approval is always required for protected-path changes.
    Remediation: Link a valid issue that authorizes the protected-path changes.

Medium

  • [error handling / runtime mechanism] Makefile — The bootstrap target installs every other language: system tool used by pre-commit hooks (lychee, actionlint, gitleaks, ruff, ty, pre-commit itself) but does not install pinact. After running make bootstrap && pre-commit run --all-files on a fresh checkout, the pinact hook will fail with "command not found". The PR body notes dependency on feat(scaffold): auto-detect and install pre-commit tool dependencies #1055 for auto-detection, but until that lands, local dev is broken.
    Remediation: Add a pinact install step to the bootstrap target in the Makefile, mirroring the curl+checksum+tar pattern used for lychee.

  • [incomplete-implementation] .pre-commit-config.yaml:60 — The pinact hook enforces SHA-pinned actions, but the repository is not yet SHA-pinned. Only sandbox-images.yml uses SHA-pinned actions; the other 15 workflow files contain 56 semver-pinned action references. Enabling this hook without first SHA-pinning will cause immediate pre-commit failures on any workflow file change.
    Remediation: Ensure PR chore(ci): pin all GitHub Actions to full-length commit SHAs #2508 (SHA-pinning the actions) merges before this PR, or adjust sequencing so the enforcement hook is added only after the repository is compliant.

Low

  • [missing-authorization] .pre-commit-config.yaml — No linked issue provides authorization for this change. The PR body references PR chore(ci): pin all GitHub Actions to full-length commit SHAs #2508 and issue feat(scaffold): auto-detect and install pre-commit tool dependencies #1055, but neither could be resolved. The PR is marked as draft and the change is a CI infrastructure improvement, so this is noted for visibility rather than as a blocker.

  • [hook-organization] .pre-commit-config.yaml:60 — The pinact hook is placed in a new repo: local block rather than being added to the existing local hooks block. The codebase already has multiple repo: local blocks, so this is a minor inconsistency rather than a pattern violation.

  • [scope-clarity] .pre-commit-config.yaml:64 — The pinact hook's file pattern matches both .github/workflows/ and internal/scaffold/fullsend-repo/.github/workflows/, but the scaffold workflows currently have 0 SHA-pinned actions. The PR description does not mention the scaffold scope.

  • [installation-consistency] .github/workflows/lint.yml:39 — The pinact tar command differs from the lychee installation pattern (--strip-components=1). This is correct behavior since the tarballs have different internal structures — not an actual inconsistency.

  • [edge case / regex correctness] .pre-commit-config.yaml — The files regex does not match internal/scaffold/fullsend-repo/templates/, which the actionlint hook covers. No workflow YAML files currently exist under that path, so there is no gap today.


Labels: PR modifies CI workflow and pre-commit configuration for SHA-pinning enforcement.

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread .pre-commit-config.yaml
- id: shellcheck
args: ["-x", "-e", "SC1091,SC2001,SC2016"]

- repo: local

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] incomplete-implementation

The pinact hook enforces SHA-pinned actions, but the repository is not yet SHA-pinned. Only sandbox-images.yml uses SHA-pinned actions; the other 15 workflow files contain 56 semver-pinned action references. Enabling this hook without first SHA-pinning will cause immediate pre-commit failures.

Suggested fix: Ensure PR #2508 (SHA-pinning the actions) merges before this PR, or adjust sequencing so the enforcement hook is added only after the repository is compliant.

Comment thread .pre-commit-config.yaml
- id: shellcheck
args: ["-x", "-e", "SC1091,SC2001,SC2016"]

- repo: local

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] hook-organization

The pinact hook is placed in a new repo: local block rather than being added to the existing local hooks block. The codebase already has multiple repo: local blocks, so this is a minor inconsistency.

Comment thread .pre-commit-config.yaml
hooks:
- id: pinact
name: pinact (SHA-pin check)
entry: pinact run --fix=false --no-api

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] scope-clarity

The pinact hook file pattern matches both .github/workflows/ and internal/scaffold/fullsend-repo/.github/workflows/, but the scaffold workflows currently have 0 SHA-pinned actions. The PR description does not mention the scaffold scope.

echo "1f4e0ef7f6554a6ed33dd7ac144fb2e1bbed98598e7af973042fc5cd43951c9a /tmp/lychee.tar.gz" | sha256sum -c
tar xzf /tmp/lychee.tar.gz -C /usr/local/bin --strip-components=1 lychee-x86_64-unknown-linux-gnu/lychee

- name: Install pinact

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] installation-consistency

The pinact tar command differs from the lychee installation pattern (--strip-components=1). This is correct behavior since the tarballs have different internal structures.

@fullsend-ai-review fullsend-ai-review Bot added component/ci CI pipelines and checks type/chore Maintenance and housekeeping tasks labels Jun 22, 2026
@ralphbean
ralphbean force-pushed the pin-actions-to-sha branch from 9aa8f24 to 0b6dea8 Compare June 22, 2026 21:32
@ralphbean
ralphbean force-pushed the chore/pinact-precommit-hook branch from f64eecd to 4fef525 Compare June 22, 2026 23:00
@ralphbean
ralphbean marked this pull request as ready for review June 22, 2026 23:00
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

CI: add pinact pre-commit hook to enforce SHA-pinned GitHub Actions
⚙️ Configuration changes ✨ Enhancement 🕐 10-20 Minutes

Grey Divider

Description

• Add a local pre-commit hook to validate GitHub Actions use full-length SHA refs.
• Install checksum-verified pinact in the CI lint workflow so the hook runs in CI.
• Scope pinact checks to workflow directories and run offline-only via --no-api.
Diagram

graph TD
  A["Developer or CI"] --> B["pre-commit hook: pinact"] --> C["pinact run --fix=false --no-api"] --> D["Workflow YAML files"]
  E["CI lint job"] --> F["Install pinact v4.1.0"] --> B
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. CI-only enforcement (pinact as workflow step)
  • ➕ No local toolchain dependency for contributors
  • ➕ Single enforcement point in CI
  • ➖ Issues are found later (post-push), slowing feedback
  • ➖ Doesn’t ensure local changes remain compliant before commit
2. Use a dedicated pinning GitHub Action instead of installing pinact
  • ➕ Less custom curl/tar logic in the workflow
  • ➕ Potentially simpler upgrades via action versioning
  • ➖ Still needs its own pinning/verification story to avoid circular trust
  • ➖ May be less flexible than the same tool used in pre-commit
3. Custom grep/script to enforce 40-char SHAs
  • ➕ No external binary to install
  • ➕ Very small implementation surface area
  • ➖ More likely to miss edge cases (matrix/expressions, reusable workflows, uncommon syntaxes)
  • ➖ Ongoing maintenance burden vs. using purpose-built tooling

Recommendation: The current approach (pre-commit hook + CI installation of a checksum-verified pinact binary) is the best tradeoff: it provides fast local feedback, consistent CI enforcement, and avoids network fragility by using --no-api. Ensure the dependency on tooling auto-detection (#1055) is satisfied so pinact is reliably available in all CI/sandbox environments.

Files changed (2) +19 / -0

Other (2) +19 / -0
lint.ymlInstall checksum-verified pinact in CI lint workflow +6/-0

Install checksum-verified pinact in CI lint workflow

• Adds a CI step to download pinact v4.1.0, verify its SHA-256 checksum, and install it into /usr/local/bin. This ensures the new pre-commit pinact hook can run successfully in the lint job environment.

.github/workflows/lint.yml

.pre-commit-config.yamlAdd local pre-commit hook to enforce SHA-pinned GitHub Actions +13/-0

Add local pre-commit hook to enforce SHA-pinned GitHub Actions

• Introduces a local system-language pre-commit hook that runs 'pinact run --fix=false --no-api' to validate SHA pinning. Limits enforcement to workflow directories and disables filename passing to let pinact handle discovery.

.pre-commit-config.yaml

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 51 rules

Grey Divider


Action required

1. Pinact not installed everywhere 🐞 Bug ☼ Reliability
Description
The new pre-commit pinact hook is configured with language: system, so any environment running
pre-commit must have the pinact binary on PATH, but the repo’s bootstrap and agent post-scripts
that invoke pre-commit don’t install it. This can break make lint-all (after make bootstrap) and
the post-code/post-fix authoritative pre-commit checks with Executable "pinact" not found.
Code

.pre-commit-config.yaml[R62-66]

+      - id: pinact
+        name: pinact (SHA-pin check)
+        entry: pinact run --fix=false --no-api
+        language: system
+        files: |
Relevance

⭐⭐⭐ High

Team previously fixed missing system-hook binaries by installing them in bootstrap/post-scripts
(lychee, uvx). Likely same for pinact.

PR-#831
PR-#843
PR-#96

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The hook is explicitly configured to execute the pinact binary from the system PATH. CI installs
pinact before make lint-all, but the repo’s standard bootstrap and the agent post-scripts both run
pre-commit without installing pinact, so those flows will fail when the hook runs.

.pre-commit-config.yaml[60-71]
.github/workflows/lint.yml[30-46]
Makefile[37-77]
internal/scaffold/fullsend-repo/scripts/post-code.sh[268-336]
internal/scaffold/fullsend-repo/scripts/post-fix.sh[183-245]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A new pre-commit hook runs `pinact` as a system-installed binary (`language: system`). CI installs pinact in `.github/workflows/lint.yml`, but other common execution paths that run `pre-commit` (developer bootstrap + agent post-scripts) do not install pinact, causing those paths to fail with a missing executable.

## Issue Context
- `make bootstrap` claims to install the tools needed for pre-commit workflows.
- Agent runner post-scripts (`post-code.sh`, `post-fix.sh`) run an “authoritative pre-commit” on changed files and currently install other required system tools (e.g., lychee, uv) but not pinact.

## Fix Focus Areas
- Add a pinned, checksum-verified pinact install to the developer bootstrap flow:
 - Makefile[37-77]
- Add a pinned, checksum-verified pinact install (arch-aware like lychee) before running `pre-commit` in agent runner scripts:
 - internal/scaffold/fullsend-repo/scripts/post-code.sh[268-336]
 - internal/scaffold/fullsend-repo/scripts/post-fix.sh[183-245]

(Optionally, if you want pinact available in sandboxes without network, bake it into the relevant image Containerfile(s) too.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread .pre-commit-config.yaml
Comment on lines +62 to +66
- id: pinact
name: pinact (SHA-pin check)
entry: pinact run --fix=false --no-api
language: system
files: |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Pinact not installed everywhere 🐞 Bug ☼ Reliability

The new pre-commit pinact hook is configured with language: system, so any environment running
pre-commit must have the pinact binary on PATH, but the repo’s bootstrap and agent post-scripts
that invoke pre-commit don’t install it. This can break make lint-all (after make bootstrap) and
the post-code/post-fix authoritative pre-commit checks with Executable "pinact" not found.
Agent Prompt
## Issue description
A new pre-commit hook runs `pinact` as a system-installed binary (`language: system`). CI installs pinact in `.github/workflows/lint.yml`, but other common execution paths that run `pre-commit` (developer bootstrap + agent post-scripts) do not install pinact, causing those paths to fail with a missing executable.

## Issue Context
- `make bootstrap` claims to install the tools needed for pre-commit workflows.
- Agent runner post-scripts (`post-code.sh`, `post-fix.sh`) run an “authoritative pre-commit” on changed files and currently install other required system tools (e.g., lychee, uv) but not pinact.

## Fix Focus Areas
- Add a pinned, checksum-verified pinact install to the developer bootstrap flow:
  - Makefile[37-77]
- Add a pinned, checksum-verified pinact install (arch-aware like lychee) before running `pre-commit` in agent runner scripts:
  - internal/scaffold/fullsend-repo/scripts/post-code.sh[268-336]
  - internal/scaffold/fullsend-repo/scripts/post-fix.sh[183-245]

(Optionally, if you want pinact available in sandboxes without network, bake it into the relevant image Containerfile(s) too.)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 22, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:04 PM UTC · Completed 11:13 PM UTC
Commit: 4fef525 · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

echo "1f4e0ef7f6554a6ed33dd7ac144fb2e1bbed98598e7af973042fc5cd43951c9a /tmp/lychee.tar.gz" | sha256sum -c
tar xzf /tmp/lychee.tar.gz -C /usr/local/bin --strip-components=1 lychee-x86_64-unknown-linux-gnu/lychee

- name: Install pinact

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[low] installation-consistency

The pinact tar command omits --strip-components unlike the lychee installation. This is correct behavior since the upstream tarballs have different internal structures.

Base automatically changed from pin-actions-to-sha to main June 23, 2026 18:11
@ralphbean
ralphbean force-pushed the chore/pinact-precommit-hook branch from 4fef525 to 693ed6a Compare June 23, 2026 18:28
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 23, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:31 PM UTC · Completed 6:43 PM UTC
Commit: 693ed6a · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

@fullsend-ai-review

fullsend-ai-review Bot commented Jun 23, 2026

Copy link
Copy Markdown

🤖 Review · ❌ Terminated · Started 6:59 PM UTC · Ended 7:10 PM UTC
Commit: 6bd5f3a · View workflow run →

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread .pre-commit-config.yaml
- repo: local
hooks:
- id: pinact
name: pinact (SHA-pin check)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] logic error / coverage gap

The pinact pre-commit hook files regex only matches .github/workflows/ and internal/scaffold/fullsend-repo/.github/workflows/, but .pinact.yaml also configures pinact to scan .github/actions/*/action.yml. There are four composite action directories under .github/actions/. Edits to those files will not trigger the pre-commit hook, so unpinned action references could be introduced without the hook catching them.

Suggested fix: Add |.github/actions/ to the files regex in the pinact pre-commit hook definition so it matches all paths that .pinact.yaml covers.

@fullsend-ai-review

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 6:59 PM UTC · Completed 7:10 PM UTC
Commit: a62ae64 · View workflow run →

@ralphbean
ralphbean enabled auto-merge June 24, 2026 10:35
ralphbean and others added 2 commits June 24, 2026 06:35
Add a pre-commit hook that runs `pinact run --fix=false --no-api` to
verify all GitHub Actions references use full-length commit SHAs. The
--no-api flag ensures the check is offline-only (syntactic SHA presence)
so it won't break when new action versions are released.

Also install pinact in the CI lint workflow so the hook passes there.

Depends-on: #1055 (auto-detect pre-commit tool dependencies)

Assisted-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
The new pinact pre-commit hook correctly caught these unpinned actions.

Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 10:38 AM UTC · Completed 10:49 AM UTC
Commit: 5aefa4f · View workflow run →

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Comment thread .pre-commit-config.yaml
- repo: local
hooks:
- id: pinact
name: pinact (SHA-pin check)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[medium] logic error / coverage gap

The pinact pre-commit hook files regex only matches .github/workflows/ and internal/scaffold/fullsend-repo/.github/workflows/, but .pinact.yaml also configures pinact to scan .github/actions/*/action.yml. At least one composite action (.github/actions/setup-gcp/action.yml) contains an external uses: reference. Edits to composite actions under .github/actions/ will not trigger the pre-commit hook, so unpinned action references could be introduced without the hook catching them.

Suggested fix: Add |.github/actions/ to the files regex in the pinact pre-commit hook definition so it matches all paths that .pinact.yaml covers.

@fullsend-ai-review fullsend-ai-review Bot added the security Security threat model and related concerns label Jun 24, 2026
@ralphbean
ralphbean added this pull request to the merge queue Jun 24, 2026
Add pinact installation to `make bootstrap` so local devs get the
SHA-pin checker without manual setup. Expand the pre-commit hook's
files regex to also match `.github/actions/`, aligning it with the
paths configured in `.pinact.yaml`.

Assisted-by: Claude claude-opus-4-6 <noreply@anthropic.com>
Signed-off-by: Ralph Bean <rbean@redhat.com>
@ralphbean
ralphbean removed this pull request from the merge queue due to a manual request Jun 24, 2026
@ralphbean
ralphbean enabled auto-merge June 24, 2026 11:04
@fullsend-ai-review

fullsend-ai-review Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 11:07 AM UTC · Completed 11:18 AM UTC
Commit: 75b0606 · View workflow run →

@ralphbean
ralphbean added this pull request to the merge queue Jun 24, 2026

@fullsend-ai-review fullsend-ai-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the review comment for full details.

Merged via the queue into main with commit 249e0a0 Jun 24, 2026
14 checks passed
@ralphbean
ralphbean deleted the chore/pinact-precommit-hook branch June 24, 2026 11:22
@fullsend-ai-retro

fullsend-ai-retro Bot commented Jun 24, 2026

Copy link
Copy Markdown

🤖 Finished Retro · ✅ Success · Started 11:26 AM UTC · Completed 11:35 AM UTC
Commit: 75b0606 · View workflow run →

@fullsend-ai-retro

Copy link
Copy Markdown

Retro: PR #2509chore(ci): add pinact pre-commit hook

What happened: A human-authored, 27-line, 4-file chore PR received 6 consecutive CHANGES_REQUESTED reviews from the review bot over 2 days (June 22–24), plus reviews from qodo. The bot repeated the .github/actions/ coverage gap finding identically across reviews #4 and #5 on unchanged code. After a human (ifireball) approved and the author pushed a fix addressing the bot's feedback, the bot submitted yet another CHANGES_REQUESTED review 15 minutes before merge. In total, 16 shim workflow runs fired for this PR — many triggered by pull_request_review events from the bot's own prior reviews, creating a self-amplifying dispatch cycle.

Assessment: The review quality was reasonable on the first pass (valid findings about bootstrap installation and coverage gaps), but the iteration pattern was excessive. The core problems — repeated findings, self-triggering dispatches, and lack of human-approval awareness — are all covered by existing open issues:

  • Repeated findings: #1285 (don't regenerate unchanged inline comments), #956 (resolve prior inline comments on re-review)
  • Review after human approval: #1922 (don't override human approval with stale findings)
  • Excessive dispatches: #2599 (per-PR review budget), #902 (circuit breaker), #963 (skip when SHA already reviewed)
  • Churn detection: #2111 (detect review-cycle churn), #1367 (new low-severity findings across approved passes)

This PR serves as a concrete data point for prioritizing those issues. No new proposals are warranted — the improvement areas are already well-identified in the backlog.

ifireball pushed a commit to ifireball/fullsend that referenced this pull request Jun 24, 2026
…commit-hook

chore(ci): add pinact pre-commit hook to enforce SHA-pinned actions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/ci CI pipelines and checks security Security threat model and related concerns type/chore Maintenance and housekeeping tasks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants