Skip to content

Commit a1ff7e6

Browse files
committed
fix(ci): guard UI-kit build/lint/typecheck/test/build steps with !cancelled()
An earlier, unrelated step failing anywhere in validate-code's long chain of drift checks (migrations, schema, env-reference, docs, manifest, engine-parity, branding, .nvmrc, release-manifest, observability, the MCP version audit) -- without continue-on-error -- skips every step after it by GitHub Actions' own default. "UI tests (ui-miner)" and "UI tests (miner-extension)" already had a !cancelled() guard for exactly this reason, but "Build UI-kit package", "Generate docs content collections", "UI lint", "UI typecheck", "UI tests (ui)", "Extension lint", "Extension typecheck", and "UI build" didn't. Confirmed live: a same-day MCP release tripped the version-audit step, which skipped "Build UI-kit package" entirely (no guard), and "UI tests (ui-miner)" (guarded, so it still ran) then failed with a confusing "Failed to resolve import '@loopover/ui-kit/components/...'" that looked like a real code regression instead of a skipped upstream build (PR #8182). The job as a whole still fails if any step fails -- this only stops one unrelated failure from masking every UI-specific result behind it, matching the resilience the two guarded test steps already had.
1 parent d89698d commit a1ff7e6

1 file changed

Lines changed: 26 additions & 10 deletions

File tree

.github/workflows/ci.yml

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -700,8 +700,21 @@ jobs:
700700
# dist -- so it does not exist on a fresh checkout until something builds it. Same class of gap
701701
# as "Build engine package" above; runs before UI lint/typecheck/tests/build all in this same
702702
# job, so building it here once covers all four.
703+
#
704+
# `!cancelled()` on this step and every UI step below it (through "UI tests (ui)"): this job runs
705+
# a long, unrelated chain of drift checks before reaching here (migrations, schema, env-reference,
706+
# docs, manifest, engine-parity, branding, .nvmrc, release-manifest, observability, the MCP
707+
# version audit just above, ...) -- any ONE of those failing without continue-on-error otherwise
708+
# skips every step after it by GitHub Actions' own default, INCLUDING this build. "UI tests
709+
# (ui-miner)"/"UI tests (miner-extension)" already had this guard (see their own comment below);
710+
# this build step and everything through "UI tests (ui)" didn't, so a same-day MCP release
711+
# tripping the version-audit step above skipped ui-kit's build entirely, and ui-miner's tests
712+
# (which DID still run, guarded) then failed with a confusing "Failed to resolve import
713+
# '@loopover/ui-kit/components/...'" that looked like a real code bug instead of a skipped
714+
# upstream build -- confirmed live, PR #8182. The job as a whole still fails if any step fails;
715+
# this only stops one unrelated failure from hiding/masking every UI result behind it.
703716
- name: Build UI-kit package
704-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
717+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
705718
run: npx turbo run build --filter=@loopover/ui-kit
706719
# apps/loopover-ui's fumadocs-mdx virtual modules (collections/browser, collections/server, imported by
707720
# docs-client-loader.tsx/docs-source.ts) are gitignored generated output, normally produced by npm ci's
@@ -711,7 +724,7 @@ jobs:
711724
# gap as "Build UI-kit package" above (a required, gitignored artifact absent on a fresh/cached
712725
# checkout); runs unconditionally here so cache hit or miss makes no difference.
713726
- name: Generate docs content collections
714-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
727+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
715728
run: npm run postinstall --workspace @loopover/ui
716729
# Routed through Turborepo -- "Build UI-kit package" above already built ui-kit's dist once for all of
717730
# lint/typecheck/tests/build in this same job (GitHub Actions steps run strictly sequentially), so
@@ -723,36 +736,39 @@ jobs:
723736
# package.json ui:lint/ui:typecheck scripts themselves, since ui-deploy.yml and CONTRIBUTING.md's
724737
# documented local gate sequence both call those directly and rely on their own ui:kit:build prefix.
725738
- name: UI lint
726-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
739+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
727740
run: npx turbo run lint --filter=@loopover/ui --filter=@loopover/ui-miner
728741
- name: UI typecheck
729-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
742+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
730743
run: npx turbo run typecheck --filter=@loopover/ui --filter=@loopover/ui-miner
731744
# Split into 3 independent steps (was one `&&`-chained step) -- turbo.json deliberately has no `test`
732745
# task for any package (per the plan doc: test orchestration stays out of Turborepo entirely, so
733746
# Codecov's codecov/patch keeps one centralized source of truth), so this can't use the same
734747
# union-`--filter` fix already applied to "UI lint"/"UI typecheck" two steps above. Plain `&&` meant a
735748
# failing @loopover/ui test silently prevented @loopover/ui-miner's and @loopover/miner-extension's
736749
# tests from ever running in that invocation -- same class of failure-masking bug those two steps'
737-
# own comment already describes, just still present here. `!cancelled()` on steps 2/3 (not `always()`)
750+
# own comment already describes, just still present here. `!cancelled()` on all 3 (not `always()`)
738751
# matches the pattern already used by "Save Turborepo cache"/"Save TypeScript incremental build
739752
# cache" elsewhere in this file: still run after an earlier step's failure, just not after the job
740753
# was cancelled outright. The job as a whole still fails if any of the three fails.
741754
- name: UI tests (ui)
742-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
755+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
743756
run: npm --workspace @loopover/ui run test
744757
- name: UI tests (ui-miner)
745758
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
746759
run: npm --workspace @loopover/ui-miner run test
747760
- name: UI tests (miner-extension)
748761
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
749762
run: npm --workspace @loopover/miner-extension run test
750-
# Same rationale and --filter union semantics as "UI lint"/"UI typecheck" above.
763+
# Same rationale and --filter union semantics as "UI lint"/"UI typecheck" above -- and the same
764+
# `!cancelled()` need as "Build UI-kit package" through "UI tests (ui)" above: an earlier
765+
# unrelated step failing (a drift check, the MCP version audit) would otherwise skip these too,
766+
# silently hiding real Extension lint/typecheck results behind it.
751767
- name: Extension lint
752-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
768+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
753769
run: npx turbo run lint --filter=@loopover/extension --filter=@loopover/miner-extension
754770
- name: Extension typecheck
755-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
771+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
756772
run: npx turbo run typecheck --filter=@loopover/extension --filter=@loopover/miner-extension
757773
# `npm run ui:build` also regenerates apps/loopover-ui/public/openapi.json (needed for a
758774
# standalone build), but this step's trigger condition is a strict subset of "OpenAPI drift
@@ -768,7 +784,7 @@ jobs:
768784
# and running this exact invocation regenerates it correctly (the cross-package outputs edge is
769785
# honored, not just replayed from cache).
770786
- name: UI build
771-
if: ${{ github.event_name == 'push' || needs.changes.outputs.ui == 'true' }}
787+
if: ${{ !cancelled() && (github.event_name == 'push' || needs.changes.outputs.ui == 'true') }}
772788
run: npx turbo run build --filter=@loopover/ui
773789
# Paired with "Restore Turborepo cache" above (same key, same gate condition) -- deliberately
774790
# positioned here, after every turbo-routed step in this job (Build engine package, Build MCP, Build

0 commit comments

Comments
 (0)