name: Nightly Build & Package on: push: branches: - nightly schedule: # Daily at 09:00 UTC (4am EST / 5am EDT) - cron: '0 9 * * *' workflow_dispatch: env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} jobs: build-and-push-nightly: runs-on: ubuntu-latest permissions: contents: read packages: write id-token: write outputs: version: ${{ steps.meta.outputs.version }} tags: ${{ steps.meta.outputs.tags }} digest: ${{ steps.build.outputs.digest }} steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 - name: Set up QEMU uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0 - name: Set up Docker Buildx uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to GitHub Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=raw,value=nightly type=raw,value=nightly-{{date 'YYYY-MM-DD'}} type=sha,prefix=nightly-,format=short labels: | org.opencontainers.image.title=Charon Nightly org.opencontainers.image.description=Nightly build of Charon - name: Build and push Docker image id: build uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: . platforms: linux/amd64,linux/arm64 push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | VERSION=nightly-${{ github.sha }} cache-from: type=gha cache-to: type=gha,mode=max provenance: true sbom: true - name: Generate SBOM uses: anchore/sbom-action@0b82b0b1a22399a1c542d4d656f70cd903571b5c # v0.21.1 with: image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly format: cyclonedx-json output-file: sbom-nightly.json - name: Upload SBOM artifact uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: sbom-nightly path: sbom-nightly.json retention-days: 30 test-nightly-image: needs: build-and-push-nightly runs-on: ubuntu-latest permissions: contents: read packages: read steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Log in to GitHub Container Registry uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Pull nightly image run: docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Run container smoke test run: | docker run --name charon-nightly -d \ -p 8080:8080 \ ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly # Wait for container to start sleep 10 # Check container is running docker ps | grep charon-nightly # Basic health check curl -f http://localhost:8080/health || exit 1 # Cleanup docker stop charon-nightly docker rm charon-nightly build-nightly-release: needs: test-nightly-image runs-on: ubuntu-latest permissions: contents: read steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 with: fetch-depth: 0 - name: Set up Go uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 with: go-version: '1.25.6' - name: Set up Node.js uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 with: node-version: '24.13.0' - name: Set up Zig (for cross-compilation) uses: goto-bus-stop/setup-zig@abea47f85e598557f500fa1fd2ab7464fcb39406 # v2.2.1 with: version: 0.11.0 - name: Build frontend working-directory: ./frontend run: | npm ci npm run build - name: Run GoReleaser (snapshot mode) uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 with: distribution: goreleaser version: '~> v2' args: release --snapshot --skip=publish --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Upload nightly binaries uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0 with: name: nightly-binaries path: dist/* retention-days: 30 verify-nightly-supply-chain: needs: build-and-push-nightly runs-on: ubuntu-latest permissions: contents: read packages: read security-events: write steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - name: Download SBOM uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0 with: name: sbom-nightly - name: Scan with Grype uses: anchore/scan-action@62b74fb7bb810d2c45b1865f47a77655621862a5 # v7.2.3 with: sbom: sbom-nightly.json fail-build: false severity-cutoff: high - name: Scan with Trivy uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 with: image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly format: 'sarif' output: 'trivy-nightly.sarif' - name: Upload Trivy results uses: github/codeql-action/upload-sarif@cdefb33c0f6224e58673d9004f47f7cb3e328b89 # v4.31.10 with: sarif_file: 'trivy-nightly.sarif' category: 'trivy-nightly' - name: Check for critical CVEs run: | if grep -q "CRITICAL" trivy-nightly.sarif; then echo "❌ Critical vulnerabilities found in nightly build" exit 1 fi echo "✅ No critical vulnerabilities found"