Skip to content

fix(pre-fetch): extract the prior SHA with sed, not BSD-incompatible grep -P - #6676

Merged
rh-hemartin merged 2 commits into
fullsend-ai:mainfrom
guyoron1:fix/prior-sha-bsd-grep
Sep 1, 2026
Merged

fix(pre-fetch): extract the prior SHA with sed, not BSD-incompatible grep -P#6676
rh-hemartin merged 2 commits into
fullsend-ai:mainfrom
guyoron1:fix/prior-sha-bsd-grep

Conversation

@guyoron1

@guyoron1 guyoron1 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Heyaaaa : )

Summary

pre-fetch-prior-review.sh extracts the prior review SHA with grep -oP. BSD grep (macOS) has no -P, the || true swallows the failure, and PRIOR_SHA comes back empty — two script tests fail on every macOS checkout. Replaced with sed -nE, the same expression in POSIX ERE. Second commit applies the identical swap to the GitLab scaffold twin (its comment declares it "equivalent" to this script) so the pair stays in lockstep — caught in review by @waynesun09.

Related Issue

None — found running the script test suite on macOS.

Changes

  • sed -nE 's/.*\*\*Head SHA:\*\* ([0-9a-f]{7,64}).*/\1/p' | head -1 replaces the grep; the || true goes too, since a sed no-match exits 0.
  • Same swap at fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:462, with a lockstep pointer comment.
  • One deliberate edge change: two **Head SHA:** markers on one line now yield the last, not the first. Across lines — the only shape the pipeline writes — behavior is identical, and the tests cover it.

Sweep status: hack/lint-docs-links had the same bug class and is macOS-reachable via pre-commit — fixed in #6728. The guard at reconcile-repos.sh:208 is inert on macOS (BSD grep exits non-zero, the if reads that as false) but harmless: the anchored allowlist at :212 already rejects control characters. Still unswept, genuinely Linux-only: scripts/renovate/*, hack/gitlab-runner-vm/setup.sh.

Testing

  • make lint passes (stage changes first, then run)
  • Tests added/updated for new or modified logic

pre-fetch-prior-review-test.sh: 2 failures → all pass on macOS. GitLab twin pipeline run on the same fixtures, identical output. CI (GNU grep) behaviorally unchanged.

Checklist

  • PR title follows Conventional Commits (correct type, ! for breaking changes)
  • Commits are signed off (DCO) — human and human-directed agent sessions only
  • I wrote this contribution myself and can explain all changes in it

@guyoron1
guyoron1 requested a review from a team as a code owner August 27, 2026 11:42
@github-actions

Copy link
Copy Markdown

E2E tests did not run

E2E tests run automatically for org/repo members and collaborators on pull requests.

For other contributors, a maintainer must add the ok-to-test label after the latest push.

See E2E testing guide for details.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Make prior-review SHA extraction portable across macOS and Linux

🐞 Bug fix 🕐 Less than 10 minutes

Grey Divider

AI Description

• Replace GNU-only PCRE extraction with portable POSIX ERE parsing.
• Preserve empty-SHA handling without suppressing command failures.
• Restore existing prior-review script tests on macOS.
Diagram

graph TD
  A["Prior review body"] --> B["Current section"] --> C["Portable SHA parser"] --> D["Prior SHA output"]
Loading
High-Level Assessment

The sed-based POSIX ERE pipeline is the best fit because it works with both BSD and GNU userlands, retains the established shell pipeline, and naturally returns success on no match. Adding a Perl dependency or retaining grep with platform detection would add unnecessary complexity.

Files changed (1) +7 / -1

Bug fix (1) +7 / -1
pre-fetch-prior-review.shUse portable sed for prior-review SHA extraction +7/-1

Use portable sed for prior-review SHA extraction

• Replaces GNU grep's unsupported-on-macOS PCRE lookbehind with a POSIX ERE sed substitution. Removes the error-swallowing fallback because sed safely emits no output when no SHA matches.

internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Remediation recommended

1. Multiple matches abort pre-fetch 🐞 Bug ☼ Reliability
Description
With pipefail, head -1 can close the pipe while sed is still emitting matches, causing sed
to exit on SIGPIPE and the PRIOR_SHA assignment to terminate the script. A sufficiently large
prior-review section with repeated Head SHA lines therefore prevents the later review-agent step
from running.
Code

internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh[R102-103]

    PRIOR_SHA="$(echo "${CURRENT_SECTION}" \
-        | grep -oP '(?<=\*\*Head SHA:\*\* )[0-9a-f]{7,64}' | head -1 || true)"
+        | sed -nE 's/.*\*\*Head SHA:\*\* ([0-9a-f]{7,64}).*/\1/p' | head -1)"
Relevance

●●● Strong

Recent accepted precedent flags unguarded grep/head pipelines under pipefail; this is the same
reliability failure mode.

PR-#390
PR-#2456

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The script enables set -euo pipefail, accepts and processes prior bodies up to 1 MB, and imposes
no limit on matching lines. The changed pipeline is unguarded; its exported value feeds a workflow
step that executes before the review agent, so status 141 from sed aborts the review run.

internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh[11-11]
internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh[78-89]
internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh[94-104]
.github/workflows/reusable-review.yml[143-180]

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

## Issue description
The unguarded `sed | head -1` pipeline can fail with SIGPIPE under `set -o pipefail` when many lines match, aborting pre-fetch before the review agent runs.

## Issue Context
Keep BSD/macOS portability and preserve successful empty output when no SHA exists. Prefer making `sed` print the first match and quit itself, eliminating `head`, rather than broadly swallowing genuine sed failures.

## Fix Focus Areas
- internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh[102-103]
- internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review-test.sh[121-179]

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


Grey Divider

Context sources
✅ Compliance rules (platform): 69 rules
Review mode: ⚖️ Balanced

Grey Divider

Tip of the day
💡 Did you know, you can ask Qodo to dismiss a finding you disagree with, with your reason on record

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/scaffold/fullsend-repo/scripts/pre-fetch-prior-review.sh
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review sweep at head 0ce3f82. Both findings land on files outside this PR's diff (the diff is only pre-fetch-prior-review.sh), so they are here in the review body rather than as inline comments. Neither blocks the fix itself — the sed -nE change is correct and the right call.


MEDIUM — The GitLab scaffold twin keeps the byte-identical grep -oP, and the PR body's "five other scripts" sweep is understated

internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:462

internal/scaffold/fullsend-repo-gitlab/.gitlab/ci/fullsend-agent.yml:462 runs:

PRIOR_REVIEW_SHA=$(printf '%s' "${CURRENT_SECTION}" \
  | grep -oP '(?<=\*\*Head SHA:\*\* )[0-9a-f]{7,64}' | head -1 || true)

That is byte-identical to the line this PR replaces, including the surrounding awk '/<!-- sticky:history-start -->/{exit}' section split and the 1 MB MAX_REVIEW_BYTES cap. The comment at lines 390-394 calls it out explicitly: "Pre-fetch prior review for the review agent — equivalent to pre-fetch-prior-review.sh in the GitHub scaffold." After this PR the two self-declared-equivalent extractors diverge in exactly the multi-marker-on-one-line case the PR body flags as a deliberate behavior change (grep takes the first, sed's greedy .* takes the last).

Separately, the PR body's sweep enumeration is wrong. It says "five other scripts use grep -P (scripts/renovate/*, hack/gitlab-runner-vm/setup.sh, reconcile-repos.sh). They are Linux-only automation and out of scope." A repo-wide search returns two sites that enumeration misses. The GitLab twin above is one. The other is hack/lint-docs-links:32:

done < <(grep -oP '(?<=\])\(\K[^)]+' "$mdfile" || true)

which is not Linux-only automation: .pre-commit-config.yaml:156-161 wires it as the lint-docs-links pre-commit hook over ^docs/.*\.md$, so it runs on developer machines, macOS included, with the same fail-open || true this PR is fixing. On a macOS checkout it yields zero links and the docs-link scope check passes vacuously. That is the same bug class on the same platform the PR exists to fix, described in the PR body as out of scope.

Suggestion: Apply the same sed -nE extraction at fullsend-agent.yml:462 so the pair the comment calls "equivalent" stays equivalent (one line), or leave it and note at that line why it is deliberately divergent. Either way correct the PR body: the sweep is seven sites, not six, and hack/lint-docs-links is a macOS-reachable pre-commit hook rather than Linux-only automation — worth its own follow-up issue, since it fails open exactly the way this PR's target did.


MEDIUM — PR body's reconcile-repos.sh:208 claim is factually wrong; the anchored allowlist three lines later already rejects control characters

internal/scaffold/fullsend-repo/scripts/reconcile-repos.sh:208

The PR body asserts as fact: "reconcile-repos.sh:208 deserves its own look — its grep -qP '[\x00-\x1f]' control-character guard does not error out on BSD, it just evaluates false, so that check quietly passes everything on a macOS run."

Reading the file at head 0ce3f82: line 208 is if printf '%s' "$name" | grep -qP '[\x00-\x1f]'; then inside validate_repo_name, and line 212 is if ! [[ "$name" =~ $REPO_NAME_PATTERN ]]; then with REPO_NAME_PATTERN='^[a-zA-Z0-9._-]+$' defined at line 30. That is an anchored allowlist that rejects every byte in \x00-\x1f regardless of what the grep on 208 returns, so "that check quietly passes everything on a macOS run" is false — the grep is defense-in-depth on top of a check that already covers its entire input class, and the macOS exposure is nil.

The mechanism claim is also imprecise: BSD grep does not succeed on -P, it exits non-zero with a usage error; the reason set -e does not fire is that the call sits in an if condition, where a non-zero status simply reads as false. Same net effect, different cause, and the difference matters to whoever follows the pointer — they will find stderr noise, not silence. Shipping "quietly passes everything" in a merged PR description invites someone to file a security issue against code that is already safe.

Suggestion: Reword to something checkable, e.g. "BSD grep exits non-zero on -P; inside the if that reads as false, so the guard at line 208 is inert on macOS — harmless in practice because the anchored REPO_NAME_PATTERN allowlist at line 212 already rejects control characters. Worth cleaning up for hygiene, not a hole."

…grep -P

pre-fetch-prior-review.sh read the prior review's head SHA with
`grep -oP '(?<=\*\*Head SHA:\*\* )[0-9a-f]{7,64}'`. BSD grep, which is
what macOS ships as /usr/bin/grep, has no -P: the call exits with
"grep: invalid option -- P" and the trailing `|| true` swallows it, so
PRIOR_SHA silently comes back empty.

The effect is confined to developer machines — CI and the vendored
consumer path both run on Linux with GNU grep — but there it is not
subtle: body-with-valid-sha and body-with-full-sha fail on every macOS
checkout of main, which is two red tests a newcomer has to rule out
before trusting their own changes. I spent a while assuming they were
mine.

sed -nE expresses the same match in POSIX ERE and behaves identically on
both platforms. A no-match prints nothing and exits 0, so the fallback
that `|| true` was covering is now structural rather than suppressed —
body-without-sha-no-crash still passes without it.

One deliberate difference, since it is a behavior change and not a
refactor: with two "**Head SHA:**" markers on the *same line*, grep -o
emitted both and head -1 took the first, while sed's greedy leading .*
takes the last. Across separate lines — the only shape this pipeline
writes, one bolded field per line — head -1 still yields the first, which
the tests cover.

Not swept: five other scripts use grep -P (scripts/renovate/*,
hack/gitlab-runner-vm/setup.sh, reconcile-repos.sh). They are Linux-only
automation and out of scope here, but reconcile-repos.sh:208 is worth a
look on its own — its `grep -qP '[\x00-\x1f]'` control-character guard
does not error out on BSD, it just evaluates false, so the check quietly
passes everything on a macOS run.

Verification: pre-fetch-prior-review-test.sh goes from 2 failures to all
tests passing on macOS (BSD grep 2.6.0-FreeBSD); shellcheck clean.

Signed-off-by: guy oron <goron@redhat.com>
The GitLab scaffold's fullsend-agent.yml carries a byte-identical copy
of the extraction the previous commit replaced — its own comment calls
it "equivalent to pre-fetch-prior-review.sh in the GitHub scaffold",
and after that commit the two self-declared-equivalent extractors
diverged in exactly the multi-marker-on-one-line case the change
declared. Same sed -nE expression here, so the pair stays equivalent,
with a pointer comment so the next edit finds the rationale in one
place.

Unlike the GitHub script, this path never breaks at runtime — GitLab
runners are Linux — so this is equivalence maintenance, not a platform
fix. Raised in review by @waynesun09.

Verification: the embedded pipeline extracted verbatim from the yml and
run under set -euo pipefail against the same fixture shapes as
pre-fetch-prior-review-test.sh (valid short SHA, full 40-char SHA, no
marker, marker only in the sticky-history section) — identical output
to the GitHub script in all four; multi-document YAML still parses.

Signed-off-by: guy oron <goron@redhat.com>
@guyoron1

Copy link
Copy Markdown
Contributor Author

Both fixed, thanks for the sweep check — both catches were right.

  • GitLab twin: same sed -nE in c3babba, with a lockstep comment pointing at the GitHub script for the rationale.
  • reconcile-repos.sh: PR body corrected per your wording — inert guard, input class already covered by the anchored allowlist; hygiene, not a hole.
  • lint-docs-links: indeed macOS-reachable, and it was hiding a second bug — with links actually flowing, realpath -m is next in the loop and BSD realpath has no -m, so a grep-only fix would have hard-failed every macOS docs commit. Both fixed together in fix(hack): make lint-docs-links actually run on macOS #6728 (extraction parity verified across the docs corpus: 2798 links, zero mismatches; the old pipeline extracts 0 on macOS).

@rh-hemartin
rh-hemartin added this pull request to the merge queue Sep 1, 2026
Merged via the queue into fullsend-ai:main with commit 9197175 Sep 1, 2026
31 checks passed
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.

3 participants