Fix errors #95
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI/CD Pipeline # GhostClass | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| merge_group: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| jobs: | |
| # This job acts as your "Guard". It runs on EVERY PR and Push. | |
| guard: | |
| name: Build Guard | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| # This job only runs if guard passes AND we are pushing to main (merging) | |
| build-push-sign: | |
| name: Build, Push & Sign | |
| needs: guard | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build & push image | |
| id: build-push | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| push: true | |
| tags: | | |
| ghcr.io/devakesu/ghostclass:main | |
| ghcr.io/devakesu/ghostclass:${{ github.sha }} | |
| secrets: | | |
| sentry_token=${{ secrets.SENTRY_AUTH_TOKEN }} | |
| build-args: | | |
| APP_COMMIT_SHA=${{ github.sha }} | |
| SOURCE_DATE_EPOCH=1704067200 | |
| # --- Secrets (must be set in GitHub Repo Secrets) --- | |
| NEXT_PUBLIC_BACKEND_URL=${{ secrets.NEXT_PUBLIC_BACKEND_URL }} | |
| NEXT_PUBLIC_SUPABASE_URL=${{ secrets.NEXT_PUBLIC_SUPABASE_URL }} | |
| NEXT_PUBLIC_SUPABASE_ANON_KEY=${{ secrets.NEXT_PUBLIC_SUPABASE_ANON_KEY }} | |
| NEXT_PUBLIC_GITHUB_URL=${{ secrets.NEXT_PUBLIC_GITHUB_URL }} | |
| NEXT_PUBLIC_SENTRY_DSN=${{ secrets.NEXT_PUBLIC_SENTRY_DSN }} | |
| NEXT_PUBLIC_TURNSTILE_SITE_KEY=${{ secrets.NEXT_PUBLIC_TURNSTILE_SITE_KEY }} | |
| NEXT_PUBLIC_GA_ID=${{ secrets.NEXT_PUBLIC_GA_ID }} | |
| # --- Sentry Config --- | |
| SENTRY_ORG=devakesu | |
| SENTRY_PROJECT=ghostclass | |
| # --- Public App Info (Hardcoded for stability) --- | |
| NEXT_PUBLIC_APP_NAME=GhostClass | |
| NEXT_PUBLIC_APP_DOMAIN=ghostclass.devakesu.com | |
| NEXT_PUBLIC_APP_URL=https://ghostclass.devakesu.com | |
| NEXT_PUBLIC_SITEMAP_URL=https://ghostclass.devakesu.com/sitemap.xml | |
| NEXT_PUBLIC_AUTHOR_NAME=@deva.kesu | |
| NEXT_PUBLIC_AUTHOR_URL=https://devakesu.com | |
| NEXT_PUBLIC_APP_EMAIL=@ghostclass.devakesu.com | |
| NEXT_PUBLIC_LEGAL_EMAIL=legal@ghostclass.devakesu.com | |
| NEXT_PUBLIC_LEGAL_EFFECTIVE_DATE="January 1, 2026" | |
| labels: | | |
| org.opencontainers.image.revision=${{ github.sha }} | |
| org.opencontainers.image.source=https://github.com/devakesu/GhostClass | |
| org.opencontainers.image.created=${{ steps.prep.outputs.created }} | |
| # Retrieve image digest | |
| - name: Get image digest | |
| run: | | |
| echo "IMAGE_DIGEST=${{ steps.build-push.outputs.digest }}" >> $GITHUB_ENV | |
| # Install cosign | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@v3 | |
| # GENERATE SBOM | |
| - name: Generate SBOM | |
| uses: anchore/sbom-action@v0 | |
| with: | |
| image: ghcr.io/devakesu/ghostclass@${{ env.IMAGE_DIGEST }} | |
| format: cyclonedx-json | |
| output-file: sbom.json | |
| - name: Upload SBOM | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sbom | |
| path: sbom.json | |
| # ATTEST SBOM | |
| - name: Attest SBOM | |
| env: | |
| COSIGN_EXPERIMENTAL: "true" | |
| run: | | |
| cosign attest \ | |
| --yes \ | |
| --predicate sbom.json \ | |
| --type cyclonedx \ | |
| ghcr.io/devakesu/ghostclass@${{ env.IMAGE_DIGEST }} | |
| # GENERATE PROVENANCE (SLSA) | |
| - name: Generate provenance | |
| run: | | |
| cat <<EOF > provenance.json | |
| { | |
| "builder": { | |
| "id": "https://github.com/${{ github.repository }}/.github/workflows/${{ github.workflow }}" | |
| }, | |
| "buildType": "https://github.com/slsa-framework/slsa-github-generator/container@v1", | |
| "invocation": { | |
| "configSource": { | |
| "uri": "https://github.com/${{ github.repository }}", | |
| "digest": { | |
| "gitCommit": "${{ github.sha }}" | |
| } | |
| } | |
| }, | |
| "metadata": { | |
| "buildInvocationID": "${{ github.run_id }}", | |
| "startedOn": "${{ github.run_started_at }}" | |
| } | |
| } | |
| EOF | |
| # ATTEST PROVENANCE (SLSA) | |
| - name: Attest provenance (SLSA) | |
| run: | | |
| cosign attest \ | |
| --yes \ | |
| --predicate provenance.json \ | |
| --type slsaprovenance \ | |
| ghcr.io/devakesu/ghostclass@${{ env.IMAGE_DIGEST }} | |
| # SIGN IMAGE (keyless) | |
| - name: Sign image (keyless) | |
| env: | |
| COSIGN_EXPERIMENTAL: "true" | |
| run: | | |
| cosign sign --yes \ | |
| ghcr.io/devakesu/ghostclass@${{ env.IMAGE_DIGEST }} | |
| # Trigger deployment in Coolify | |
| - name: Trigger Coolify deploy | |
| env: | |
| COOLIFY_BASE_URL: ${{ secrets.COOLIFY_BASE_URL }} | |
| COOLIFY_APP_ID: ${{ secrets.COOLIFY_APP_ID }} | |
| COOLIFY_API_TOKEN: ${{ secrets.COOLIFY_API_TOKEN }} | |
| run: | | |
| curl \ | |
| "$COOLIFY_BASE_URL/api/v1/deploy?uuid=$COOLIFY_APP_ID" \ | |
| -H "Authorization: Bearer $COOLIFY_API_TOKEN" |