name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
tag:
description: "Existing tag to (re)package, e.g. v0.2.1"
required: true
permissions:
contents: write
pull-requests: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
BAZEL_REMOTE_AUTH: ${{ secrets.BAZEL_REMOTE_AUTH }}
jobs:
build-and-test:
name: build-and-test
if: github.event_name != 'workflow_dispatch'
runs-on: [self-hosted, linux, x64]
steps:
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
clean: false
- run: moon run pond:format
- run: moon run pond:lint
- run: moon run pond:test
release-plz:
name: release-plz
needs: build-and-test
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
outputs:
releases_created: ${{ steps.release-plz.outputs.releases_created }}
steps:
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
- id: release-plz
uses: release-plz/action@v0.5
env:
GITHUB_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
publish-release:
name: publish-release
needs: release-plz
if: ${{ always() && !cancelled() && (needs.release-plz.outputs.releases_created == 'true' || github.event_name == 'workflow_dispatch') }}
runs-on: [self-hosted, linux, x64]
steps:
- uses: actions/checkout@v6.0.2
with:
fetch-depth: 0
clean: false
ref: ${{ inputs.tag }}
- uses: cachix/install-nix-action@v31
- name: Bootstrap cluster access + buildx builder
env:
KUBECONFIG_DATA: ${{ secrets.KUBECONFIG_CASCADE }}
run: |
# Keep the kubeconfig OUT of the repo checkout: goreleaser aborts on a
# dirty tree, and a kubeconfig in the workspace is an untracked file.
# ($RUNNER_TEMP is only available in steps, not at job-level env.)
# export (not just assign) so subprocesses in this step - e.g.
# `docker buildx create --driver kubernetes` - inherit it; GITHUB_ENV
# carries it to later steps (build-dist's kubectl).
export KUBECONFIG="$RUNNER_TEMP/.kube-cascade"
echo "KUBECONFIG=$KUBECONFIG" >> "$GITHUB_ENV"
# Remove any kubeconfig a prior run left in the workspace (clean:false
# preserves untracked files) so it can't dirty the tree.
rm -f "${{ github.workspace }}/.kube-cascade"
printf '%s' "$KUBECONFIG_DATA" | base64 -d > "$KUBECONFIG"
chmod 600 "$KUBECONFIG"
# buildx builder state is client-side; on a fresh runner re-register it.
# Drop any stale in-cluster deployment first so create is idempotent.
docker buildx rm pond-hetzner 2>/dev/null || true
# persistent-volume-claim.* makes buildx render a StatefulSet with a PVC
# backing /var/lib/buildkit, so the RUN --mount=type=cache dirs (target/,
# cargo registry, kache local store) survive the autoshutdown scale-to-0
# instead of cold-rebuilding every release. Default storage class
# (hcloud-volumes-encrypted), RWO; the PVC is retained across buildx
# rm/create. The autoshutdown cron scales the StatefulSet too (see x402
# buildkit-autoshutdown chart) - that MUST be deployed or the node never drains.
docker buildx create --name pond-hetzner --driver kubernetes \
--driver-opt namespace=pond-buildkit,replicas=1,nodeselector=workload=buildkit,timeout=10m \
--driver-opt requests.cpu=12,requests.memory=24Gi,limits.memory=48Gi \
--driver-opt persistent-volume-claim.requests.storage=100Gi \
--platform linux/amd64
- name: Build dist binaries
run: moon run pond:build-dist
env:
KACHE_S3_ACCESS_KEY: ${{ secrets.KACHE_S3_ACCESS_KEY }}
KACHE_S3_SECRET_KEY: ${{ secrets.KACHE_S3_SECRET_KEY }}
KACHE_S3_REGION: nbg1
KACHE_S3_ENDPOINT: https://ttq.nbg1.your-objectstorage.com
- uses: goreleaser/goreleaser-action@v7
with:
distribution: goreleaser-pro version: '~> v2'
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
GH_RELEASE_TOKEN: ${{ secrets.GH_RELEASE_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}