name: Enterprise CI/CD
run-name: ${{ github.ref_name }} · ${{ github.sha }}

on:
  pull_request:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: delivery-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  IMAGE: ghcr.io/${{ github.repository }}
  CHART: blueprints/helm/devops-platform

jobs:
  quality:
    name: Build, lint and test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci --ignore-scripts
      - run: npm run lint
      - run: npm test
      - run: npm run build
      - uses: actions/upload-artifact@v4
        with:
          name: static-delivery-artifact
          path: dist
          if-no-files-found: error
          retention-days: 14

  security:
    name: Security and supply chain
    runs-on: ubuntu-latest
    permissions:
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v4
      - uses: github/codeql-action/init@v3
        with:
          languages: javascript-typescript
      - uses: github/codeql-action/analyze@v3
      - uses: aquasecurity/trivy-action@0.28.0
        with:
          scan-type: fs
          format: sarif
          output: trivy-results.sarif
          severity: CRITICAL,HIGH
          ignore-unfixed: true
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: trivy-results.sarif

  chart:
    name: Validate Helm release
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: azure/setup-helm@v4
      - run: helm lint "$CHART"
      - run: helm template devops-platform "$CHART" --set image.repository="$IMAGE" --set image.tag="${GITHUB_SHA}" > rendered-manifests.yaml
      - uses: actions/upload-artifact@v4
        with:
          name: rendered-kubernetes-manifests
          path: rendered-manifests.yaml
          retention-days: 14

  image:
    name: Build immutable image
    if: github.event_name != 'pull_request'
    needs: [quality, security, chart]
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      id-token: write
      attestations: write
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          file: Dockerfile
          push: true
          tags: ${{ env.IMAGE }}:${{ github.sha }}
          provenance: true
          sbom: true
          cache-from: type=gha
          cache-to: type=gha,mode=max
      - uses: actions/attest-build-provenance@v2
        with:
          subject-name: ${{ env.IMAGE }}
          subject-digest: ${{ steps.build.outputs.digest }}
          push-to-registry: true

  promote:
    name: Promote desired state
    if: github.ref == 'refs/heads/main'
    needs: image
    runs-on: ubuntu-latest
    environment: production
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/checkout@v4
        with:
          repository: ${{ vars.GITOPS_REPOSITORY }}
          token: ${{ secrets.GITOPS_TOKEN }}
          path: gitops
      - run: node scripts/update-values.mjs gitops/environments/production/values.yaml "${GITHUB_SHA}"
      - working-directory: gitops
        run: |
          git config user.name github-actions[bot]
          git config user.email 41898282+github-actions[bot]@users.noreply.github.com
          git add environments/production/values.yaml
          if git diff --cached --quiet; then
            echo "Desired state already references ${GITHUB_SHA}"
          else
            git commit -m "deploy: ${{ github.repository }}@${GITHUB_SHA}"
            git push
          fi

  verify:
    name: Verify production
    if: github.ref == 'refs/heads/main'
    needs: promote
    runs-on: ubuntu-latest
    steps:
      - run: sleep 30
      - name: Verify application health
        run: curl --fail --show-error --retry 10 --retry-all-errors --retry-delay 12 "${{ vars.PRODUCTION_HEALTH_URL }}"
