Skip to content

feat(api): implement SPA fallback handling and tests #6

feat(api): implement SPA fallback handling and tests

feat(api): implement SPA fallback handling and tests #6

# Publishes only a rolling `nightly` tag on GHCR (replaced on every push to `main`).
# Image is linux/amd64 only for faster CI; release-container.yml publishes multi-arch.
# Previous nightly digests become untagged; cleanup-container prunes them. For stable
# pins, use a semver image from a GitHub release. Unstable: use `nightly` for pre-release.
name: Nightly Container
on:
push:
branches:
- main
workflow_dispatch: # re-run the workflow against current main without a new commit
concurrency:
group: nightly-container-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
packages: write
id-token: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract image metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=nightly,enable=true
labels: |
org.opencontainers.image.title=SampleDB
org.opencontainers.image.source=https://github.com/${{ github.repository }}
org.opencontainers.image.licenses=MIT
org.opencontainers.image.version=nightly
org.opencontainers.image.description=Nightly build from the latest commit on the default branch
- name: Build and push (linux/amd64)
id: build
uses: docker/build-push-action@v6
with:
build-args: |
APP_BUILD_ID=${{ github.sha }}
context: .
file: ./Dockerfile
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# `scope=sampledb` lines up BuildKit cache for release / nightly / PR; nightly omits provenance+SBOM (faster) — release still attests
cache-from: type=gha,scope=sampledb
cache-to: type=gha,mode=max,scope=sampledb
provenance: false
sbom: false
- name: Install cosign
uses: sigstore/cosign-installer@v3
- name: Sign image with cosign (keyless / OIDC)
env:
DIGEST: ${{ steps.build.outputs.digest }}
TAGS: ${{ steps.meta.outputs.tags }}
run: |
while IFS= read -r tag; do
[ -z "$tag" ] && continue
cosign sign --yes "${tag}@${DIGEST}"
done <<< "${TAGS}"
- name: Summary
run: |
{
echo "### Nightly image published"
echo ""
echo "**Digest:** \`${{ steps.build.outputs.digest }}\`"
echo ""
echo "**Platform:** linux/amd64 (ARM: use a **semver** release image from release-container)"
echo ""
echo '**Tag:** `nightly` only (latest `main`); no per-commit tags. After each push, older nightlies are left untagged; see cleanup workflow. Pin in production with a **semver** release image, or (short-term) the digest printed above.'
echo ""
echo "Verify with:"
echo '```bash'
echo "cosign verify \\"
echo " --certificate-identity-regexp 'https://github.com/${{ github.repository }}/.github/workflows/nightly-container.yml@.*' \\"
echo " --certificate-oidc-issuer https://token.actions.githubusercontent.com \\"
echo " ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"