Skip to content

Review fixes for #610: spec-tests sync hardening, fork policy, docs - #635

Merged
GalRogozinski merged 14 commits into
spec-test-cifrom
pr-610-fixes
Aug 6, 2026
Merged

Review fixes for #610: spec-tests sync hardening, fork policy, docs#635
GalRogozinski merged 14 commits into
spec-test-cifrom
pr-610-fixes

Conversation

@GalRogozinski

Copy link
Copy Markdown
Contributor

Addresses review comments on #610. Targets spec-test-ci so the fixes land in that PR.

Commit Comment addressed
3002d0052 Local-run docs: sibling spec-tests/<module> layout, generate-before-make test, multiple-checkout collision
99f5ced30 Pin local golangci-lint to the version CI pins (v2.12.2)
fa23e5883 Use the supported installer — the master install.sh fails sha256 verification for v2 (same change as #629, plus the pin)
5b53256f2 Validate PR_HEAD_REF in the merge sync before it reaches git checkout -B / git push --force
1608fb86c Concurrency group on the PR sync, keyed on PR number
e5f973ae5, f69153349, 50c07ff0c, 2db08b6f3, 59a8536e6 Fork policy: fork PRs skip the pre-merge sync; the merge sync skips its push step for fork-originated merges
7f4aae97e Composite action path in the Files table, dead App-setup link, t.Fatalf instead of panic in qbft/types spectest

Not taken, with reasoning in the review threads: extracting the duplicated sync core (the control flow around it is deliberately asymmetric), renaming mirror branches to ssv-spec-pr-<number>, and the workflow_run restructure for fork PRs.

Two things for whoever merges:

  • Confirm no required status check is pinned to Test / buildmain is governed by an org-level ruleset I can't read.
  • ci: use supported golangci-lint installer #629 makes the same installer change and should be closed rather than merged, or the version pin reverts to latest.

Every workflow change was reviewed by codex; the review caught a jq // empty defect that collapsed the PR lookup for deleted forks, fixed in 59a8536e6.

🤖 Generated with Claude Code

Add a Running Locally section to the CI workflow docs covering the
<parent-of-ssv-spec>/spec-tests/<module> layout, the generate-before-test
order, and the shared-directory caveat for multiple checkouts. Point to it
from the root README.
make lint-prepare installed 'latest' while lint.yaml pins v2.12.2, so
local and CI could run different linter versions. Pin the Makefile to the
same version via GOLANGCI_LINT_VERSION.
sync-spec-tests-merge.yaml used the merged PR's head ref unvalidated in
git checkout -B, git push --force and gh pr list --head. head.ref is a bare
branch name, so a fork PR opened from the fork's default branch yields
'main'; origin/main always exists, so the missing-mirror-branch check at
line 130 cannot catch it and the run force-pushes generated fixtures onto
spec-tests main outside the mirror PR.

Apply the same shape check and main/master refusal that
sync-spec-tests-pr.yaml already performs, at the point the ref is
resolved.
The install.sh served from the golangci-lint master branch fails checksum
verification for v2 releases, so 'make lint-prepare' pinned to v2.12.2
installed nothing:

  hash_sha256_verify checksum for golangci-lint-2.12.2-darwin-arm64.tar.gz
  did not verify

https://golangci-lint.run/install.sh installs the same pinned version
successfully. Same change as #629, kept together with the version pin so
local and CI stay on one version.
Two pushes in quick succession force-push the same mirror branch with
no ordering, so an older commit's fixtures can land last and leave
the mirror stale until the next push.
Fork PRs get no secrets on pull_request, so the pre-merge sync workflow
never worked for them and the merge workflow failed loudly instead.
Post-merge, fork code is already trusted: a human reviewed and merged
it, and the merge workflow already runs go generate from main in the
same job that holds the App token. Pre-merge mirroring for forks would
let any GitHub user trigger App-token writes to spec-tests without
review, which is the risk this change avoids.
The main/master and unsafe-shape checks on PR_HEAD_REF ran before
is-fork was known, so a fork PR opened from its own default branch
(head ref "main") tripped the protected-name refusal and never
reached the fork sync path. Move the is-fork computation earlier and
skip that validation for fork PRs, since their head ref is never used
as a push/checkout target on the fork path.
…path

Each sync in this step replaces the entire generated tree from main,
so the next same-repo merge already carries a fork's fixtures into
spec-tests. A dedicated fork push path only bought a shorter staleness
window at the cost of a second, unaudited write path into spec-tests
— skip the step for fork-originated merges instead.
Codex review of the fork policy found two defects and one wrong claim:

- jq's 'empty' suppresses the whole object, so head_repo: (.head.repo.full_name
  // empty) collapsed PR_INFO when the head repository is gone (deleted fork),
  making the run exit 'No PR found' and never reaching the fork check. Use ""
  instead.
- Unknown head repo now means 'not this repo': skip the sync. There is no mirror
  branch to finalize in that case, and treating it as same-repo risked pushing to
  an unrelated mirror branch.
- The push step gate is 'is-fork == false' rather than '!= true', so a missing
  output fails closed.

README: the 'next in-repo merge' guarantee was too strong. An in-repo PR with no
fixture diff never pushes a mirror branch, so if it merges next its merge run
fails loudly instead of syncing; the sync lands on the following in-repo merge
that has a mirror branch.
…leanly

- README Files table: ../actions/... not ../.github/actions/..., which
  resolved to .github/.github/actions.
- Drop the link to a GITHUB_APP_SETUP.md that does not exist in this repo;
  point at GitHub's own App registration docs and name the two secrets.
- qbft and types spectest TestJson: t.Fatalf instead of panic on a
  spec-tests dir resolution failure, matching ssv/spectest/run_test.go.
@greptile-apps

greptile-apps Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR hardens spec-test synchronization by serializing PR runs, validating mirror refs, and explicitly excluding fork PRs from credential-dependent synchronization. It also aligns local lint tooling with CI, improves local-generation documentation, and reports fixture-path failures through the Go test framework.

  • Adds same-repository and fork-aware workflow gates.
  • Validates merge-time branch names before Git operations.
  • Pins local golangci-lint installation to v2.12.2.
  • Documents sibling fixture directories and multi-checkout collisions.
  • Replaces test panics with t.Fatalf.

Confidence Score: 5/5

The PR appears safe to merge, with the delayed synchronization of fork-originated fixtures explicitly documented as an intentional policy tradeoff.

The changed workflow guards consistently prevent fork refs from reaching mirror-branch operations, same-repository refs receive matching validation in both synchronization workflows, and the tooling and test changes preserve their existing contracts.

Important Files Changed

Filename Overview
.github/workflows/sync-spec-tests-merge.yaml Adds fork classification, same-repository ref validation, and conditional finalization of mirror branches without an unacknowledged actionable defect.
.github/workflows/sync-spec-tests-pr.yaml Serializes updates per PR and skips both generation and synchronization for fork PRs as documented.
Makefile Pins the local linter to CI’s v2.12.2 version and switches to the supported installer endpoint.
.github/workflows/README.md Documents fork synchronization policy, local fixture generation, and the shared-directory limitation across checkouts.
README.md Clarifies that fixture generation must precede tests and points to the detailed workflow guide.
qbft/spectest/run_test.go Converts fixture-directory resolution failure from a panic into a test-scoped fatal error.
types/spectest/run_test.go Converts fixture-directory resolution failure from a panic into a test-scoped fatal error.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Pull request opened or updated] --> B{Same repository?}
    B -->|Yes| C[Generate fixture artifact]
    C --> D[Sync mirror branch and PR]
    B -->|Fork| E[Skip credential-dependent PR sync]
    F[PR merged to main] --> G[Generate final fixtures]
    G --> H{Fork-originated merge?}
    H -->|No| I[Validate mirror branch ref]
    I --> J[Push final fixtures]
    J --> K[Merge spec-tests PR]
    H -->|Yes| L[Skip final push]
    L --> M[Fixtures carried by later qualifying in-repo merge]
Loading

Reviews (1): Last reviewed commit: "docs: fix composite action path and dead..." | Re-trigger Greptile

Codex review of the branch found three issues in what we changed:

- 'curl ... | sh' reports the exit status of sh, and sh with empty input
  exits 0, so a failed download looked like a successful install. Download
  to a temp file and run it as an &&-chain instead (verified: a 404 URL now
  exits 56 rather than 0).
- The fork comment in the merge sync claimed fixtures reach spec-tests with
  'the next same-repo merge', contradicting the gap documented in README.md.
- The workflows README overview claimed every in-repo PR keeps a mirror PR
  open; PRs whose fixtures match spec-tests never create one.
Tags are mutable refs: whoever controls the action repo can retag
to different code, which then runs inside jobs holding the spec-tests
App private key. Pin checkout, upload/download-artifact,
create-github-app-token, setup-go, and golangci-lint-action to their
resolved commit SHAs (with the version as a trailing comment).

Add .github/dependabot.yml for the github-actions ecosystem so these
pins keep getting bumped instead of going stale.
github-actions with directory '/' scans .github/workflows and a root
action.yml only, so the setup-go pin in .github/actions/generate-spec-tests
would never be bumped. Add that path explicitly.
@GalRogozinski
GalRogozinski merged commit b6380e0 into spec-test-ci Aug 6, 2026
5 checks passed
@GalRogozinski
GalRogozinski deleted the pr-610-fixes branch August 6, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant