diff --git a/.github/workflows/main-branch-flow.md b/.github/workflows/main-branch-flow.md index b0e6551..3a26ed1 100644 --- a/.github/workflows/main-branch-flow.md +++ b/.github/workflows/main-branch-flow.md @@ -30,15 +30,15 @@ Observed averages below are from recent completed runs (sampled from GitHub Acti | `sec-audit.yml` | PR + push to `main` | 127.2s | No | No | No | | `workflow-sanity.yml` | Workflow-file changes | 34.2s | No | No | No | | `pr-label-policy-check.yml` | Label policy/automation changes | 14.7s | No | No | No | -| `pub-docker-img.yml` (`pull_request`) | Docker-related PR changes | 240.4s | Yes | Yes | No | -| `pub-docker-img.yml` (`push` tag) | Tag push `v*` | 139.9s | Yes | No | Yes | +| `pub-docker-img.yml` (`pull_request`) | Docker build-input PR changes | 240.4s | Yes | Yes | No | +| `pub-docker-img.yml` (`push`/`workflow_dispatch`) | `main` push (build-input paths), tag push `v*`, or manual dispatch | 139.9s | Yes | No | Yes | | `pub-release.yml` | Tag push `v*` | N/A in recent sample | No | No | No | Notes: 1. `pub-docker-img.yml` is the only workflow in the main PR/push path that builds Docker images. 2. Container runtime verification (`docker run`) occurs in PR smoke only. -3. Container registry push occurs on tag pushes only. +3. Container registry push occurs on `main` build-input pushes, tag pushes, and manual dispatch. 4. `ci-run.yml` "Build (Smoke)" builds Rust binaries, not Docker images. ## Step-By-Step @@ -54,7 +54,7 @@ Notes: - `ci-run.yml` - `sec-audit.yml` - path-scoped workflows if matching files changed: - - `pub-docker-img.yml` (Docker-related paths only) + - `pub-docker-img.yml` (Docker build-input paths only) - `workflow-sanity.yml` (workflow files only) - `pr-label-policy-check.yml` (label-policy files only) 4. In `ci-run.yml`, `changes` computes: @@ -127,7 +127,7 @@ Workflow: `.github/workflows/pub-docker-img.yml` ### PR behavior -1. Triggered on `pull_request` to `main` when Docker-related paths change. +1. Triggered on `pull_request` to `main` when Docker build-input paths change. 2. Runs `PR Docker Smoke` job: - Builds local smoke image with Blacksmith builder. - Verifies container with `docker run ... --version`. @@ -136,17 +136,18 @@ Workflow: `.github/workflows/pub-docker-img.yml` ### Push behavior -1. `publish` job runs only when `github.event_name == 'push'` and ref starts with `refs/tags/`. -2. Tag format expected by workflow trigger is `v*`. +1. `publish` job runs on `push` and `workflow_dispatch`. +2. Workflow trigger includes `main` pushes with Docker build-input changes and tag pushes `v*`. 3. Login to `ghcr.io` uses `${{ github.actor }}` and `${{ secrets.GITHUB_TOKEN }}`. 4. Tag computation includes: - - semantic tag from pushed git tag (`vX.Y.Z`) - - SHA tag (`sha-<12 chars>`) -5. Multi-platform publish is used for tag pushes (`linux/amd64,linux/arm64`). + - `latest` + SHA tag (`sha-<12 chars>`) for `main` + - semantic tag from pushed git tag (`vX.Y.Z`) + SHA tag for tag pushes + - branch name + SHA tag for non-`main` manual dispatch refs +5. Multi-platform publish is used for tag pushes (`linux/amd64,linux/arm64`), while `main` publish stays `linux/amd64`. 6. Typical runtime in recent sample: ~139.9s. 7. Result: pushed image tags under `ghcr.io//`. -Important: Docker publish does not run on plain `main` pushes anymore. +Important: Docker publish now runs on qualifying `main` pushes; no release tag is required to refresh `latest`. ## Release Logic @@ -208,4 +209,4 @@ flowchart TD 1. Unexpected skipped jobs: inspect `scripts/ci/detect_change_scope.sh` outputs. 2. Workflow-change PR blocked: verify `WORKFLOW_OWNER_LOGINS` and approvals. 3. Fork PR appears stalled: check whether Actions run approval is pending. -4. Docker not published: confirm a `v*` tag push happened (plain `main` push will not publish). +4. Docker not published: confirm changed files match Docker build-input paths, or run workflow dispatch manually. diff --git a/.github/workflows/pub-docker-img.yml b/.github/workflows/pub-docker-img.yml index 8e93df0..9a6bc22 100644 --- a/.github/workflows/pub-docker-img.yml +++ b/.github/workflows/pub-docker-img.yml @@ -2,14 +2,33 @@ name: Pub Docker Img on: push: + branches: [main] tags: ["v*"] + paths: + - "Dockerfile" + - ".dockerignore" + - "Cargo.toml" + - "Cargo.lock" + - "rust-toolchain.toml" + - "src/**" + - "crates/**" + - "benches/**" + - "firmware/**" + - "dev/config.template.toml" + - ".github/workflows/pub-docker-img.yml" pull_request: branches: [main] paths: - "Dockerfile" - - "docker-compose.yml" - - "dev/docker-compose.yml" - - "dev/sandbox/**" + - ".dockerignore" + - "Cargo.toml" + - "Cargo.lock" + - "rust-toolchain.toml" + - "src/**" + - "crates/**" + - "benches/**" + - "firmware/**" + - "dev/config.template.toml" - ".github/workflows/pub-docker-img.yml" workflow_dispatch: @@ -61,7 +80,7 @@ jobs: publish: name: Build and Push Docker Image - if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' runs-on: blacksmith-2vcpu-ubuntu-2404 timeout-minutes: 25 permissions: diff --git a/Dockerfile b/Dockerfile index 10a52a8..95d5c3a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,19 +14,22 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ # 1. Copy manifests and toolchain pin to cache dependencies with the same compiler COPY Cargo.toml Cargo.lock rust-toolchain.toml ./ +COPY crates/robot-kit/Cargo.toml crates/robot-kit/Cargo.toml # Create dummy targets declared in Cargo.toml so manifest parsing succeeds. -RUN mkdir -p src benches \ +RUN mkdir -p src benches crates/robot-kit/src \ && echo "fn main() {}" > src/main.rs \ - && echo "fn main() {}" > benches/agent_benchmarks.rs + && echo "fn main() {}" > benches/agent_benchmarks.rs \ + && echo "pub fn placeholder() {}" > crates/robot-kit/src/lib.rs RUN --mount=type=cache,id=zeroclaw-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=zeroclaw-cargo-git,target=/usr/local/cargo/git,sharing=locked \ --mount=type=cache,id=zeroclaw-target,target=/app/target,sharing=locked \ cargo build --release --locked -RUN rm -rf src benches +RUN rm -rf src benches crates/robot-kit/src # 2. Copy only build-relevant source paths (avoid cache-busting on docs/tests/scripts) COPY src/ src/ COPY benches/ benches/ +COPY crates/ crates/ COPY firmware/ firmware/ RUN --mount=type=cache,id=zeroclaw-cargo-registry,target=/usr/local/cargo/registry,sharing=locked \ --mount=type=cache,id=zeroclaw-cargo-git,target=/usr/local/cargo/git,sharing=locked \ diff --git a/docs/ci-map.md b/docs/ci-map.md index 0c2ccb9..eb7b604 100644 --- a/docs/ci-map.md +++ b/docs/ci-map.md @@ -24,7 +24,7 @@ Merge-blocking checks should stay small and deterministic. Optional checks are u ### Non-Blocking but Important - `.github/workflows/pub-docker-img.yml` (`Docker`) - - Purpose: PR Docker smoke check and publish images on tag pushes (`v*`) + - Purpose: PR Docker smoke check and publish images on `main` pushes (build-input paths), tag pushes (`v*`), and manual dispatch - `.github/workflows/sec-audit.yml` (`Security Audit`) - Purpose: dependency advisories (`rustsec/audit-check`, pinned SHA) and policy/license checks (`cargo deny`) - `.github/workflows/sec-codeql.yml` (`CodeQL Analysis`) @@ -66,7 +66,7 @@ Merge-blocking checks should stay small and deterministic. Optional checks are u ## Trigger Map - `CI`: push to `main`, PRs to `main` -- `Docker`: tag push (`v*`), PRs touching docker/workflow files, manual dispatch +- `Docker`: push to `main` when Docker build inputs change, tag push (`v*`), matching PRs, manual dispatch - `Release`: tag push (`v*`) - `Security Audit`: push to `main`, PRs to `main`, weekly schedule - `Workflow Sanity`: PR/push when `.github/workflows/**`, `.github/*.yml`, or `.github/*.yaml` change