diff --git a/.dockerignore b/.dockerignore index 4bc5f6c79..08712f7bb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,4 @@ * !docker/entrypoint.sh !docker/settings.toml -!docker-context/** +!tmp/docker-context/** diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3d3758d53..07cd3e155 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -188,9 +188,9 @@ jobs: x86_64-*) arch=amd64 ;; aarch64-*) arch=arm64 ;; esac - mkdir -p "docker-context/$arch" + mkdir -p "tmp/docker-context/$arch" tar -xzf "target/distrib/fabro-${target}.tar.gz" -C target/distrib - cp "target/distrib/fabro-${target}/fabro" "docker-context/$arch/fabro" + cp "target/distrib/fabro-${target}/fabro" "tmp/docker-context/$arch/fabro" done - uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 diff --git a/.gitignore b/.gitignore index 12bf2b2ca..cb1ebbe2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ target -docker-context/ .env .entire node_modules diff --git a/AGENTS.md b/AGENTS.md index f46aaf2d7..12caab195 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,7 +25,7 @@ macOS note: if `cargo nextest run` fails with `Too many open files (os error 24) - `cargo dev refresh-spa` — **run this before committing any TypeScript change in `apps/fabro-web/` or `lib/packages/fabro-api-client/`**. It runs the production build and then copies `dist/` into `lib/crates/fabro-spa/assets/` (which is tracked in git). CI's TypeScript `Build` job reruns this command and then `git diff --exit-code -- lib/crates/fabro-spa/assets` — if the committed bundle drifts from source (e.g. content-hashed filenames like `entry-.js` change), the check fails. `bun run build` on its own is not enough. ### Docker image -- `cargo dev docker-build` — builds the local Docker image from the current tree using the release pipeline's cargo-zigbuild approach. Honors `--arch amd64|arm64`, `--tag ` (default `fabro`), `--compile-only` (stages `docker-context//fabro` without `docker build`), and `--dry-run` (prints the Docker commands without running them). Prefer this over writing a throwaway Dockerfile; the release pipeline, `Dockerfile`, and this command share the same binary layout. +- `cargo dev docker-build` — builds the local Docker image from the current tree using the release pipeline's cargo-zigbuild approach. Honors `--arch amd64|arm64`, `--tag ` (default `fabro`), `--compile-only` (stages `tmp/docker-context//fabro` without `docker build`), and `--dry-run` (prints the Docker commands without running them). Prefer this over writing a throwaway Dockerfile; the release pipeline, `Dockerfile`, and this command share the same binary layout. - Refresh the embedded SPA before rebuilding the image after any `apps/fabro-web` change: `cargo dev refresh-spa` runs the bun build and copies `dist/` into `lib/crates/fabro-spa/assets/`. Skipping this step produces a Docker image whose Rust binary embeds a stale SPA bundle. ### Release automation @@ -102,7 +102,7 @@ When working on Rust crates, read the relevant strategy doc **before** making ch - **`docs-internal/logging-strategy.md`** — read when adding `tracing` calls (`info!`, `debug!`, `warn!`, `error!`), working on error handling paths, or adding new operations that should be observable - **`docs-internal/events-strategy.md`** — read when adding or modifying `Event` variants, touching `Emitter`/`emit()`, changing `progress.jsonl` output, or adding new workflow stage types -- **`files-internal/testing-strategy.md`** — read when adding or reorganizing tests, choosing between unit vs `tests/it`, deciding whether a test belongs in `cmd` vs `workflow` vs `scenario`, or deciding how to structure snapshots and fixtures +- **`docs-internal/testing-strategy.md`** — read when adding or reorganizing tests, choosing between unit vs `tests/it`, deciding whether a test belongs in `cmd` vs `workflow` vs `scenario`, or deciding how to structure snapshots and fixtures - **`docs-internal/server-secrets-strategy.md`** — read when adding or changing server-level secrets, startup validation, install-time secret persistence, or subprocess env inheritance/scrubbing ## Shell quoting in sandbox code diff --git a/Dockerfile b/Dockerfile index 29ff48dbc..0ced73368 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,8 +3,8 @@ # Runtime image for the Fabro server. # # Binaries are supplied pre-built via the release workflow: -# docker-context/amd64/fabro (x86_64-unknown-linux-musl) -# docker-context/arm64/fabro (aarch64-unknown-linux-musl) +# tmp/docker-context/amd64/fabro (x86_64-unknown-linux-musl) +# tmp/docker-context/arm64/fabro (aarch64-unknown-linux-musl) # # The image serves the HTTP API (with embedded web UI) on $PORT (default # 32276), persists state to /storage, and runs as the unprivileged `fabro` @@ -26,7 +26,7 @@ RUN apk add --no-cache \ && adduser -S -u 1000 -G fabro -h /var/fabro -s /sbin/nologin fabro \ && install -d -o fabro -g fabro -m 0755 /var/fabro /storage -COPY --chmod=0755 docker-context/${TARGETARCH}/fabro /usr/local/bin/fabro +COPY --chmod=0755 tmp/docker-context/${TARGETARCH}/fabro /usr/local/bin/fabro COPY --chmod=0755 docker/entrypoint.sh /usr/local/bin/fabro-entrypoint diff --git a/lib/crates/fabro-dev/src/commands/docker_build.rs b/lib/crates/fabro-dev/src/commands/docker_build.rs index 60a2a1b91..c56217711 100644 --- a/lib/crates/fabro-dev/src/commands/docker_build.rs +++ b/lib/crates/fabro-dev/src/commands/docker_build.rs @@ -117,7 +117,7 @@ impl DockerBuildPlan { if self.compile_only { println!( - "Staged docker-context/{}/fabro (skipping docker build per --compile-only).", + "Staged tmp/docker-context/{}/fabro (skipping docker build per --compile-only).", self.arch ); return Ok(()); @@ -135,7 +135,7 @@ impl DockerBuildPlan { self.extract_command().to_shell_line(), ]; if self.compile_only { - lines.push(format!("staged docker-context/{}/fabro", self.arch)); + lines.push(format!("staged tmp/docker-context/{}/fabro", self.arch)); } else { lines.push(self.image_build_command().to_shell_line()); } @@ -202,12 +202,13 @@ impl DockerBuildPlan { fn context_dir(&self) -> PathBuf { self.workspace_root + .join("tmp") .join("docker-context") .join(self.arch.to_string()) } fn relative_context_dir(&self) -> String { - format!("docker-context/{}", self.arch) + format!("tmp/docker-context/{}", self.arch) } } diff --git a/lib/crates/fabro-dev/tests/it/docker_build.rs b/lib/crates/fabro-dev/tests/it/docker_build.rs index 461de29c9..2ea9d67db 100644 --- a/lib/crates/fabro-dev/tests/it/docker_build.rs +++ b/lib/crates/fabro-dev/tests/it/docker_build.rs @@ -83,7 +83,7 @@ fn dry_run_compile_only_skips_image_build() { let stdout = output_text(&output.stdout); assert!( - stdout.contains("docker-context/arm64/fabro"), + stdout.contains("tmp/docker-context/arm64/fabro"), "dry-run compile-only should print staged binary path:\n{stdout}" ); assert!(