Skip to content

fix(ci): stop regenerating the OpenAPI spec twice in the same UI build - #2444

Merged
JSONbored merged 2 commits into
mainfrom
fix/ui-build-openapi-double-regen
Jul 2, 2026
Merged

JSONbored merged 2 commits into
mainfrom
fix/ui-build-openapi-double-regen

Conversation

@JSONbored

@JSONbored JSONbored commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • ui:build (extension:build && vite build) also runs ui:openapi, which recomputes and rewrites apps/gittensory-ui/public/openapi.json unconditionally. Both places that chain it after ui:openapi:check in the same job/step — ci.yml's "UI build" step, ui-deploy.yml's "Validate frontend" step — pay for that regeneration twice: the check step immediately before it already proved the committed spec is byte-identical to what regenerating it would produce.
  • Fixed by running ui:build's other two steps (extension:build, the vite build) directly in both places instead of the aggregate script. ui:build itself is untouched, so anyone invoking it standalone (local dev, or any future call site without a preceding check) still gets a correct, freshly-generated spec — this is scoped to the two places that already verify freshness first.
  • ci.yml's "UI build" step's trigger condition (push || ui==true) is a strict subset of "OpenAPI drift check"'s (push || ui==true || uiContract==true), so the check step is guaranteed to have already run and passed whenever the build step runs — confirmed by reading both if: conditions.
  • Added test/unit/ci-ui-build-openapi.test.ts: a small guardrail test (mirroring workflow-runner-labels.test.ts's style) that fails if either step regresses back to invoking the aggregate npm run ui:build. Verified it actually catches the regression by reverting the fix locally and confirming the test fails, then restoring.

Scope

Validation

  • git diff --check
  • npm run actionlint
  • npm run typecheck
  • npm run test:coverage — full unsharded run green (96.51% stmts / 95.49% branches), including the new guardrail test.
  • npm run test:workers
  • npm run build:mcp
  • npm run test:mcp-pack
  • npm run ui:openapi:check
  • npm run ui:lint
  • npm run ui:typecheck
  • npm run ui:build
  • npm audit --audit-level=moderate
  • Full npm run test:ci green end to end.
  • Manually verified the fix's actual behavior: ran ui:openapi:check then the two split commands (extension:build, the vite build) directly — build succeeds, and apps/gittensory-ui/public/openapi.json is untouched (git status shows no diff) throughout, confirming no redundant regeneration and no behavior change to the output.
  • Manually verified the new regression test: reverted the fix locally, confirmed test/unit/ci-ui-build-openapi.test.ts fails, then restored the fix and confirmed it passes again.

Safety

  • No secrets, wallet details, hotkeys, coldkeys, user PATs, private keys, raw trust scores, private rankings, or private maintainer evidence are exposed.
  • Public GitHub text stays sanitized, low-noise, and does not imply compensation guarantees or optimization tactics.
  • N/A — no auth, cookie, CORS, GitHub App, Cloudflare, or session changes.
  • N/A — no API/OpenAPI/MCP behavior change; this only changes when the (unchanged) generator script runs, not what it produces.
  • N/A — no UI code changes.
  • N/A — no visible UI change; this is CI-workflow-only.
  • N/A — no docs/changelog changes needed.

Notes

`ui:build` (extension:build + vite build) also runs `ui:openapi`, which
recomputes and rewrites apps/gittensory-ui/public/openapi.json unconditionally.
In both call sites that chain it after `ui:openapi:check` in the same job
(ci.yml's "UI build" step, ui-deploy.yml's "Validate frontend" step), that
regeneration is pure repeat work: the check step immediately before it just
proved the committed spec is already byte-identical to what regenerating it
would produce.

ci.yml's "UI build" step's trigger condition (push || ui==true) is a strict
subset of "OpenAPI drift check"'s (push || ui==true || uiContract==true), so
the check step is guaranteed to have already run and passed whenever the build
step runs. ui-deploy.yml chains both unconditionally in one command. In both
places, run ui:build's other two steps (extension:build, the vite build)
directly instead of the aggregate script. ui:build itself is untouched, so
anyone invoking it standalone (local dev, or any future call site without a
preceding check) still gets a correct, freshly-generated spec.

Verified locally: running `ui:openapi:check` then the two split commands
produces an identical build to `npm run ui:build`, and leaves
apps/gittensory-ui/public/openapi.json byte-for-byte unchanged (untouched by
git status) throughout.
@dosubot dosubot Bot added the size:XS label Jul 2, 2026
@loopover-orb

loopover-orb Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-02 01:08:42 UTC

3 files · 1 AI reviewer · no blockers · readiness 93/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review

Review summary
The workflow changes correctly split the UI build into the two non-OpenAPI commands only at call sites that already run `ui:openapi:check`, while leaving the aggregate `ui:build` path intact for standalone callers. The CI step ordering and `if:` conditions in `ci.yml` support the stated invariant, and `ui-deploy.yml` runs the check in the same shell chain before the split build. The added test is narrow but useful as a regression guard for these two workflow call sites.

Nits — 3 non-blocking
  • nit: test/unit/ci-ui-build-openapi.test.ts:11 relies on slicing the CI step by the next blank line, which is fragile if the workflow formatting changes around adjacent comments or multi-line YAML blocks.
  • test/unit/ci-ui-build-openapi.test.ts:11 would be more robust if it parsed the workflow YAML or matched the `UI build` step with a bounded regex that stops at the next `- name:` entry instead of the next blank line.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 1 reviewer
Linked issue ✅ No-issue rationale PR body explains why no issue is linked.
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (size label size:XS; no linked issue context).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 65 registered-repo PR(s), 55 merged, 563 issue(s).
Contributor context ✅ Confirmed Gittensor contributor JSONbored; Gittensor profile; 65 PR(s), 563 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Review context
  • Author: JSONbored
  • Role context: owner (maintainer lane)
  • Public audience mode: oss maintainer
  • Lane context: Repository registration is not available in the local Gittensory cache.
  • Public profile languages: Python, TypeScript, JavaScript, Ruby, Go, Kotlin, MDX, Shell
  • Official Gittensor activity: 65 PR(s), 563 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Treat this as maintainer-lane context rather than normal contributor-lane activity.
  • Triage stale or unlinked PRs.
  • No action.
  • Link the issue being solved, or explicitly explain why this is a no-issue PR.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot added gittensor gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier. labels Jul 2, 2026
…ssion test

The prior commit removed the aggregate ui:build call from both places that
chain it after ui:openapi:check in the same job. Add a small guardrail test
(mirroring workflow-runner-labels.test.ts's raw-string read-and-assert style)
that fails if either step's run command regresses back to invoking `npm run
ui:build` -- verified locally by reverting the fix and confirming this test
catches it before restoring.
@codecov

codecov Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 95.90%. Comparing base (9d58403) to head (98619a2).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2444   +/-   ##
=======================================
  Coverage   95.90%   95.90%           
=======================================
  Files         224      224           
  Lines       25175    25175           
  Branches     9154     9154           
=======================================
  Hits        24143    24143           
  Misses        419      419           
  Partials      613      613           
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JSONbored
JSONbored merged commit 8f6373f into main Jul 2, 2026
12 checks passed
@JSONbored
JSONbored deleted the fix/ui-build-openapi-double-regen branch July 2, 2026 01:12
@github-project-automation github-project-automation Bot moved this from Todo to Done in gittensory - v1 roadmap Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix — scores a 0.05x multiplier.

Projects

No open projects
Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant