chore(ci): adopt gt repo governance - #26
Merged
Merged
Conversation
Onboards this repository onto gt's governance subsystem (pedromvgomes/gt#31). A committed .gt-repo.yaml is the source of truth and `gt repo sync` renders the files from it. Must not merge before gt v1 is cut: every rendered caller pins pedromvgomes/gt@v1, which does not exist yet. There is no .github/dependabot.yml here today, so this repository gains dependency updates for the first time — npm at the workspace root and github-actions — plus the daily auto-merge batch for patch and minor bumps. The npm entry is deliberately one entry at the ROOT. This is a pnpm workspace with a single pnpm-lock.yaml, so per-member entries for /page and /worker would edit only those manifests, leave the root lockfile stale, and fail every frozen-lockfile install. gt got this wrong on first detection — it decided workspace-root-ness from package.json's workspaces field, which pnpm does not use — and pedromvgomes/gt#31 now recognises pnpm-workspace.yaml. The reasoning is recorded as a note so a future sync cannot quietly re-split it. bulwark is on: no security scanning here today, so gt's stage is an addition rather than a duplicate. CD is off, and here it is a design question rather than a migration: deploy.yml already ships from pushes to main, so delivery is not tag-shaped at all. Turning CD on means deciding whether that changes. The ci-* stages land as empty no-ops and end2end is omitted. ci.yml, deploy.yml and validate-topology.yml keep running, and branch protection is unchanged. Claude-Session: https://claude.ai/code/session_01PvwKxJ5vnqa9h9XXyTEj43
Picks up pedromvgomes/gt#31's annotation. semgrep's secrets-inherit rule flagged the rendered orchestrator; gt cannot enumerate a repository's secret names, so the reasoning is recorded at each site rather than the rule being silenced. Claude-Session: https://claude.ai/code/session_01PvwKxJ5vnqa9h9XXyTEj43
The governance PR added the gt workflows but left ci.yml in place, so ci-gate went green on a pipeline that ran nothing. This moves the work. ci.yml's single `test` job becomes two stages: ci-build runs the type-check (for TypeScript the build is the type-check — the worker's own "build" script is `tsc --noEmit`) and ci-test runs `pnpm -r test`. Every step is carried over unchanged; the install is repeated because each stage is its own workflow on its own runner. ci.yml's concurrency group is dropped rather than lost — ci-orchestration.yml already cancels superseded PR runs. Both stages declare packages: read. @wardnet/* resolve from GitHub Packages, so a frozen-lockfile install fails without it, and a called workflow can only narrow what the caller granted. Action tags are pinned to the SHAs `@v4` resolved to at the time, so the move changes no behaviour; Dependabot owns bumps from here. .bulwark.yml goes back to `coverage.source: run`. It was scaffolded as `report` by an earlier pass, but nothing produces a report — neither workspace declares a test:coverage script and @vitest/coverage-v8 is not a dependency. Under `run` bulwark skips packages with no such script and reports no TypeScript coverage, which is at least true. Re-synced with gt 1.3.0: ci-orchestration.yml and dependabot-auto-merge.yml now name their secrets instead of inheriting them, which is what actually works across owners — gt lives under pedromvgomes, this repo under wardnet. `gt repo config` resolves identically before and after apart from the version stamp.
|
Onboarding put bulwark's TypeScript check on this repo for the first time
and it went red on code the governance PR never touched: bulwark's eslint
is not diff-scoped (--diff-base is passed to semgrep only), so the whole
back-catalogue arrives at once.
Of eslint-plugin-security's 14 findings, 13 were detect-object-injection
on typed record lookups. That rule fires on any obj[key] and cannot be
disabled on its own — .bulwark.yml has no rule-level exclusion — so the
choice was to suppress it at fourteen sites or to change linter. Biome's
security + correctness sets report five things instead, and unlike the
object-injection noise they are worth acting on:
- incidents.ts took a `from: Status` the body never read. Removed, with
its 21 call sites. A transition function advertising a parameter that
cannot affect the outcome misleads every caller.
- topology-file.test.ts used __dirname and node:path. Now a URL
relative to import.meta.url, which drops the node:path import and the
CommonJS global. fileURLToPath takes .href rather than the URL object
because @cloudflare/workers-types declares a global URL that is not
node:url's, and passing the object does not type-check.
- the same test's node:fs import is suppressed file-wide with a reason:
it reads the real topology.yaml off disk under vitest and is never
bundled into the Worker, which is the rule's actual concern.
- mockServiceWorker.js trips noSecrets on msw's integrity checksum.
bulwark's typescript.exclude only filters package discovery, and
Biome ignores a nested config under --config-path, so the suppression
has to be inline. msw regenerates that file and will drop it; CI says
so again if that happens. The file already carries msw's own
/* eslint-disable */, so it is in keeping.
Verified with bulwark v1.9.0, the release the action installs: biome
passes at the root and in both packages, and semgrep passes diff-scoped.
type-check and all 97 tests pass.
It ran one vitest file, worker/test/topology-file.test.ts, which `pnpm -r test` in ci-test now runs anyway. Keeping it meant the worker suite ran twice on any PR touching topology.yaml. Coverage widens rather than narrows. validate-topology.yml was filtered to `paths: [topology.yaml]`, so it only fired when that file changed; gt CI has no path filter and runs on every pull request and every push to main, and ci-preflight is still the scaffolded no-op that skips nothing. A topology.yaml pushed straight to main carries no prior attestation, so attest does not short-circuit the stages either. deploy.yml is untouched: it still skips topology-only pushes, because topology.yaml is fetched at runtime and needs no deploy. That is exactly why the schema gate has to exist somewhere else, and it is now ci-test. Both comments that pointed at the deleted file say so instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Onboards this repository onto gt's governance subsystem
(pedromvgomes/gt#31).
Important
Do not merge before gt
v1is cut. Every rendered caller pinspedromvgomes/gt@v1, which does not exist yet.Dependency updates, for the first time
There is no
.github/dependabot.ymlhere today. This adds one coveringnpmat the workspace root andgithub-actions, weekly with a 7-daycooldown, plus the daily auto-merge batch for patch and minor bumps.
The npm entry is deliberately one entry at the root, and this repository
is why gt can get it right. It is a pnpm workspace —
pnpm-workspace.yamllists
workerandpage— with a singlepnpm-lock.yaml. Per-memberentries for
/pageand/workerwould edit only thosepackage.jsonfiles, leave the root lockfile stale, and fail every frozen-lockfile
install.
gt got this wrong on first detection: it decided workspace-root-ness from
package.json'sworkspacesfield, which pnpm does not use — members livein the sibling YAML and the root manifest has no such field at all. So the
collapse never fired for the one package manager where the shared root
lockfile makes it matter most. Fixed in pedromvgomes/gt#31.
The reasoning is recorded as a
note:in the spec, so a future sync cannotquietly re-split it.
bulwark is on
No security scanning here today, so gt's stage is an addition rather than a
duplicate. Expect findings on the first run; nothing gates on them while
ci-gateis not the required check.CD is off — a design question, not a migration
deploy.ymlalready ships from pushes tomain, so delivery here is nottag-shaped at all, while
cd-orchestrationis built around a tag trigger.Turning CD on means deciding whether that changes — not just moving jobs.
Inert
The
ci-*stages land as empty no-ops;end2endis omitted.ci.yml,deploy.ymlandvalidate-topology.ymlkeep running, and branch protectionis unchanged.