fix(ci): repair backend startup crash and CI workflow config on main - #1091
Merged
Conversation
main has been broken since a series of bad merges landed. This fixes every currently-failing check on main-branch CI: - backend/src/jobs/eventIndexer.js: a merge dropped a comment's opening `/**` and the Semaphore class's closing `}`, leaving doc-comment text as bare tokens. Node can't parse the module, so the backend crashed on every boot (root cause of Security Headers Check failing on every recent commit). - backend/src/index.js: two more merge artifacts — `indexerRepository` and `defaultRateLimiter` were referenced in the /graphql route wiring but never declared anywhere in scope. - backend/src/db/migrations/037_outbox.js: missing the required `version`/`description` exports, so the migration runner threw instead of applying it. - backend/src/db/migrations/038 (new): 026_notification_preferences.js and 026_operator_balance_log.js share version 26, so the checked-in trivela.db (which already has 26 recorded from whichever file ran first) never got notification_channel_settings created, crashing the notification repository at boot. Same disease as the existing 034 backfill migration for the version-13 collision; this heals it the same way with a fresh version number. - .github/workflows/frontend-ci.yml: a bad merge dropped the `accessibility` job's `steps:` entirely and spliced its steps into `cross-browser-e2e` instead, producing an invalid job with no steps and no `uses:` — GitHub can't even schedule the workflow. Split the steps back into their own jobs. - .github/workflows/performance-gate.yml: `actions-rs/toolchain@v1` is unmaintained and doesn't install the wasm32-unknown-unknown target that `stellar-cli` needs to build. Swapped for `dtolnay/rust-toolchain` with the target declared explicitly, matching the working pattern already used in ci-performance.yml. - Repo-wide `prettier --write` per format:check's own globs — 50 files had drifted since nobody had run it before committing. Verified locally: backend now boots clean and GET /health returns 200 with every header Security Headers Check greps for; all workflow YAML re-validated; `node --check` clean across backend/src.
| purged.push({ table, count: result.changes }); | ||
| log.info(`[pii-purge] Deleted ${result.changes} rows from ${table} for campaign ${campaignId}`); | ||
| log.info( | ||
| `[pii-purge] Deleted ${result.changes} rows from ${table} for campaign ${campaignId}`, |
Follow-up to the previous commit, after watching the PR's actual GitHub
Actions run rather than just the reduced main-branch check set:
- backend/src/jobs/eventIndexer.js: an orphaned early
`return { processEvent, poll, pollWithCursor };` sat in the middle of
createEventIndexer (left behind by the same merge that broke the
header comment, from before gap-detection/reorg-safety/SSE support
existed). It silently made every function after it — getState,
getCursor, updateCursor, getHealth, getMetrics, startSse,
confirmPending, detectReorg, handleReorg, and the real final return —
dead code. None of those were ever actually reachable at runtime.
Confirmed against the commit that authored the stray line: in that
commit it was the correct final return; later merges added the real
feature set after it without removing it.
- backend/src/index.js: gracefulShutdown (in startServer) assigned
`isShuttingDown = true` directly, but that variable is local to
createApp — a different top-level function. Since ES modules are
strict mode, this throws ReferenceError the moment SIGTERM/SIGINT
fires, crashing the shutdown handler instead of shutting down
gracefully. The very next line, `app._close?.()`, already flips the
flag correctly through createApp's own closure — removed the
redundant broken assignment.
- backend/src/services/cacheService.js: empty `catch {}` in
CacheService.clear() failed eslint's no-empty rule. Added a comment
explaining it's an intentional best-effort swallow.
- .github/workflows/performance-gate.yml: the `load-test` job's
`npm run build` step compiles the Rust contracts too, but the job
had no Rust setup at all — same missing wasm32-unknown-unknown
target as gas-profiling. Added the same dtolnay/rust-toolchain step.
Separately, gas-profiling's `cargo install stellar-cli` needs
libdbus-1-dev + pkg-config on the runner; added an apt-get step.
- frontend: `prettier --write .` — 8 .jsx files had drifted from the
frontend workspace's own format:check globs (separate from the root
format:check fixed previously, which doesn't cover frontend/src).
Verified: backend lint now 0 errors (was 3: no-undef, no-unreachable,
no-empty); backend still boots clean with /health returning all
security headers; SIGTERM now logs "graceful shutdown complete"
instead of crashing; frontend format:check passes; performance-gate.yml
re-validated as YAML.
- .github/workflows/monitoring-ci.yml: amtool doesn't expand \${VAR}
references — the workflow set SLACK_WEBHOOK_URL/PAGERDUTY_SERVICE_KEY
as step env vars assuming amtool would resolve them itself, but
amtool check-config just reads the literal file, so it tried to
parse the literal string "${SLACK_WEBHOOK_URL}" as a URL and failed
with "unsupported scheme". Render a throwaway copy through envsubst
first, then validate that. Confirmed locally: only the two intended
placeholders get substituted, nothing else in the file changes.
- frontend/src/components/PageMeta.test.jsx: react-helmet-async commits
its <head> tags via requestAnimationFrame, not synchronously during
render(), so all 11 assertions were reading the pre-mount DOM and
getting undefined. Not a component bug — PageMeta.jsx's tags are
correct. Made renderMeta async and await one animation frame before
asserting. Verified: all 11 tests pass, and the full frontend suite
(36 files, 422 tests) passes clean.
sdk/client's generate script (openapi-ts) cleans its entire --output directory before writing, and the hand-written ZK proof module (zk/index.ts, zk/proof.worker.ts, zk/types.ts — a Web Worker and its types, not generator output) lived inside that same directory. Running "the fix" (regenerate + commit, which is what the CI check effectively asks contributors to do locally) would have silently deleted real source code. Confirmed nothing in the repo currently imports zk/, so relocating it to sdk/client/zk/ (a sibling of the generated src/) needed no import-path updates. Added an explicit "./zk" export in package.json so it stays consumable at @trivela/client/zk if/when it's wired up. With zk/ out of the way, ran the actual generate step and it reveals real (and previously invisible) drift: backend/openapi.yaml has PII export/purge endpoints and ApiKeyRateTier that were never regenerated into the committed client. Committing that regenerated output — it's mechanical, spec-driven, no hand-written logic involved.
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.
main has been broken since a series of bad merges landed. This fixes
every currently-failing check on main-branch CI:
/**and the Semaphore class's closing}, leaving doc-comment textas bare tokens. Node can't parse the module, so the backend crashed
on every boot (root cause of Security Headers Check failing on every
recent commit).
indexerRepositoryand
defaultRateLimiterwere referenced in the /graphql route wiringbut never declared anywhere in scope.
version/descriptionexports, so the migration runner threwinstead of applying it.
and 026_operator_balance_log.js share version 26, so the checked-in
trivela.db (which already has 26 recorded from whichever file ran
first) never got notification_channel_settings created, crashing the
notification repository at boot. Same disease as the existing 034
backfill migration for the version-13 collision; this heals it the
same way with a fresh version number.
accessibilityjob'ssteps:entirely and spliced its steps intocross-browser-e2einstead, producing an invalid job with no stepsand no
uses:— GitHub can't even schedule the workflow. Split thesteps back into their own jobs.
actions-rs/toolchain@v1isunmaintained and doesn't install the wasm32-unknown-unknown target
that
stellar-clineeds to build. Swapped fordtolnay/rust-toolchainwith the target declared explicitly, matching the working pattern
already used in ci-performance.yml.
prettier --writeper format:check's own globs — 50 fileshad drifted since nobody had run it before committing.
Verified locally: backend now boots clean and GET /health returns 200
with every header Security Headers Check greps for; all workflow YAML
re-validated;
node --checkclean across backend/src.