name: release

on:
  push:
    tags: [ 'v*' ]

permissions:
  contents: read

jobs:
  release-flux-cli:
    outputs:
      hashes: ${{ steps.slsa.outputs.hashes }}
      image_url: ${{ steps.slsa.outputs.image_url }}
      image_digest: ${{ steps.slsa.outputs.image_digest }}
    runs-on: ubuntu-latest
    permissions:
      contents: write # needed to write releases
      id-token: write # needed for keyless signing
      packages: write # needed for ghcr access
    steps:
      - name: Checkout
        uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
      - name: Unshallow
        run: git fetch --prune --unshallow
      - name: Setup Go
        uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
        with:
          go-version: 1.20.x
          cache: false
      - name: Setup QEMU
        uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
      - name: Setup Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55  # v2.10.0
      - name: Setup Syft
        uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
      - name: Setup Cosign
        uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
      - name: Setup Kustomize
        uses: fluxcd/pkg/actions/kustomize@main
      - name: Login to GitHub Container Registry
        uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
        with:
          registry: ghcr.io
          username: fluxcdbot
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Login to Docker Hub
        uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc  # v2.2.0
        with:
          username: fluxcdbot
          password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
      - name: Generate manifests
        run: |
          make cmd/flux/.manifests.done
          ./manifests/scripts/bundle.sh "" ./output manifests.tar.gz
          kustomize build ./manifests/install > ./output/install.yaml
      - name: Build CRDs
        run: |
          kustomize build manifests/crds > all-crds.yaml
      - name: Generate OpenAPI JSON schemas from CRDs
        uses: fluxcd/pkg/actions/crdjsonschema@main
        with:
          crd: all-crds.yaml
          output: schemas
      - name: Archive the OpenAPI JSON schemas
        run: |
          tar -czvf ./output/crd-schemas.tar.gz -C schemas .
      - name: Download release notes utility
        env:
          GH_REL_URL: https://github.com/buchanae/github-release-notes/releases/download/0.2.0/github-release-notes-linux-amd64-0.2.0.tar.gz
        run: cd /tmp && curl -sSL ${GH_REL_URL} | tar xz && sudo mv github-release-notes /usr/local/bin/
      - name: Generate release notes
        run: |
          NOTES="./output/notes.md"
          echo '## CLI Changelog' > ${NOTES}
          github-release-notes -org fluxcd -repo flux2 -since-latest-release -include-author >> ${NOTES}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Run GoReleaser
        id: run-goreleaser
        uses: goreleaser/goreleaser-action@5fdedb94abba051217030cc86d4523cf3f02243d # v4.6.0
        with:
          version: latest
          args: release --release-notes=output/notes.md --skip-validate
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
          AUR_BOT_SSH_PRIVATE_KEY: ${{ secrets.AUR_BOT_SSH_PRIVATE_KEY }}
      - name: Generate SLSA metadata
        id: slsa
        env:
          ARTIFACTS: "${{ steps.run-goreleaser.outputs.artifacts }}"
        run: |
          set -euo pipefail
          
          hashes=$(echo -E $ARTIFACTS | jq --raw-output '.[] | {name, "digest": (.extra.Digest // .extra.Checksum)} | select(.digest) | {digest} + {name} | join("  ") | sub("^sha256:";"")' | base64 -w0)
          echo "hashes=$hashes" >> $GITHUB_OUTPUT
          
          image_url=fluxcd/flux-cli:$GITHUB_REF_NAME
          echo "image_url=$image_url" >> $GITHUB_OUTPUT
          
          image_digest=$(docker buildx imagetools inspect ${image_url}  --format '{{json .}}' | jq -r .manifest.digest)
          echo "image_digest=$image_digest" >> $GITHUB_OUTPUT

  release-flux-manifests:
    runs-on: ubuntu-latest
    needs: release-flux-cli
    permissions:
      id-token: write
      packages: write
    steps:
      - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
      - name: Setup Kustomize
        uses: fluxcd/pkg/actions/kustomize@main
      - name: Setup Flux CLI
        uses: ./action/
      - name: Prepare
        id: prep
        run: |
          VERSION=$(flux version --client | awk '{ print $NF }')
          echo "version=${VERSION}" >> $GITHUB_OUTPUT
      - name: Login to GHCR
        uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
        with:
          registry: ghcr.io
          username: fluxcdbot
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Login to DockerHub
        uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
        with:
          username: fluxcdbot
          password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
      - name: Push manifests to GHCR
        run: |
          mkdir -p ./ghcr.io/flux-system
          flux install --registry=ghcr.io/fluxcd \
          --components-extra=image-reflector-controller,image-automation-controller \
          --export > ./ghcr.io/flux-system/gotk-components.yaml
          
          cd ./ghcr.io && flux push artifact \
          oci://ghcr.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
          --path="./flux-system" \
          --source=${{ github.repositoryUrl }} \
          --revision="${{ github.ref_name }}@sha1:${{ github.sha }}"
      - name: Push manifests to DockerHub
        run: |
          mkdir -p ./docker.io/flux-system
          flux install --registry=docker.io/fluxcd \
          --components-extra=image-reflector-controller,image-automation-controller \
          --export > ./docker.io/flux-system/gotk-components.yaml
          
          cd ./docker.io && flux push artifact \
          oci://docker.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
          --path="./flux-system" \
          --source=${{ github.repositoryUrl }} \
          --revision="${{ github.ref_name }}@sha1:${{ github.sha }}"
      - uses: sigstore/cosign-installer@11086d25041f77fe8fe7b9ea4e48e3b9192b8f19 # v3.1.2
      - name: Sign manifests
        env:
          COSIGN_EXPERIMENTAL: 1
        run: |
          cosign sign --yes ghcr.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }}
          cosign sign --yes docker.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }}
      - name: Tag manifests
        run: |
          flux tag artifact oci://ghcr.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
          --tag latest

          flux tag artifact oci://docker.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
          --tag latest

  release-provenance:
    needs: [release-flux-cli]
    permissions:
      actions: read # for detecting the Github Actions environment.
      id-token: write # for creating OIDC tokens for signing.
      contents: write # for uploading attestations to GitHub releases.
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
    with:
      provenance-name: "provenance.intoto.jsonl"
      base64-subjects: "${{ needs.release-flux-cli.outputs.hashes }}"
      upload-assets: true

  dockerhub-provenance:
    needs: [release-flux-cli]
    permissions:
      actions: read # for detecting the Github Actions environment.
      id-token: write # for creating OIDC tokens for signing.
      packages: write # for uploading attestations.
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
    with:
      image: ${{ needs.release-flux-cli.outputs.image_url }}
      digest: ${{ needs.release-flux-cli.outputs.image_digest }}
      registry-username: fluxcdbot
    secrets:
      registry-password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}

  ghcr-provenance:
    needs: [release-flux-cli]
    permissions:
      actions: read # for detecting the Github Actions environment.
      id-token: write # for creating OIDC tokens for signing.
      packages: write # for uploading attestations.
    uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
    with:
      image: ghcr.io/${{ needs.release-flux-cli.outputs.image_url }}
      digest: ${{ needs.release-flux-cli.outputs.image_digest }}
      registry-username: fluxcdbot
    secrets:
      registry-password: ${{ secrets.GHCR_TOKEN }}