Skip to content

Adding a devcontainer for local testing - #198

Merged
Strycher merged 1 commit into
masterfrom
chore/devcontainer
Oct 12, 2026
Merged

Strycher merged 1 commit into
masterfrom
chore/devcontainer

Conversation

@ITblacksheep

@ITblacksheep ITblacksheep commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Just a chore. Doesn't need a new push to staging.

Refs #200

@ITblacksheep

Copy link
Copy Markdown
Contributor Author

fixes #200

@diffwireauto

Copy link
Copy Markdown
Contributor

Reviewed the diff. The devcontainer is straightforward and the local E2E runner is careful work — mktemp workdir, trap cleanup EXIT, arg validation, sqlite3 presence check, server-liveness polling, log tail on failure, per-test rc accumulation. Being able to run one E2E test locally against a fresh fixture is a real gap closed.

One design concern worth your answer before this merges, and two smaller things.

The concern: e2e-local.sh scrapes deploy.yml to get the seeding SQL

WF=.github/workflows/deploy.yml
grep -E "sqlite3 test-fixtures/e2e-fixture.db \"UPDATE observers" "$WF" \
  | sed -E 's/^ *run: *//; s#test-fixtures/e2e-fixture.db#'"$DB"'#' | bash
awk '/sqlite3 test-fixtures\/e2e-fixture.db <<.SQL.$/{f=1;next} /^ *SQL$/{f=0} f' "$WF" | sqlite3 "$DB"

This extracts shell and SQL out of a YAML file by regex and pipes the result into bash and sqlite3. It works today, but it couples local E2E to the formatting of the workflow, not its behaviour. Any of these silently breaks it:

  • re-indenting the run: block
  • renaming the SQL heredoc delimiter
  • changing the quoting on the UPDATE observers line
  • splitting that step into two

And the failure mode is bad: grep finds nothing, the pipeline into bash succeeds with empty input, set -euo pipefail does not catch it, and you get a silently under-seeded fixture. Tests then fail for a reason that has nothing to do with the code under test — which is the same class of problem #199 exists to fix.

The fix is the pattern you used in #199. There you pulled duplicated server-start logic into scripts/e2e-fresh-server.sh and had the workflow call it. The seeding is the same shape: extract it to scripts/e2e-seed-fixture.sh "$DB", have deploy.yml call that, and have e2e-local.sh call the same script. One definition, both callers, no YAML parsing. These two PRs are landing within ten minutes of each other and are pulling in opposite directions on exactly this point.

Not insisting — if you want to land this now and extract the seeding as a follow-up, say so and I will file it rather than let it sit as a comment.

remoteEnv: { "CI": "true" }

Deliberate for parity, or carried over? It makes every local run take CI code paths — npm, Playwright reporters and several tools change behaviour on CI. That is useful for reproducing a CI failure and unhelpful when you want normal local behaviour. If it is for parity, worth a comment in devcontainer.json saying so, since the next person will wonder.

Nits

  • npm ci --production=false works but is the deprecated spelling; --include=dev is current.
  • scripts/e2e-local.sh has no trailing newline.
  • A few + lines in the Dockerfile are whitespace-only.
  • ARG GO_VERSION=1.26.0 pins the patch while CI uses GO_VERSION: '1.26' [repo: deploy.yml:44]. Your comment already says to keep them in step, which is the right call — just flagging it is two places.

State

✅ Go Build & Test, Docker image, Detect changes and the author-email check all pass; Playwright was still running when I looked.

Reviewed as diffwireauto on Strycher's request. Not approving or requesting changes — the scraping point is the only one I would want an answer on.

@diffwireauto diffwireauto left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving on Strycher's instruction ("Rebase and merge #198"), acting as diffwireauto.

Rebased onto 5206c709 (current master) — the rebase preserved content exactly, diff hash 41f6a50ce1c6989005014c23b48842e9640b039f before and after, and kept ITBlacksheep as commit author. New head 822b5f8f.

CI green on the rebased head: Playwright pass 18m54s, Go Build & Test pass 12m43s, Docker image, change-detection and author-email all pass. Also checked locally: bash -n scripts/e2e-local.sh clean, devcontainer.json parses as valid JSON.

The devcontainer itself is sound — Ubuntu 24.04, Node 22 and Go 1.26 pinned to match CI, plus sqlite3 and psmisc which the E2E scripts actually need. e2e-local.sh is careful: mktemp workdir with trap cleanup EXIT, argument validation, a sqlite3 presence check, it copies the fixture rather than mutating the tracked one, runs the goose baseline, polls readiness with a kill -0 liveness check, tails the log on failure, and accumulates a per-test exit code.

Merging with one known latent defect, deliberately

The YAML scraping in e2e-local.sh is unchanged:

WF=.github/workflows/deploy.yml
grep -E "sqlite3 test-fixtures/e2e-fixture.db \"UPDATE observers" "$WF" | sed ... | bash
awk '/sqlite3 test-fixtures\/e2e-fixture.db <<.SQL.$/{f=1;next} /^ *SQL$/{f=0} f' "$WF" | sqlite3 "$DB"

This is a real bug, not a style note: it breaks silently when deploy.yml is reformatted, an empty grep is not caught by set -euo pipefail, and the result is an under-seeded fixture so local tests fail for reasons unrelated to the code.

It is not blocking because its blast radius is one developer's local run. Nothing in CI invokes e2e-local.sh, nothing on prod depends on it, and it cannot produce a bad release. Filing the extraction as a follow-up so it is not lost — the fix is the pattern used in #199: move the seeding to scripts/e2e-seed-fixture.sh and have both deploy.yml and e2e-local.sh call it.

Two non-issues for the record: remoteEnv: CI=true is a deliberate parity choice in your own dev environment, and npm ci --production=false is a deprecated spelling that still works.

Refs #200.

@Strycher
Strycher merged commit d36d1ec into master Oct 12, 2026
9 checks passed
@diffwireauto

Copy link
Copy Markdown
Contributor

Merged as d36d1ecc by Strycher. Master run 38209079783 is fully green — Go Build & Test, Playwright, Docker image, and Deploy Staging all success. Dev is on d36d1ec and healthy.

The seeding-extraction concern from my review is filed as #203 so it does not get lost. Not urgent, and the reasoning for merging without it is on that issue: the blast radius is a single developer's local run, nothing in CI calls scripts/e2e-local.sh, and it cannot produce a bad release.

The fix there is the pattern you already used in #199 — pull the shared logic into scripts/ and have both callers use it. Your e2e-fresh-server.sh did it for the server start; #203 is the same move for the fixture seeding.

@diffwireauto
diffwireauto deleted the chore/devcontainer branch October 12, 2026 06:23
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.

3 participants