# Tag-triggered release workflow. # Generates changelog, publishes Docker images to GHCR, and creates Forgejo release. # # Images published on v* tags: # ghcr.io/circuitforgellc/peregrine:latest — FastAPI API (includes cf-orch) # ghcr.io/circuitforgellc/peregrine: # ghcr.io/circuitforgellc/peregrine-web:latest — Vue SPA (base path /) # ghcr.io/circuitforgellc/peregrine-web: # # The cloud image (compose.cloud.yml) is never published — it is built and # deployed directly on Heimdall from Dockerfile.cfcore with sibling repos. # # Required secrets: # FORGEJO_RELEASE_TOKEN — Forgejo API token for creating releases # GH_GHCR_TOKEN — GitHub PAT with packages:write for GHCR push # FORGEJO_CF_ORCH_TOKEN — Forgejo token to install private circuitforge-orch # during the API image build (BSL client for paid tier) name: Release on: push: tags: ['v*'] jobs: release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # ── Changelog ──────────────────────────────────────────────────────────── - name: Generate changelog uses: orhun/git-cliff-action@v3 id: cliff with: config: .cliff.toml args: --latest --strip header env: OUTPUT: CHANGES.md # ── Docker setup ───────────────────────────────────────────────────────── - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GHCR uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GH_GHCR_TOKEN }} # ── API image ───────────────────────────────────────────────────────────── # cf-orch (BSL, private) is installed via BuildKit secret — token never # appears in any image layer. Community builds without the secret fall back # to local backends automatically. - name: Build and push API image uses: docker/build-push-action@v6 with: context: . dockerfile: Dockerfile push: true platforms: linux/amd64,linux/arm64 secrets: | forgejo_token=${{ secrets.FORGEJO_CF_ORCH_TOKEN }} tags: | ghcr.io/circuitforgellc/peregrine:${{ github.ref_name }} ghcr.io/circuitforgellc/peregrine:latest cache-from: type=gha,scope=api cache-to: type=gha,mode=max,scope=api # ── Web image ───────────────────────────────────────────────────────────── # Published with VITE_BASE_PATH=/ (self-hosted default). # Cloud and demo deployments build locally with VITE_BASE_PATH=/peregrine/. - name: Build and push web image uses: docker/build-push-action@v6 with: context: . dockerfile: docker/web/Dockerfile push: true platforms: linux/amd64,linux/arm64 build-args: | VITE_BASE_PATH=/ tags: | ghcr.io/circuitforgellc/peregrine-web:${{ github.ref_name }} ghcr.io/circuitforgellc/peregrine-web:latest cache-from: type=gha,scope=web cache-to: type=gha,mode=max,scope=web # ── Forgejo Release ─────────────────────────────────────────────────────── - name: Create Forgejo release env: FORGEJO_TOKEN: ${{ secrets.FORGEJO_RELEASE_TOKEN }} REPO: ${{ github.event.repository.name }} TAG: ${{ github.ref_name }} NOTES: ${{ steps.cliff.outputs.content }} run: | curl -sS -X POST \ "https://git.opensourcesolarpunk.com/api/v1/repos/Circuit-Forge/${REPO}/releases" \ -H "Authorization: token ${FORGEJO_TOKEN}" \ -H "Content-Type: application/json" \ -d "$(jq -n --arg tag "$TAG" --arg body "$NOTES" \ '{tag_name: $tag, name: $tag, body: $body}')"