Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,15 @@ name: CI
on: [push, pull_request]

jobs:
build:
lint-typecheck-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: "10.28.0"
node-version: "22"
- name: Enable Corepack
run: corepack enable
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Lint
Expand All @@ -23,3 +20,44 @@ jobs:
run: pnpm run typecheck
- name: Build
run: pnpm run build
- name: Test
run: pnpm test

docker-build:
needs: lint-typecheck-test
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
with:
driver: docker-container
- name: Log in to GHCR
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build (PR, cache-from only)
if: github.event_name == 'pull_request'
uses: docker/bake-action@v5
with:
files: docker/bake.hcl
targets: ci-core
set: |-
*.platform=linux/amd64,linux/arm64
*.cache-to=
- name: Build and push (main)
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: docker/bake-action@v5
with:
files: docker/bake.hcl
targets: default
push: true
set: |-
*.platform=linux/amd64,linux/arm64
CACHE_FROM_ONLY=false
71 changes: 39 additions & 32 deletions .kiro/specs/build-devx-overhaul/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,56 +123,63 @@ D).

## Phase C: Compose Collapse

- [ ] **C.1** Create `/Users/ben/Projects/wavekit/compose.yaml` per the design §3 with four profiles (`dev`, `prod-single-host`, `prod-distributed`, `demod-test`). _Requirements: 2.1–2.5_
- [ ] **C.2** Each service with a `build:` block declares `cache_from` pointing at the relevant `ghcr.io/coriou/wavekit:cache-*` registry refs (for now this is harmless; in Phase D those refs get populated). _Requirements: 2.5_
- [ ] **C.3** Verify `docker compose --profile dev config` parses without warnings. _Requirements: 2.1, 2.6_
- [ ] **C.4** Verify `docker compose --profile prod-single-host config` parses without warnings. _Requirements: 2.2_
- [ ] **C.5** Verify `docker compose --profile prod-distributed config` parses without warnings. _Requirements: 2.3_
- [ ] **C.6** Verify `docker compose --profile demod-test config` parses without warnings. _Requirements: 2.4_
- [ ] **C.7** Delete `/Users/ben/Projects/wavekit/docker-compose.dev.yml`. _Requirements: 2.6, 2.7_
- [ ] **C.8** Delete `/Users/ben/Projects/wavekit/docker-compose.prod.yml`. _Requirements: 2.6_
- [ ] **C.9** Delete `/Users/ben/Projects/wavekit/docker-compose.override.yml`. _Requirements: 2.6_
- [ ] **C.10** Delete `/Users/ben/Projects/wavekit/docker-compose.demod-test.yml`. _Requirements: 2.6_
- [ ] **C.11** Delete `/Users/ben/Projects/wavekit/docker/Dockerfile.demod-test`. _Requirements: 3.12_
- [ ] **C.12** Run end-to-end: `docker compose --profile dev up --build`. wavekit-api SHALL reach `service_healthy`. `curl localhost:9000/health` SHALL return 200. _Requirements: 2.1_
- [x] **C.1** Create `/Users/ben/Projects/wavekit/compose.yaml` per the design §3 with four profiles (`dev`, `prod-single-host`, `prod-distributed`, `demod-test`). _Requirements: 2.1–2.5_
- [x] **C.2** Each service with a `build:` block declares `cache_from` pointing at the relevant `ghcr.io/coriou/wavekit:cache-*` registry refs (for now this is harmless; in Phase D those refs get populated). _Requirements: 2.5_
- [x] **C.3** Verify `docker compose --profile dev config` parses without warnings. _Requirements: 2.1, 2.6_
- [x] **C.4** Verify `docker compose --profile prod-single-host config` parses without warnings. _Requirements: 2.2_
- [x] **C.5** Verify `docker compose --profile prod-distributed config` parses without warnings. _Requirements: 2.3_
- [x] **C.6** Verify `docker compose --profile demod-test config` parses without warnings. _Requirements: 2.4_
- [x] **C.7** Delete `/Users/ben/Projects/wavekit/docker-compose.dev.yml`. _Requirements: 2.6, 2.7_
- [x] **C.8** Delete `/Users/ben/Projects/wavekit/docker-compose.prod.yml`. _Requirements: 2.6_
- [x] **C.9** Delete `/Users/ben/Projects/wavekit/docker-compose.override.yml`. _Requirements: 2.6_
- [x] **C.10** Delete `/Users/ben/Projects/wavekit/docker-compose.demod-test.yml`. _Requirements: 2.6_
- [x] **C.11** Delete `/Users/ben/Projects/wavekit/docker/Dockerfile.demod-test`. _Requirements: 3.12_
- [x] **C.12** Run end-to-end: `docker compose --profile dev up --build`. wavekit-api SHALL reach `service_healthy`. `curl localhost:9000/health` SHALL return 200. _Requirements: 2.1_
- **Notes**: Three deviations from design.md §3 were necessary to make the gate pass; each is documented inline in compose.yaml.
1. **sdrpp-server healthcheck**: design.md prescribes `curl -fsS http://localhost:5259/`, but SDR++ in server mode speaks its own binary protocol on 5259, not HTTP, so curl fails on every probe with `HTTP/0.9 not allowed`. Switched to `bash -c '</dev/tcp/localhost/5259'` TCP probe. Same change applied to prod-distributed's `wavekit-sdrpp-prod` for consistency.
2. **wavekit-api port mapping**: design.md prescribes `9000:9000`, but `config/default.yaml`'s `api.port=3000` makes the container bind 3000. The s6-supervised process does not inherit `WAVEKIT_API_PORT` env from `docker exec`-style container env (s6 env-isolation: only `with-contenv` would propagate, which is a Phase B-scope script change). Mapped `9000:3000` to match the legacy `make dev-up -p 9000:3000` pattern, so the user-facing `curl http://localhost:9000/health` works. The wavekit-api healthcheck (which runs inside the container) probes `http://localhost:3000/health` to match the actually-bound port. Follow-up: update `config/default.yaml` or add `with-contenv` to make env override work, then revert to `9000:9000`.
3. **start-sdrpp.sh `--log-level info`**: pre-existing Phase A/B regression — SDR++ v1.1.0 doesn't accept `--log-level` and crash-loops with `basic_string from null` `std::logic_error`. Removed the flag from `docker/scripts/start-sdrpp.sh` to unblock C.12. This script wasn't in Phase C's "do not touch" list and the bug fully blocked the gate.
- **C.12 result**: `wavekit-sdrpp` reached `(healthy)` after ~60s of init-time crash-loop (writing first-run config files). `wavekit-api` reached `(healthy)` 7s after start. `curl http://localhost:9000/health` returned `{"status":"ok","timestamp":"..."}` immediately.

## Phase D: Bake + Registry Cache

- [ ] **D.1** Write `/Users/ben/Projects/wavekit/docker/bake.hcl` per design §4.3. Define `_base`, all four final-target bakes, the `ci-core` helper target, the `default` group, and the `demod` group. _Requirements: 5.2, 5.3, 4.4_
- [x] **D.1** Write `/Users/ben/Projects/wavekit/docker/bake.hcl` per design §4.3. Define `_base`, all four final-target bakes, the `ci-core` helper target, the `default` group, and the `demod` group. _Requirements: 5.2, 5.3, 4.4_
- [ ] **D.2** Test bake locally: `docker buildx bake --file docker/bake.hcl default --set "*.platform=linux/amd64"`. All three targets in `default` SHALL build successfully. _Requirements: 5.2_
- [ ] **D.3** Test multi-arch bake: `docker buildx bake --file docker/bake.hcl ci-core --set "*.platform=linux/amd64,linux/arm64"`. Build SHALL succeed without `--push` (uses local layer cache for both arches). _Requirements: 5.4_
- [ ] **D.4** Rewrite `/Users/ben/Projects/wavekit/docker/build.sh` as a thin wrapper that delegates to `docker buildx bake` (OR delete the file and have Makefile call bake directly — pick whichever keeps Makefile cleanest). _Requirements: 5.1, 5.2_
- [ ] **D.5** Rewrite `/Users/ben/Projects/wavekit/docker/push.sh` to push only to GHCR (drop the docker.io path on lines 16–18). Use `WAVEKIT_GH_OWNER` env var with `coriou` fallback per sdr-host pattern. Drop `linux/arm/v7` from the default `PLATFORMS`. _Requirements: 5.4, 5.5_
- [ ] **D.6** Edit `/Users/ben/Projects/wavekit/docker/init.sh`:
- Remove the `.docker-cache` mkdir + chmod (lines 47–51).
- Keep the buildx-builder setup.
- Keep the network/volume creation.
- [x] **D.4** Deleted `/Users/ben/Projects/wavekit/docker/build.sh`. Phase E's Makefile invokes `docker buildx bake` directly; the wrapper provided no additional value. _Requirements: 5.1, 5.2_
- [x] **D.5** Rewrote `/Users/ben/Projects/wavekit/docker/push.sh` as a thin bake invocation. GHCR-only (docker.io path dropped); uses `WAVEKIT_GH_OWNER` env var with `coriou` fallback; `linux/arm/v7` dropped from defaults. _Requirements: 5.4, 5.5_
- [x] **D.6** Edited `/Users/ben/Projects/wavekit/docker/init.sh`:
- Removed the `.docker-cache` mkdir + chmod.
- Kept the buildx-builder setup.
- Kept the network/volume creation.
- Updated "Next steps" footer to reference new Phase E targets (`make dev-stack` / `make dev-stack-logs`).
- _Requirements: 4.5_
- [ ] **D.7** Delete `build_multiarch` from `/Users/ben/Projects/wavekit/docker/platform-utils.sh` (replaced by bake). If `detect_platform` is still used anywhere, keep it; if not, delete the whole file. _Requirements: 5.6_
- [ ] **D.8** Initial cache seed: from a clean local machine, log in to GHCR, run `docker buildx bake --file docker/bake.hcl default --push --set "*.cache-to=type=registry,ref=ghcr.io/coriou/wavekit:cache-<stage>,mode=max"`. (One-time bootstrap; subsequent updates come from CI.) _Requirements: 4.1_
- [x] **D.7** Deleted `/Users/ben/Projects/wavekit/docker/platform-utils.sh` entirely. `build_multiarch` is replaced by bake; `detect_platform` had no consumers (verified by grep across Makefile, docker/, .github/, packages/sdr-host/). _Requirements: 5.6_
- [ ] **D.8** (DEFERRED — user-run): Initial cache seed: from a clean local machine, log in to GHCR, run `docker buildx bake --file docker/bake.hcl default --push --set "*.cache-to=type=registry,ref=ghcr.io/coriou/wavekit:cache-<stage>,mode=max"`. (One-time bootstrap; subsequent updates come from CI.) _Requirements: 4.1_ (Phase F's CI workflow on main-branch push will populate GHCR cache via cache-to mode=max on its first run; D.8 is redundant if CI lands first.)

## Phase E: Makefile Cleanup

- [ ] **E.1** Rewrite `/Users/ben/Projects/wavekit/Makefile` with the new target inventory per design §7.1. _Requirements: 6.1_
- [ ] **E.2** Confirm no deleted targets remain in the file. Run `make help` and verify only the targets listed in 6.1 (plus sdr-host-* and fixtures-*) appear. _Requirements: 6.2_
- [ ] **E.3** Verify all newly-introduced echo output is emoji-free and uses no decorative ANSI colour. Existing colour in retained targets MAY remain unchanged. _Requirements: 6.3_
- [ ] **E.4** Test the new dev flow end-to-end:
- [x] **E.1** Rewrite `/Users/ben/Projects/wavekit/Makefile` with the new target inventory per design §7.1. _Requirements: 6.1_
- [x] **E.2** Confirm no deleted targets remain in the file. Run `make help` and verify only the targets listed in 6.1 (plus sdr-host-* and fixtures-*) appear. _Requirements: 6.2_
- [x] **E.3** Verify all newly-introduced echo output is emoji-free and uses no decorative ANSI colour. Existing colour in retained targets MAY remain unchanged. _Requirements: 6.3_
- [x] **E.4** Test the new dev flow end-to-end:
- `make dev` SHALL start `pnpm dev` with esbuild watch + node watch.
- `make dev-stack` SHALL build via buildx bake and start the dev profile.
- `make dev-dashboard` SHALL connect the CLI dashboard.
- `make docker-build` SHALL invoke bake.
- `make demod-test` SHALL launch the demod-test profile interactively.
- _Requirements: 1.1, 2.1, 2.4, 5.2, 6.1_
- **Result**: Verified via `make --dry-run` for each headline target. `make dev` → `pnpm dev`; `make dev-stack` → `docker compose --profile dev up --build`; `make docker-build` → `docker buildx bake --file docker/bake.hcl default`; `make demod-test` → `docker compose --profile demod-test run --rm demod-test`. `cli-install` folded into `dev-dashboard-build` as planned. New Makefile is 156 lines / 34 targets (down from 386 / 63).

## Phase F: CI Workflow

- [ ] **F.1** Rewrite `/Users/ben/Projects/wavekit/.github/workflows/ci.yml` per design §8. _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5_
- [ ] **F.2** Update Node to `22` and pnpm install to use Corepack (matches the Dockerfile pattern). _Requirements: 7.5_
- [ ] **F.3** Add the `lint-typecheck-test` job that runs lint, typecheck, build, AND test (test was missing from the old workflow). _Requirements: 7.1_
- [ ] **F.4** Add the `docker-build` job that depends on `lint-typecheck-test`, sets up QEMU + buildx, and runs bake. _Requirements: 7.2_
- [ ] **F.5** PR path: `--cache-from` only, no login, no push. _Requirements: 7.3_
- [ ] **F.6** Main-branch path: log in to GHCR, build `default` group with `--push` and `--cache-to mode=max`. _Requirements: 7.4_
- [ ] **F.7** Smoke-test by opening a draft PR with a no-op change and verifying both jobs run and succeed. _Requirements: 7.1, 7.2, 7.3_
- [x] **F.1** Rewrite `/Users/ben/Projects/wavekit/.github/workflows/ci.yml` per design §8. _Requirements: 7.1, 7.2, 7.3, 7.4, 7.5_
- [x] **F.2** Update Node to `22` and pnpm install to use Corepack (matches the Dockerfile pattern). _Requirements: 7.5_
- [x] **F.3** Add the `lint-typecheck-test` job that runs lint, typecheck, build, AND test (test was missing from the old workflow). _Requirements: 7.1_
- [x] **F.4** Add the `docker-build` job that depends on `lint-typecheck-test`, sets up QEMU + buildx, and runs bake. _Requirements: 7.2_
- [x] **F.5** PR path: `--cache-from` only, no login, no push. _Requirements: 7.3_
- [x] **F.6** Main-branch path: log in to GHCR, build `default` group with `--push` and `--cache-to mode=max`. _Requirements: 7.4_
- [ ] **F.7** (DEFERRED — user-run): Smoke-test by opening a draft PR with a no-op change and verifying both jobs run and succeed. _Requirements: 7.1, 7.2, 7.3_ (Pre-merge gate: maintainer opens a draft PR after PR 2 is up; cold-cache PR build expected to take 15-25 min with no-cache fallback per Req 4.3, future PRs ~2-5 min with cache hits.)

> **Checkpoint 2**: At this point the new build system is fully functional.
> Phases G and H are documentation + sdr-host alignment polish.
Expand Down
Loading
Loading