Skip to content

feat(action): publish reports through the git-data API - #328

Merged
BenSheridanEdwards merged 3 commits into
mainfrom
feat/api-report-publish
Jul 21, 2026
Merged

feat(action): publish reports through the git-data API#328
BenSheridanEdwards merged 3 commits into
mainfrom
feat/api-report-publish

Conversation

@BenSheridanEdwards

@BenSheridanEdwards BenSheridanEdwards commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Why does this feature exist?

So publishing a report keeps working no matter how large the report branch grows. The publish step cloned the whole report branch to add one pr-<n>/ folder, so every publish cost the size of every report ever kept. Once the branch reached a few gigabytes, the clone started dying mid-transfer (curl 18 ... invalid index-pack output) and the publish step failed on every PR in the repository, after the gate had already reached its verdict. Publish now costs the size of the report being published, so branch growth can never break it again.

A blobless clone cannot fix this: git push re-fetches the retained blobs to build its pack, so --filter=blob:none moves the cost from clone time to push time instead of removing it.

What changed?

  • New src/report-publish.ts and bin/styleproof-publish-report.mjs (registered in package.json bin): publish through the GitHub git-data API. Upload the report blobs (report.md plus every crops/*.png), build one tree on the current tip (delete this PR's stale folder if present, seed the README if missing), create the commit, and fast-forward the ref with force: false. A rejected update means another publish advanced the branch; the attempt retries against the fresh tip, up to 5 times with backoff. First runs create the branch as an orphan; a racing first run loses the ref create and retries onto the winner's branch.
  • action.yml publish step: the clone/commit/push loop is replaced by one call to the new command. Report generation, the receipt embedded in report.md, the fail-closed read-back at the exact published commit, and the sha/url/raw-base outputs are unchanged contracts.
  • Publish now measures the branch's total blob size from the recursive tree listing (skipped when truncated) and logs a workflow warning above 1 GB, so consumers hear about growth long before anything that still clones the branch starts to hurt.
  • test/action.test.mjs: the five contracts that pinned the old bash internals now assert the same guarantees at their new home, including that the publish step never runs git clone or git push.

Behavioural Proof (with video and screenshots)

Not applicable: this is CI plumbing with no rendered surface. Behavioural proof is the Action dogfood workflow on this PR, which runs the real composite action end to end — it published its report through the new API path and passed. test/report-publish.test.mjs additionally drives the publisher against an in-memory git-data API double: existing-branch publish with zero report bytes downloaded, wholesale folder replacement leaving other folders untouched, orphan first run with README, README seeding, the fast-forward race retrying then succeeding, the attempt budget surfacing a persistent race, immediate failure on non-retryable client errors, the size warning above threshold, truncated listings skipping size telemetry, and receipt verification passing and failing closed.

Verification Summary

  • npm test (build + full suite): 620 pass, 0 fail on this branch.
  • npm run format:check: clean.
  • Action dogfood and Map store dogfood workflows: green on this PR, exercising the real publish path.
  • Receipt contract unchanged: embedded before upload, verified by read-back at the exact advertised commit, fail closed.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

Fallow audit report

No GitHub PR/MR findings.

Generated by fallow.

@github-actions github-actions 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.

Fallow audit report

Review needed

1 inline finding selected for GitHub review.

Comment thread src/report-publish.ts Outdated

/** One publish attempt against the current branch tip. Throws
* ReportPublishApiError with status 422 when the ref moved under us. */
async function publishOnce(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

warn fallow/high-cognitive-complexity: 'publishOnce' has cognitive complexity 18 (threshold: 15)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in d979262.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in 0e89643.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Resolved in 5ee57ac.

@github-actions

github-actions Bot commented Jul 21, 2026

Copy link
Copy Markdown

🗺️ StyleProof report

📊 View the side-by-side visual report →


Coverage, determinism, or report/diff consistency evidence is incomplete — repair the capture or reflow source; visual approval cannot clear this failure.

StyleProof Test added 3 commits July 21, 2026 17:44
The publish step cloned the report branch to add one pr-<n>/ folder, so
every publish cost the size of the whole branch. With one folder per PR
the branch grows without bound, and once it reaches a few gigabytes the
clone dies mid-transfer and publish fails on every PR in the repository.
A blobless clone does not help: git push re-fetches the retained blobs
to build its pack.

Publish now uploads the report blobs, grafts the folder onto the current
tip tree server-side, and fast-forwards the ref, so it costs the size of
this report and never downloads report bytes. The fast-forward race
against concurrent publishes retries against the fresh tip, first runs
create the branch as an orphan with the README, and the run receipt is
embedded and verified at the published commit exactly as before, fail
closed. Publish also measures the branch's blob size from the tree
listing and logs a workflow warning when it passes 1 GB, so consumers
hear about growth long before anything breaks.
The one-function publish attempt crossed the complexity gate, and the
README constant leaked into the public surface. Tip read, blob upload,
tree grafting, ref advance, and size telemetry are now separate small
functions; behaviour is unchanged and covered by the existing tests.
@BenSheridanEdwards
BenSheridanEdwards force-pushed the feat/api-report-publish branch from 7318616 to 2e167fd Compare July 21, 2026 16:45
@BenSheridanEdwards
BenSheridanEdwards merged commit 82afbea into main Jul 21, 2026
12 checks passed
BenSheridanEdwards added a commit that referenced this pull request Jul 22, 2026
Cut 4.7.0 from the six commits merged since 4.6.3. Two are feature work, so
this is a minor bump; the version bump is the Release workflow's signal to
tag, publish to npm, and cut the GitHub Release on merge.

Added
- Reports publish through the git-data API (#328).
- styleproof-init prunes reports by API with a retention + size-budget sweep (#329).
- CERTIFICATION_FAILED dogfooded end-to-end (#327).

Security
- Cleared two high-severity transitive advisories: brace-expansion 5.0.6→5.0.7
  (#330) and fast-uri 3.1.3→3.1.4, GHSA-v2hh-gcrm-f6hx (#331).

Verified locally: build, typecheck, lint, format:check, privacy:check all
clean; full node --test suite 630/630 with a complete install.

Co-authored-by: StyleProof Test <styleproof@example.test>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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