Skip to content

ci(e2e): only run bronze→API suite when product paths change - #1

Closed
ktursunov wants to merge 1 commit into
mainfrom
e2e-triggers-fix
Closed

ktursunov wants to merge 1 commit into
mainfrom
e2e-triggers-fix

Conversation

@ktursunov

Copy link
Copy Markdown
Owner

What

Rework the E2E — Bronze to API workflow so it stops running the ~30-min suite on docs-only and other non-product PRs, without reintroducing the required-check "Expected forever" hang that the original no-paths: design was avoiding.

Why

The suite deliberately triggered on every PR (no paths: filter) because a path-filtered required status check stays stuck on "Expected — Waiting for status" forever on PRs outside the filter, blocking merge. The cost: docs/non-product PRs paid a full bronze→API run (clickhouse + mariadb + dbt + pytest) for an outcome that couldn't change.

How

Mirrors the changes → work → gate topology already used in ci.yml, so relevance is decided inside the workflow and the required check always reports:

  • changes — always runs on every PR; git diff against main; sets run=true only when a path the suite actually consumes changed. workflow_dispatch always runs.
  • e2e (Run E2E suite) — the existing suite, unchanged, now gated on needs.changes.outputs.run == 'true'.
  • e2e-gate (E2E gate) — always runs to completion; green when the suite passed or was legitimately skipped, red only when detection or the suite actually failed. New required status check.
  • Added a concurrency group so a force-push cancels an in-flight run.

Trigger paths

Chosen from what the suite reads at build/test time (src/ingestion/tests/e2e/lib/config.py + compose build contexts):

Path Trigger Reason
src/backend/** analytics-api compiled into the runner + its dbt manifest dir
src/ingestion/** dbt project, CH/Maria migrations, connector enrich, the e2e harness/fixtures
.github/workflows/e2e-bronze-to-api.yml the workflow itself
deploy/** rig ships its own compose/seed under tests/e2e; never reads deploy/
src/frontend/** suite stops at the analytics-api HTTP layer

⚠️ Required action after merge

Update branch protection to require E2E gate instead of Run E2E suite. The latter is now conditionally skipped and would hang docs-only PRs if left as the required check.

The E2E suite deliberately triggered on every PR (no paths filter) because
a path-filtered required status check hangs on 'Expected' forever for PRs
outside the filter. That means docs-only and other non-product PRs paid the
full ~30-min bronze→API run for nothing.

Rework triggers to the changes→work→gate topology already used in ci.yml so
the suite is gated without reintroducing the hang:

- changes: always runs, diffs the PR against main, sets run=true only when a
  path the suite actually consumes changed — src/backend/** (analytics-api
  baked into the runner + its dbt manifest dir) and src/ingestion/** (dbt
  project, CH/Maria migrations, connector enrich, and the e2e harness itself),
  plus this workflow file. Not deploy/** (rig ships its own compose/seed) or
  src/frontend/** (suite stops at the analytics-api HTTP layer).
- e2e: the existing suite, now gated on changes.outputs.run.
- e2e-gate: always runs; green when the suite passed or was legitimately
  skipped, red only on real failure. This is the new required status check.

Also add a concurrency group so a force-push cancels an in-flight run.

NOTE: branch protection must require 'E2E gate' instead of 'Run E2E suite'
(the latter is now conditionally skipped and would hang docs-only PRs).

Signed-off-by: Konstantin Tursunov <Konstantin.Tursunov@constructor.tech>
@ktursunov ktursunov closed this Jul 1, 2026
@ktursunov
ktursunov deleted the e2e-triggers-fix branch July 1, 2026 15:41
@ktursunov
ktursunov restored the e2e-triggers-fix branch July 1, 2026 15:43
ktursunov pushed a commit that referenced this pull request Jul 2, 2026
…eline (#1, constructorfabric#3)

The drift check was a Rube Goldberg pipeline: serve /openapi.json -> boot the full
stack -> collect openapi.live.json -> upload -> a separate CI job -> openapi_spec.py
diffs. It's fundamentally one golden-file test, and the registry builds the doc
with NO AppState (build_openapi runs before .with_state), so it needs no app boot.

- api/mod.rs: split build_registry() out of router() (registry populated with no
  state); add #[cfg(test)] openapi_spec_matches_committed — canonical-sorts the
  built spec and diffs the committed docs/.../openapi.json. UPDATE_OPENAPI=1 cargo
  test … regenerates it. The runtime GET /openapi.json route stays (cheap, serves
  the contract per the gears comparison). Verified in rust:1.95: the canonical
  output is byte-identical to the committed doc, so the doc is unchanged.
- Delete scripts/ci/openapi_spec.py; the drift gate now runs in backend-checks'
  cargo llvm-cov (which executes the suite). No artifact round-trip.
- collect_coverage_artifacts.py: collect only catalog_metrics.json (no live spec).
- e2e workflow: drop the openapi-spec-drift-gate job (constructorfabric#3 — now just e2e +
  metric-coverage-gate). e2e.sh gates + README repointed to the cargo test.

Validated: cargo test (regenerate + verify) green; doc byte-identical; e2e
workflow parses (2 jobs); collectors/conftest compile.

Signed-off-by: Konstantin Tursunov <Konstantin.Tursunov@constructor.tech>
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