300 lines
11 KiB
YAML
300 lines
11 KiB
YAML
name: Nightly Build & Package
|
|
on:
|
|
schedule:
|
|
# Daily at 09:00 UTC (4am EST / 5am EDT)
|
|
- cron: '0 9 * * *'
|
|
workflow_dispatch:
|
|
inputs:
|
|
reason:
|
|
description: "Why are you running this manually?"
|
|
required: true
|
|
default: "manual trigger"
|
|
skip_tests:
|
|
description: "Skip test-nightly-image job?"
|
|
required: false
|
|
default: "false"
|
|
|
|
env:
|
|
GO_VERSION: '1.25.6'
|
|
NODE_VERSION: '24.12.0'
|
|
GOTOOLCHAIN: auto
|
|
GHCR_REGISTRY: ghcr.io
|
|
DOCKERHUB_REGISTRY: docker.io
|
|
IMAGE_NAME: wikid82/charon
|
|
|
|
jobs:
|
|
sync-development-to-nightly:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: write
|
|
outputs:
|
|
has_changes: ${{ steps.sync.outputs.has_changes }}
|
|
|
|
steps:
|
|
- name: Checkout nightly branch
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: nightly
|
|
fetch-depth: 0
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Configure Git
|
|
run: |
|
|
git config user.name "github-actions[bot]"
|
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
|
|
- name: Sync development to nightly
|
|
id: sync
|
|
run: |
|
|
# Fetch both branches to ensure we have the latest remote state
|
|
git fetch origin development
|
|
git fetch origin nightly
|
|
|
|
# Sync local nightly with remote nightly to prevent non-fast-forward errors
|
|
echo "Syncing local nightly with remote nightly..."
|
|
git reset --hard origin/nightly
|
|
|
|
# Check if there are differences between remote branches
|
|
if git diff --quiet origin/nightly origin/development; then
|
|
echo "No changes to sync from development to nightly"
|
|
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Syncing changes from development to nightly"
|
|
# Fast-forward merge development into nightly
|
|
git merge origin/development --ff-only -m "chore: sync from development branch [skip ci]" || {
|
|
# If fast-forward fails, force reset to development
|
|
echo "Fast-forward not possible, resetting nightly to development"
|
|
git reset --hard origin/development
|
|
}
|
|
# Force push to handle cases where nightly diverged from development
|
|
git push --force origin nightly
|
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
build-and-push-nightly:
|
|
needs: sync-development-to-nightly
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
HAS_DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN != '' }}
|
|
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 nightly branch
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: nightly
|
|
fetch-depth: 0
|
|
|
|
- name: Set lowercase image name
|
|
run: echo "IMAGE_NAME_LC=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
|
|
|
- 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@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
|
with:
|
|
registry: ${{ env.GHCR_REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Log in to Docker Hub
|
|
if: env.HAS_DOCKERHUB_TOKEN == 'true'
|
|
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
|
with:
|
|
registry: docker.io
|
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
|
|
- name: Extract metadata
|
|
id: meta
|
|
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
|
|
with:
|
|
images: |
|
|
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
${{ env.DOCKERHUB_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 }}
|
|
VCS_REF=${{ github.sha }}
|
|
BUILD_DATE=${{ github.event.repository.pushed_at }}
|
|
cache-from: type=gha
|
|
cache-to: type=gha,mode=max
|
|
provenance: true
|
|
sbom: true
|
|
|
|
- name: Record nightly image digest
|
|
run: |
|
|
echo "## 🧾 Nightly Image Digest" >> $GITHUB_STEP_SUMMARY
|
|
echo "- ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:nightly@${{ steps.build.outputs.digest }}" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: Generate SBOM
|
|
uses: anchore/sbom-action@deef08a0db64bfad603422135db61477b16cef56 # v0.22.1
|
|
with:
|
|
image: ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:nightly@${{ steps.build.outputs.digest }}
|
|
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
|
|
|
|
# Install Cosign for keyless signing
|
|
- name: Install Cosign
|
|
uses: sigstore/cosign-installer@faadad0cce49287aee09b3a48701e75088a2c6ad # v4.0.0
|
|
|
|
# Sign GHCR image with keyless signing (Sigstore/Fulcio)
|
|
- name: Sign GHCR Image
|
|
run: |
|
|
echo "Signing GHCR nightly image with keyless signing..."
|
|
cosign sign --yes ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
|
|
echo "✅ GHCR nightly image signed successfully"
|
|
|
|
# Sign Docker Hub image with keyless signing (Sigstore/Fulcio)
|
|
- name: Sign Docker Hub Image
|
|
if: env.HAS_DOCKERHUB_TOKEN == 'true'
|
|
run: |
|
|
echo "Signing Docker Hub nightly image with keyless signing..."
|
|
cosign sign --yes ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
|
|
echo "✅ Docker Hub nightly image signed successfully"
|
|
|
|
# Attach SBOM to Docker Hub image
|
|
- name: Attach SBOM to Docker Hub
|
|
if: env.HAS_DOCKERHUB_TOKEN == 'true'
|
|
run: |
|
|
echo "Attaching SBOM to Docker Hub nightly image..."
|
|
cosign attach sbom --sbom sbom-nightly.json ${{ env.DOCKERHUB_REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }}
|
|
echo "✅ SBOM attached to Docker Hub nightly image"
|
|
|
|
test-nightly-image:
|
|
needs: build-and-push-nightly
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: read
|
|
|
|
steps:
|
|
- name: Checkout nightly branch
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: nightly
|
|
|
|
- name: Set lowercase image name
|
|
run: echo "IMAGE_NAME_LC=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
|
|
|
- name: Log in to GitHub Container Registry
|
|
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
|
with:
|
|
registry: ${{ env.GHCR_REGISTRY }}
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Pull nightly image
|
|
run: docker pull ${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:nightly@${{ needs.build-and-push-nightly.outputs.digest }}
|
|
|
|
- name: Run container smoke test
|
|
run: |
|
|
docker run --name charon-nightly -d \
|
|
-p 8080:8080 \
|
|
${{ env.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}:nightly@${{ needs.build-and-push-nightly.outputs.digest }}
|
|
|
|
# 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
|
|
|
|
# NOTE: Standalone binary builds removed - Charon uses Docker-only deployment
|
|
# The build-nightly-release job that ran GoReleaser for Windows/macOS/Linux binaries
|
|
# was removed because:
|
|
# 1. Charon is distributed exclusively via Docker images
|
|
# 2. Cross-compilation was failing due to Unix-specific syscalls
|
|
# 3. No users download standalone binaries (all use Docker)
|
|
# If standalone binaries are needed in the future, re-add the job with Linux-only targets
|
|
|
|
verify-nightly-supply-chain:
|
|
needs: build-and-push-nightly
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: read
|
|
security-events: write
|
|
|
|
steps:
|
|
- name: Checkout nightly branch
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
ref: nightly
|
|
|
|
- name: Set lowercase image name
|
|
run: echo "IMAGE_NAME_LC=${IMAGE_NAME,,}" >> $GITHUB_ENV
|
|
|
|
- name: Download SBOM
|
|
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
with:
|
|
name: sbom-nightly
|
|
|
|
- name: Scan with Grype
|
|
uses: anchore/scan-action@8d2fce09422cd6037e577f4130e9b925e9a37175 # v7.3.1
|
|
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.GHCR_REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.build-and-push-nightly.outputs.digest }}
|
|
format: 'sarif'
|
|
output: 'trivy-nightly.sarif'
|
|
|
|
- name: Upload Trivy results
|
|
uses: github/codeql-action/upload-sarif@6bc82e05fd0ea64601dd4b465378bbcf57de0314 # v4.32.1
|
|
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"
|