Skip to content

chore(release): promote the shared star-chart refresh workflow to main - #33

Merged
scttbnsn merged 27 commits into
mainfrom
dev/repository-standards
Aug 20, 2026
Merged

chore(release): promote the shared star-chart refresh workflow to main#33
scttbnsn merged 27 commits into
mainfrom
dev/repository-standards

Conversation

@scttbnsn

Copy link
Copy Markdown
Contributor

Promotes starchart-refresh.yml and its contract test so consuming repos can pin a frozen full commit SHA on main.

Reviewed on #32 (two non-author approvals, CodeRabbit read and answered). Reconciled with chore(sync): reconcile main before promotion; the reconcile left the tree unchanged.

What lands

  • .github/workflows/starchart-refresh.yml — reusable workflow that regenerates a repository's star-history chart as a first-party SVG from GitHub's stargazer timestamps and commits it back to the caller's integration branch, only when the chart changed.
  • .github/tests/starchart_refresh_contract_test.py — 10 contract tests, wired into Standards Validation.
  • REPOSITORY_ONBOARDING.md — the caller shape and why the chart is a committed artifact rather than a live route or a third-party embed.

Why it exists

Third star-chart decision in a week, and the first two both rested on a diagnosis that turned out to be false. The record said GitHub had restricted stargazer API access. It hadn't: Accept: application/vnd.github.star+json returns real starred_at timestamps with any authenticated token, 3 API calls for drydock's 238 stars against 5000/hour. star-history.com broke because a third party has no token for our repos. drydock's self-hosted route broke because its own code returns a placeholder SVG at HTTP 200 when process.env.GITHUB_TOKEN is unset, and it was never set in Vercel production.

So the rule isn't that self-hosting can't work. It's that a live route needs a production secret and fails silently without one, while a committed artifact needs nothing at runtime and can't fail silently. It also settles the marketing-page case with no proxy: same file, zero third-party requests, no visitor IPs leaving our infrastructure.

Review found a real one

CodeRabbit caught that max-pages: 0 fetched nothing, which fell through to the "too few stars" clean exit, so a repository with 238 stars would have reported a green no-op. That's the same silent-success shape this workflow exists to remove, sitting inside the workflow itself. A cap merely below the needed count was the other half, publishing a partial history as a whole one behind a ::warning::. Both now fail loudly. Two smaller ones fixed alongside: branch is rejected before checkout if it names a default branch, and output-path can't escape the workspace.

Verification

  • actionlint clean, zizmor clean (one commented suppression: persist-credentials: true, because the job's whole purpose is a commit-back).
  • All contract tests pass, including a node --check of the generator recovered exactly as the shell sees it after YAML strips the run block's indentation. Proven with a negative control: injecting a syntax error fails the test.
  • Generator run against live data for drydock (238 stars), sockguard (7), portwing (4), and careerrat (1, clean no-op exit). Byte-identical to the reference output.
  • Rejected inputs verified behaviourally: zero cap, truncating cap, absolute path, and traversal path all throw, and nothing lands outside the workspace.
  • Standards Validation and CodeQL green on the exact reviewed head 8288ada60e169c3b968cd7ca38a7c6491dec7c6c.

@coderabbitai review

Adds organization-wide community health defaults, validation, ownership, contribution guidance, security policy, and hardened workflow checks.
* ci(workflows): add reusable CI foundation

* fix(workflows): harden reusable release contracts
* feat(quality): add normalized reporting foundation

* test(quality): run reporting contracts in standards validation

* fix(quality): align report validator with schema

* test(quality): verify GitHub integration outputs
* ci(profile): make asset generation read-only

* fix(profile): restrict asset validation egress
* ci(review): add deduplicated Greptile summon

* fix(review): serialize exact-head Greptile summons

* test(review): lock Greptile security controls
go-ci.yml's test and lint jobs ran unconditionally, so a Go-less repo
that only wants the language-agnostic workflow-security (zizmor) job
couldn't call it. Add run-test/run-lint boolean inputs, mirroring the
existing run-govulncheck/run-workflow-security/etc. toggle pattern,
defaulting to true so existing callers see no behavior change.

Fixes: #18
* ci(workflows): add module-directory input to node-ci

Mirrors go-ci's module-directory idiom: a string input defaulting to
"." threaded into each fixed script's env as MODULE_DIRECTORY, so a
repo with several independently-gated Node projects can call node-ci
once per project. The default preserves current behavior for existing
callers.

Extends the reusable CI contract test to assert the new input and its
threading, matching how run-test/run-lint were added for go-ci in #19.

* test(workflows): assert module-directory threads into all three node jobs
* docs(onboarding): align with the codified standards registry

- docs(onboarding): name Codecov as the coverage cloud; Qlty Cloud App and
  maintainability badge stay, checks stay non-required
- docs(onboarding): trivy deprecated in favor of Grype, including the qlty
  plugin blocks in the two reference configs (drydock#753, portwing#135)
- docs(onboarding): CodeRabbit free Pro is public-only; private repos use
  cross-account human review
- docs(onboarding): add the greptile.json contract and the label-gated
  second-opinion caller

* docs(onboarding): reword the CodeRabbit private-repo claim as org policy

- docs(onboarding): free-plan private-repo reviews exist but are
  rate-limited and never fired here; the skip is policy, not a plan fact
- docs(onboarding): pair the Greptile caller with auto-applied CodeRabbit
  labeling so the second-opinion label is criteria-driven
* chore(repo): meet our own onboarding checklist

- chore(repo): MIT LICENSE (infrastructure repos are MIT; products AGPL)
- docs(repo): root AGENTS.md with repo-specific rules and validation
- build(hooks): lefthook with commit-msg + pre-push mirroring CI via
  scripts/validate.sh

* fix(hooks): tighten the commit-msg exemptions and mirror zizmor's CI flags

- fix(hooks): merge/revert exemptions match git's generated subjects only,
  so a hand-typed 'Merge ...' subject no longer bypasses the check
- fix(hooks): require a non-whitespace character after the colon
- fix(hooks): zizmor runs --no-online-audits locally, matching CI's
  online-audits: false for local/CI parity

* fix(hooks): exempt only git-generated merge and revert subjects
* docs(community): add org-default code of conduct and community checklist items

CODE_OF_CONDUCT.md is Contributor Covenant 2.0 (drydock's tuned copy) with
the org contact security@codeswhat.com, cascading to every repo without a
local one. Onboarding checklist gains the cascade-first rule and the
Discussions on/off split for product vs meta repos.

* test(community): assert the code of conduct in the community-health contract
…32)

* feat(workflows): add the shared star-chart refresh reusable workflow

Replaces both retired star-chart engines org-wide. The chart becomes a
first-party SVG generated from GitHub's own stargazer timestamps and
committed into the consuming repository, so it needs no secret and makes
no request at render time.

That property is the point. A live route that loses its credential serves
a plausible placeholder at HTTP 200 forever with nothing reporting red,
which is exactly how drydock's chart sat broken. A committed artifact
fails visibly or not at all.

The generator is embedded in the workflow rather than checked out from a
second repository, so a caller's SHA pin covers every line of behaviour
with nothing resolved at run time. Verified against live data before
committing: byte-identical output to the reference implementation for
drydock at 238 stars and 3 API calls, and a clean no-op exit on a repo
with a single star.

- feat(workflows): starchart-refresh.yml, egress-blocked to api.github.com
  and github.com, contents: write as its only elevated scope
- test(workflows): contract test covering the embedded generator, env-var
  input handling, the self-contained SVG, and the conditional commit-back
- ci(validation): run the new contract test in standards validation
- docs(onboarding): document the caller shape and why the artifact is
  committed rather than served

* test(workflows): syntax-check the embedded star-chart generator

This workflow never runs in this repository, so a syntax error inside the
heredoc would first surface in a consumer's scheduled job, days later and
in someone else's lane.

The test recovers the generator the way the shell will actually see it,
stripping the run block's base indentation rather than reading the file
as written, since a heredoc body that looks correct in YAML can still
reach node malformed. Then node --check parses it.

Verified with a negative control rather than assumed: injecting a syntax
error into the generator fails the test, and reverting passes it.

* fix(workflows): reject the inputs that would publish a wrong star chart

All three from CodeRabbit on #32, and the max-pages one was a real bug of
exactly the kind this workflow exists to prevent.

max-pages: 0 made pages 0, which fetched nothing, which hit the "too few
stars" clean exit. A repository with 238 stars would have reported a
green no-op. A cap below the needed page count was worse than that: it
drew a chart from the first N pages and published a partial history as a
whole one behind a ::warning:: nobody reads. Both now fail loudly, and
the cap must be a positive integer.

branch had no runtime guard. Omitting a default only prevents omission,
so a caller could still pass main and, on a repository whose ruleset let
the push through, commit straight to the default branch. Rejected before
checkout rather than at the push, where the error would be confusing.

output-path was read through the environment, which stops script
injection but not traversal. An absolute or ../ path reached writeFileSync
outside the checkout, and the commit step then found nothing staged and
reported success. Writes now use the resolved and validated path rather
than the raw input, since a check that doesn't govern the write is
decoration.

Verified behaviourally, not by reading: each rejected input throws, the
one-star exit still no-ops, nothing lands outside the workspace, and the
happy path is still byte-identical to the reference output for drydock.
@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@scttbnsn, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 50 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 698bc681-9a3d-4ab6-8d90-1630dd27d410

📥 Commits

Reviewing files that changed from the base of the PR and between bbc181d and 82f48ca.

📒 Files selected for processing (4)
  • .github/tests/starchart_refresh_contract_test.py
  • .github/workflows/standards-validation.yml
  • .github/workflows/starchart-refresh.yml
  • REPOSITORY_ONBOARDING.md

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@biggest-littlest biggest-littlest 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.

Approved for promotion. Same content reviewed on #32; the reconcile left the tree unchanged, and checks are green on the exact head.

@ALARGECOMPANY ALARGECOMPANY 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.

Approved. Reusable workflow with contents: write asserted as its only elevated scope, egress blocked, and the commit-back guarded against a default-branch target before checkout.

@scttbnsn
scttbnsn merged commit 96e2765 into main Aug 20, 2026
4 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