Skip to content

fix(scaffold): preserve user-added headers across shim reconciliation#1779

Open
waynesun09 wants to merge 1 commit into
mainfrom
fix-preserve-shim-header
Open

fix(scaffold): preserve user-added headers across shim reconciliation#1779
waynesun09 wants to merge 1 commit into
mainfrom
fix-preserve-shim-header

Conversation

@waynesun09
Copy link
Copy Markdown
Contributor

Problem

The reconcile script compared and replaced the shim workflow file wholesale, stripping any content users added above the template (e.g. license headers required by their repo CI). This caused repos like conforma/policy to fail addlicense lint checks after each shim update (CI run).

Solution

Add a sentinel comment # --- fullsend managed below - do not edit --- to the top of the shim template. The reconcile script now:

  1. Compares only the managed portion (from sentinel onward) for drift detection, so user-added headers do not trigger false staleness.
  2. Preserves user content above the sentinel when writing updates — the user adds their license header once, and it survives all future reconciliation runs.
  3. Falls back to full-file comparison for pre-sentinel shims (backwards-compatible — the first reconciliation adds the sentinel, subsequent runs use sentinel-aware logic).

Changes

  • templates/shim-workflow-call.yaml — added sentinel line at top
  • scripts/reconcile-repos.sh — added SENTINEL constant, 4 helper functions (extract_managed_content, extract_user_header, shim_with_header_b64, managed_content_b64), updated drift detection and write path
  • scripts/reconcile-repos-test.sh — fixed base64 mock to not strip newlines during decode, added blob content capture, added 2 new test cases (header preservation on stale update, no false drift on up-to-date shim with header)

Test plan

bash internal/scaffold/fullsend-repo/scripts/reconcile-repos-test.sh
# Expected: PASS x3

Related

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Site preview

Preview: https://0a0b1232-site.fullsend-ai.workers.dev

Commit: 87166e6582d7e53d2dae26f20c6fd23c9bdfc2ae

@fullsend-ai-review
Copy link
Copy Markdown

fullsend-ai-review Bot commented Jun 2, 2026

Review

Findings

Low

  • [edge-case] internal/scaffold/fullsend-repo/scripts/reconcile-repos.shextract_managed_content and extract_user_header use exact string match ($0 == sentinel) for the sentinel line. If a remote file's sentinel line has trailing whitespace, the sentinel won't be detected and the script falls back to pre-sentinel behavior (treating the entire file as managed content). This is self-correcting — the next reconciliation writes the correct sentinel — but could cause one unnecessary update cycle.

Info

  • [content-injection] internal/scaffold/fullsend-repo/scripts/reconcile-repos.sh — The content-injection guard in shim_with_header_b64 correctly validates that all preserved header lines match ^[[:space:]]*(#|$) (comments or blanks only). Non-comment YAML that could inject workflow keys is rejected by discarding the entire header. The prior medium-severity finding is confirmed remediated.

  • [sub-agent-failure] N/A — The style-conventions and intent-coherence sub-agents did not return findings: model claude-sonnet-4-5@20250929 unavailable on this deployment. These are sonnet-tier dimensions; correctness and security (opus-tier) completed successfully.

Previous run

Review

Findings

Low

  • [edge-case] internal/scaffold/fullsend-repo/scripts/reconcile-repos.shextract_managed_content and extract_user_header use exact string match ($0 == sentinel) for the sentinel line. If a remote file's sentinel line has trailing whitespace, the sentinel won't be detected and the script falls back to pre-sentinel behavior (treating the entire file as managed content). This is self-correcting — the next reconciliation writes the correct sentinel — but could cause one unnecessary update cycle.

Info

  • [content-injection] internal/scaffold/fullsend-repo/scripts/reconcile-repos.sh:113 — The prior medium-severity content-injection finding in shim_with_header_b64 has been remediated. The function now validates that all lines in the extracted user header match ^(#|$) (comment or blank). Any header containing non-comment YAML content is discarded entirely, preventing injection of workflow keys above the sentinel. The fix is correct and sufficient.

  • [sub-agent-failure] N/A — The style-conventions and intent-coherence sub-agents did not return findings: model claude-sonnet-4-5@20250929 unavailable on this deployment. These are sonnet-tier dimensions; correctness and security (opus-tier) completed successfully.

Previous run (2)

Review

Findings

Medium

  • [content-injection] internal/scaffold/fullsend-repo/scripts/reconcile-repos.shshim_with_header_b64 preserves arbitrary content from above the sentinel line in the remote workflow file and writes it back as part of a GitHub Actions workflow YAML. Since only YAML comments are expected in the user header section, a user with push access could place valid YAML keys (e.g., additional env: blocks, extra job definitions) above the sentinel that would survive reconciliation. While mitigated by the fact that (a) the user already needs push access to the default branch, (b) reconcile creates a PR that goes through human review, and (c) duplicate top-level keys like jobs: are overridden by the managed section — additive keys could persist and execute.
    Remediation: Validate that every line in the extracted header starts with # (comment) or is blank before merging with the managed template. For example: if printf '%s\n' "$header" | grep -qvE '^(#|$)'; then header=''; fi

Low

  • [edge-case] internal/scaffold/fullsend-repo/scripts/reconcile-repos.shextract_managed_content uses exact string match ($0 == sentinel) for the sentinel line. If a remote file's sentinel line has trailing whitespace, the sentinel won't be detected and the script falls back to treating the entire file as managed content (pre-sentinel behavior). This is self-correcting — the next reconciliation writes the correct sentinel — but could cause one unnecessary update cycle.

Info

  • [sub-agent-failure] N/A — The style-conventions, intent-coherence, and cross-repo-contracts sub-agents did not return findings: model claude-sonnet-4-5@20250929 unavailable on this deployment. These are sonnet-tier dimensions; correctness and security (opus-tier) completed successfully.

@fullsend-ai-review fullsend-ai-review Bot added the requires-manual-review Review requires human judgment label Jun 2, 2026
@waynesun09 waynesun09 force-pushed the fix-preserve-shim-header branch from 8366f0d to ef689c3 Compare June 2, 2026 14:12
local header
header=$(printf '%s\n' "$remote_raw" | extract_user_header)

# Only preserve headers that are pure comments/blanks — reject non-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.

[info] content-injection

Prior medium-severity content-injection finding remediated. shim_with_header_b64 now validates all header lines match ^(#|$), discarding non-comment content. Fix is correct and sufficient.

@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed requires-manual-review Review requires human judgment labels Jun 2, 2026
The reconcile script compared and replaced the shim workflow file
wholesale, stripping any content users added (e.g. license headers
required by their CI). This caused repos like conforma/policy to fail
lint checks after each shim update.

Add a sentinel comment ("# --- fullsend managed below - do not edit ---")
to the shim template. The reconcile script now:
- Compares only the managed portion (from sentinel onward) for drift
- Preserves any user content above the sentinel when writing updates
- Falls back to full-file comparison for pre-sentinel shims

Signed-off-by: Wayne Sun <gsun@redhat.com>
@fullsend-ai-review fullsend-ai-review Bot added ready-for-merge All reviewers approved — ready to merge and removed ready-for-merge All reviewers approved — ready to merge labels Jun 2, 2026
@rh-hemartin
Copy link
Copy Markdown
Contributor

I think the easier fix for this was adding our own license header, as this file is produced by fullsend and should be kept to fullsend license. I don't think this feature is really useful for users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants