Skip to content

Fix deploy concurrency and slim frontend SSR image - #1286

Closed
daveearley wants to merge 2 commits into
developfrom
feature/deploy-testing
Closed

Fix deploy concurrency and slim frontend SSR image#1286
daveearley wants to merge 2 commits into
developfrom
feature/deploy-testing

Conversation

@daveearley

Copy link
Copy Markdown
Contributor

Test branch for validating the staging deploy path. feature/deploy-testing is temporarily added to the deploy.yml push triggers so merges here exercise the workflow end to end.

deploy.yml

Concurrency. Added a workflow-level concurrency group keyed on target environment, cancel-in-progress: false. Back-to-back merges previously ran two overlapping deploys, so whichever vapor deploy finished last won β€” not whichever merged last. Runs now queue. Keying on environment rather than github.ref also closes the case where a dispatched production deploy from a non-main branch could run alongside a main push.

Deployment phase handling. The poll loop checked for a FAILED phase, which does not exist in the DigitalOcean API. Real phases are UNKNOWN, PENDING_BUILD, BUILDING, PENDING_DEPLOY, DEPLOYING, ACTIVE, SUPERSEDED, ERROR, CANCELED. Consequences:

  • ERROR (a genuinely broken build) fell through and burned the full timeout, reporting "Deployment timed out" instead of the real failure.
  • SUPERSEDED (what happens on back-to-back merges) did the same, producing a red X on a deploy that was fine.

Now handled explicitly: ACTIVE β†’ pass, SUPERSEDED β†’ pass with a note, ERROR/CANCELED β†’ fail and name the state. Timeout raised 10 β†’ 15 min so a slow cold build doesn't report a false failure.

frontend image

Dockerfile.ssr rebuilt as a 4-stage build: pinned node:22-alpine, BuildKit yarn cache mounts, --frozen-lockfile, production-only runtime deps, messages:extract dropped from the build.

2.84 GB β†’ 412 MB (βˆ’85%). Build time unchanged (~53s).

Two things this surfaced:

  • node:alpine now resolves to Node 26, which no longer bundles yarn, so apk add yarn was pulling Alpine's own nodejs 24.17.0 in as a dependency β€” the image shipped two Node runtimes, on a version nobody develops against. Pinning to 22 fixes both.
  • server.js imported vite (a devDependency) at the top level, blocking any production-only install. Moved to a dynamic import inside the existing dev branch.

dependencies

Five packages were imported at SSR runtime but declared nowhere, surviving only via hoisting. lodash was the live bug: it reached the app through @lingui/vite-plugin β†’ @lingui/cli β†’ inquirer, all dev-only. NumberSelector imports it, and that renders on the tiered ticket-selection page β€” so a production-only install would have crashed SSR on the ticket-buying page while the homepage stayed green.

Promoted to dependencies: lodash, @lingui/core, invariant, react-fast-compare, shallowequal. @lingui/cli added to devDependencies β€” yarn build depends on that same fragile chain.

Pinned to exact versions deliberately: ^4.17.21 resolves to lodash 4.18.1, and this change should not carry a silent upgrade. All six resolve to exactly the previously-hoisted versions, so the change is behaviour-neutral.

Testing

Full E2E suite against the new image: 123 passed, 4 failed.

The 4 failures are pre-existing on develop β€” verified by rebuilding the frontend from the original Dockerfile and re-running the same specs, which fails identically:

promo-code-checkout.spec.ts:88   per-order fixed code discounts the order once, not per ticket
promo-code-checkout.spec.ts:115  per-order discount that cannot split evenly stays exact by splitting a line
promo-code-checkout.spec.ts:139  per-order discount is split pro-rata across multiple products
management/promo-codes.spec.ts:20 per-order fixed code β€” edit modal restores its settings

All four sit in per-order promo allocation and look like a genuine gap worth its own issue.

E2E only covers production mode, so the dev SSR path was verified separately β€” NODE_ENV=development node server.js boots and serves 200 through the dynamic vite import.

Notes

  • The image change does not affect this deploy. DigitalOcean builds the frontend via buildpack (environment_slug: node-js), not Dockerfile.ssr. It affects the E2E suite, released images, and self-hosters β€” and materially de-risks a future container platform, where cold start scales with image size.
  • feature/deploy-testing should come out of the push triggers before merge. feature/vapor-env-updates is also still listed and looks stale.
  • Worth confirming whether deploy_on_push is set on the real staging/production DO apps. If it is, every push triggers a DO deploy and the workflow triggers a second one, which will now surface as SUPERSEDED rather than a red X.

@railway-app
railway-app Bot temporarily deployed to Hi.Events / Hi.Events-pr-1286 July 28, 2026 20:48 Destroyed
@daveearley

Copy link
Copy Markdown
Contributor Author

Superseded by #1287, which drops the temporary feature/deploy-testing push trigger.

@daveearley daveearley closed this Jul 28, 2026
@railway-app
railway-app Bot temporarily deployed to Hi.Events / Hi.Events-pr-1286 July 28, 2026 21:16 Destroyed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant