diff --git a/.gitea/workflows/server-deploy.yml b/.gitea/workflows/server-deploy.yml index 17a41b8..09f4959 100644 --- a/.gitea/workflows/server-deploy.yml +++ b/.gitea/workflows/server-deploy.yml @@ -71,15 +71,16 @@ jobs: fi } - # The three Go images build from the repo root and COPY + # The four Go images build from the repo root and COPY # shared/ plus their own directory, so shared/ rebuilds all - # three. proto/ is in server's list as insurance: the + # four. proto/ is in server's list as insurance: the # generated pb is committed under server/, but a proto change # that someone regenerates in the same push should not depend # on that ordering. flag server '^(server/|shared/|proto/|default_steps/|go\.work)' flag sitesvc '^(sitesvc/|shared/|go\.work)' flag admin '^(admin/|shared/|go\.work)' + flag vantagectl '^(vantagectl/|shared/|go\.work)' # The three Next images and the docs site use their own # directory as the build context, so nothing outside it can @@ -159,6 +160,14 @@ jobs: docker build -t "$IMAGE" -f admin/Dockerfile . docker push "$IMAGE" + - name: Build and push vantagectl image + if: steps.changed.outputs.vantagectl == 'true' + run: | + IMAGE="${{ vars.DOCKER_HOST }}/${{ github.repository_owner }}/vantage/vantagectl:latest" + # Root context: vantagectl depends on the shared module. + docker build -t "$IMAGE" -f vantagectl/Dockerfile . + docker push "$IMAGE" + - name: Build and push adminsite image if: steps.changed.outputs.adminsite == 'true' run: | diff --git a/.gitea/workflows/vantagectl-release.yml b/.gitea/workflows/vantagectl-release.yml new file mode 100644 index 0000000..6b8ea57 --- /dev/null +++ b/.gitea/workflows/vantagectl-release.yml @@ -0,0 +1,60 @@ +name: vantagectl Release + +on: + push: + tags: + - "vantagectl/v*" + +jobs: + build: + runs-on: ubuntu-docker + container: node:26 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.26" + cache: true + cache-dependency-path: vantagectl/go.sum + + - name: Extract version + id: version + run: echo "VERSION=${GITHUB_REF_NAME#vantagectl/}" >> $GITHUB_OUTPUT + + - name: Test + working-directory: vantagectl + run: go test ./... + + - name: Build + working-directory: vantagectl + env: + VERSION: ${{ steps.version.outputs.VERSION }} + run: | + mkdir -p dist + for target in linux/amd64 linux/arm64 darwin/arm64 windows/amd64; do + goos="${target%/*}" + goarch="${target#*/}" + out="dist/vantagectl-${goos}-${goarch}" + if [ "$goos" = "windows" ]; then out="${out}.exe"; fi + CGO_ENABLED=0 GOOS="$goos" GOARCH="$goarch" go build \ + -ldflags="-s -w -X main.Version=${VERSION}" \ + -o "$out" . + done + + - name: Checksums + working-directory: vantagectl/dist + run: sha256sum vantagectl-* > checksums.txt + + - name: Create release + uses: https://gitea.com/actions/gitea-release-action@v1 + with: + token: ${{ secrets.RELEASE_TOKEN }} + files: | + vantagectl/dist/vantagectl-linux-amd64 + vantagectl/dist/vantagectl-linux-arm64 + vantagectl/dist/vantagectl-darwin-arm64 + vantagectl/dist/vantagectl-windows-amd64.exe + vantagectl/dist/checksums.txt diff --git a/vantagectl/Dockerfile b/vantagectl/Dockerfile new file mode 100644 index 0000000..437c1ad --- /dev/null +++ b/vantagectl/Dockerfile @@ -0,0 +1,36 @@ +# Build stage +# +# Context is the repository root, not vantagectl/, because vantagectl depends on +# the shared module through a replace directive. +FROM golang:1.26 AS builder + +WORKDIR /src + +# Manifests first so the dependency layer caches independently of source edits. +COPY shared/go.mod shared/go.sum ./shared/ +COPY vantagectl/go.mod vantagectl/go.sum ./vantagectl/ +RUN cd vantagectl && go mod download + +COPY shared/ ./shared/ +COPY vantagectl/ ./vantagectl/ + +ARG VERSION=dev +RUN cd vantagectl && CGO_ENABLED=0 GOOS=linux go build \ + -ldflags="-s -w -X main.Version=${VERSION}" -o /vantagectl . + +# Staged so the scratch image below can have a /tmp. It cannot mkdir one +# itself — scratch has no shell. +RUN mkdir -p /staging/tmp && chmod 1777 /staging/tmp + +# Runtime stage +FROM scratch + +COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +# restore extracts an archive here before verifying its checksums, and backup +# stages nothing but still inherits os.MkdirTemp's requirements. Without this +# every restore stops at "temp dir: stat /tmp: no such file or directory". +COPY --from=builder /staging/tmp /tmp +COPY --from=builder /vantagectl /vantagectl + +ENTRYPOINT ["/vantagectl"]