diff --git a/.gitea/workflows/build-image.yml b/.gitea/workflows/build-image.yml deleted file mode 100644 index 6bfaeb7..0000000 --- a/.gitea/workflows/build-image.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Publish the immutable crucible: image on version tags. -# PR/main test builds live in test-image.yml and never publish, so registry -# packages are only generated for releases we intend to use (not on every merge). -# -# Daemonless: the host-mode runner has no container runtime, so the image is -# built by Nix (`nix build .#image`, see flake.nix) and pushed with skopeo -# straight from the OCI tarball. No `docker build`/`docker login` involved. -name: build-image - -on: - push: - tags: ['v*'] - -env: - REGISTRY: registry.westgate.pw - IMAGE: deployment/crucible - -jobs: - publish: - runs-on: nix-docker - steps: - - uses: actions/checkout@v4 - with: { fetch-depth: 0 } - - - name: Resolve tag - id: tag - run: echo "sha=$(git rev-parse --short=12 HEAD)" >> "$GITHUB_OUTPUT" - - - name: Build OCI image (daemonless) - run: nix build .#image - - # This workflow only runs on v* tags, so every run is a release publish. - - name: Publish image - env: - REGISTRY_USER: ${{ secrets.REGISTRY_USER }} - REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} - run: | - nix shell nixpkgs#skopeo -c skopeo copy \ - --dest-creds "${REGISTRY_USER}:${REGISTRY_PASSWORD}" \ - docker-archive:result \ - "docker://${REGISTRY}/${IMAGE}:${{ steps.tag.outputs.sha }}" - - - name: Emit release fragment - run: | - FRAG_REPO=sow-tools \ - FRAG_SHA=${{ steps.tag.outputs.sha }} \ - FRAG_ARTIFACT="${REGISTRY}/${IMAGE}:${{ steps.tag.outputs.sha }}" \ - FRAG_URL="${REGISTRY}/${IMAGE}" \ - FRAG_RUN_ID=${{ gitea.run_id }} \ - bash scripts/emit-release-fragment.sh - - uses: actions/upload-artifact@v3 - with: { name: release-fragment, path: release-fragment.json } diff --git a/.gitea/workflows/publish-image.yml b/.gitea/workflows/publish-image.yml deleted file mode 100644 index a0c6838..0000000 --- a/.gitea/workflows/publish-image.yml +++ /dev/null @@ -1,49 +0,0 @@ -# Manual compatibility publisher for the Crucible image. -# Normal release publishing happens in build-image.yml on v* tags; this is the -# break-glass / re-publish path, triggered by hand. -# -# Daemonless: built by Nix (`nix build .#image`) and pushed with skopeo from the -# OCI tarball. No `docker build`/`docker login` involved. -name: publish-image - -on: - workflow_dispatch: - -env: - REGISTRY: registry.westgate.pw - IMAGE: deployment/crucible - -jobs: - publish: - runs-on: nix-docker - steps: - - uses: actions/checkout@v4 - with: { fetch-depth: 0 } - - - name: Resolve tag - id: tag - run: echo "sha=$(git rev-parse --short=12 HEAD)" >> "$GITHUB_OUTPUT" - - - name: Build OCI image (daemonless) - run: nix build .#image - - - name: Publish image - env: - REGISTRY_USER: ${{ secrets.REGISTRY_USER }} - REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }} - run: | - nix shell nixpkgs#skopeo -c skopeo copy \ - --dest-creds "${REGISTRY_USER}:${REGISTRY_PASSWORD}" \ - docker-archive:result \ - "docker://${REGISTRY}/${IMAGE}:${{ steps.tag.outputs.sha }}" - - - name: Emit release fragment - run: | - FRAG_REPO=sow-tools \ - FRAG_SHA=${{ steps.tag.outputs.sha }} \ - FRAG_ARTIFACT="${REGISTRY}/${IMAGE}:${{ steps.tag.outputs.sha }}" \ - FRAG_URL="${REGISTRY}/${IMAGE}" \ - FRAG_RUN_ID=${{ gitea.run_id }} \ - bash scripts/emit-release-fragment.sh - - uses: actions/upload-artifact@v3 - with: { name: release-fragment, path: release-fragment.json } diff --git a/.gitea/workflows/test-image.yml b/.gitea/workflows/test-image.yml deleted file mode 100644 index 3b87d00..0000000 --- a/.gitea/workflows/test-image.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Test-build the Crucible image on PRs. Proves `nix build .#image` still works -# (daemonless, Nix-built OCI tarball) but does NOT publish — release publishing -# happens in build-image.yml on v* tags. PR-only: with up-to-date-before-merge -# protection, main == the tested PR head, so a throwaway post-merge rebuild that -# publishes nothing is pure waste. -name: test-image - -on: - pull_request: - -jobs: - build-image: - runs-on: nix-docker - steps: - - uses: actions/checkout@v4 - with: { fetch-depth: 0 } - - - name: Build OCI image (daemonless, no publish) - run: nix build .#image diff --git a/AGENTS.md b/AGENTS.md index 8a7f386..4446b7a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,13 +41,14 @@ section and `.gitea/workflows/`. - Dev loop: `nix develop`, then `make check` / `make build` / `make smoke` (see Commands below). - Release: push a `v*` tag. CI uploads cross-built binaries + wrappers to the - Gitea release and publishes the `crucible` container image. + Gitea release. There is no container image; Crucible ships as binaries, + wrappers, and the Nix input. - Consumers (they download released binaries via the wrapper; they never vendor a toolkit): - sow-module — https://git.westgate.pw/ShadowsOverWestgate/sow-module - sow-topdata — https://git.westgate.pw/ShadowsOverWestgate/sow-topdata - sow-assets-manifest — https://git.westgate.pw/ShadowsOverWestgate/sow-assets-manifest - - sow-platform (deploys the released image/pins) — + - sow-platform (infra/deploy authority) — https://git.westgate.pw/ShadowsOverWestgate/sow-platform ## What this repo owns / does not own @@ -62,7 +63,7 @@ is `sow-platform`). 1. **Fail closed, never fake.** A builder with no migrated logic yet (`depot`) exits `70`. Do not stub a builder to emit a placeholder artifact. -2. **Binaries are not committed.** They are CI artifacts / image layers. +2. **Binaries are not committed.** They are CI artifacts. `/bin/`, `*.exe`, `nwn-tool`, `sow-toolkit` are gitignored. 3. **The registry is the command surface.** `internal/dispatch.Registry` is the single source of truth; keep it in sync with `cmd/` and @@ -81,7 +82,6 @@ is `sow-platform`). nix develop && make check # vet + test + shellcheck + yamllint make build # cmd/* -> ./bin make smoke # assert fail-closed contract -make image # crucible: ``` ## Tests diff --git a/Makefile b/Makefile index 1beaec4..2b60c1f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ SHELL := bash .ONESHELL: -.PHONY: check test vet build smoke fmt image +.PHONY: check test vet build smoke fmt # Lint + unit tests. Mirrors the `test` CI job; runs green inside `nix develop`. check: vet test @@ -22,9 +22,3 @@ smoke: build fmt: gofmt -l -w cmd internal - -# Build the Crucible image locally. Requires docker; mirrors build-image CI. -IMAGE ?= crucible -GIT_SHA ?= $(shell git rev-parse --short=12 HEAD 2>/dev/null || echo unknown) -image: - docker build --build-arg GIT_SHA=$(GIT_SHA) -f docker/Dockerfile -t $(IMAGE):$(GIT_SHA) . diff --git a/README.md b/README.md index fb71610..39335ae 100644 --- a/README.md +++ b/README.md @@ -71,10 +71,9 @@ nix develop # Go + shellcheck + yamllint + make make check # go vet + go test + shellcheck + yamllint make build # build every cmd/* into ./bin (gitignored) make smoke # build + assert the fail-closed contract -make image # docker build -> crucible: ``` -Binaries are **never committed** — they are CI artifacts / image layers (D19). +Binaries are **never committed** — they are CI artifacts (D19). This retires the old habit of checking in `nwn-tool` / `sow-toolkit`. ## CI @@ -84,12 +83,8 @@ publish event is a `v*` tag (see `runbooks/ci-trigger-standard.md` in sow-docs, https://git.westgate.pw/ShadowsOverWestgate/sow-docs). - `test.yml` — vet, test, shellcheck, yamllint, binary smoke (PR + main). -- `test-image.yml` — build the OCI image to prove it compiles (PR + main, no push). - `build-binaries.yml` — cross-build all targets (PR + main); on a `v*` tag, upload the binaries, `SHA256SUMS`, and the wrappers to the Gitea release. -- `build-image.yml` — on a `v*` tag, build and publish - `registry.westgate.pw/deployment/crucible:`. -- `publish-image.yml` — manual `workflow_dispatch` break-glass republish. - `sync-wrappers.yml` — on a `main` push that touches `wrappers/`, auto-PR the canonical wrappers to the consumer repos in `wrappers/consumers.txt`. Consumer drift checks run after those PRs merge to `main`, not on the PRs diff --git a/docker/Dockerfile b/docker/Dockerfile deleted file mode 100644 index bcb7125..0000000 --- a/docker/Dockerfile +++ /dev/null @@ -1,38 +0,0 @@ -# syntax=docker/dockerfile:1 -# -# Crucible toolchain image: registry.westgate.pw/deployment/crucible: -# -# Reproducible multi-stage build, no on-VPS build. Produces every cmd/* binary -# and ships them on a static base. The `crucible` dispatcher is the entrypoint; -# consumer CI can also call the standalone crucible- binaries by path. -# -FROM golang:1.26-alpine AS build -WORKDIR /src -RUN apk add --no-cache git -# go.sum is committed now that the migrated packages pull golang.org/x/text and -# gopkg.in/yaml.v3; the glob keeps the build working if it is ever absent. -COPY go.mod go.sum* ./ -RUN go mod download -COPY . . -ARG GIT_SHA=unknown -ENV CGO_ENABLED=0 -RUN set -eux; \ - mkdir -p /out; \ - for dir in ./cmd/*/; do \ - name="$(basename "${dir}")"; \ - go build -trimpath \ - -ldflags "-s -w -X git.westgate.pw/ShadowsOverWestgate/sow-tools/internal/buildinfo.Version=${GIT_SHA}" \ - -o "/out/${name}" "${dir}"; \ - done - -FROM debian:12-slim -# ca-certificates: builders fetch published manifests over HTTPS. -RUN set -eux; \ - apt-get update; \ - apt-get install -y --no-install-recommends ca-certificates; \ - rm -rf /var/lib/apt/lists/*; \ - useradd --system --create-home --uid 65532 nonroot -COPY --from=build /out/ /usr/local/bin/ -USER nonroot -ENTRYPOINT ["/usr/local/bin/crucible"] -CMD ["help"] diff --git a/docs/consumer-contract.md b/docs/consumer-contract.md index 491213d..030a914 100644 --- a/docs/consumer-contract.md +++ b/docs/consumer-contract.md @@ -49,10 +49,10 @@ by `flake.lock`. CI runs the _same_ `crucible ` as local dev, inside the nix devshell (binary-cache fast). No build container, no token, no CI-only pre-steps. -The `registry.westgate.pw/deployment/crucible:` image is **deployment-only**: -`prod.yml` pins it so tools travel with the runtime host (`nwn.enable`), a -disabled placeholder until the NWN stack lands. It is **not** a build tool and no -build/CI job consumes it. +The `registry.westgate.pw/deployment/crucible:` image is **retired** +(2026-07-17): nothing consumed it, `prod.yml` no longer reserves a slot for +it, and CI no longer builds or publishes it. Binaries, wrappers, and the Nix +input are the only supported ways to run Crucible. ## Determinism