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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
      - name: Unshallow
        run: git fetch --prune --unshallow
      - name: Setup Go
        uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
        with:
          go-version: 1.25.x
          cache: false
      - name: Setup QEMU
        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0
      - name: Setup Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
      - name: Setup Syft
        uses: anchore/sbom-action/download-syft@f8bdd1d8ac5e901a77a92f111440fdb1b593736b # v0.20.6
      - name: Setup Cosign
        uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
      - name: Setup Kustomize
        uses: fluxcd/pkg/actions/kustomize@bf02f0a2d612cc07e0892166369fa8f63246aabb # main
      - name: Login to GitHub Container Registry
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
        with:
          registry: ghcr.io
          username: fluxcdbot
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Login to Docker Hub
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.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@bf02f0a2d612cc07e0892166369fa8f63246aabb # 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: Run GoReleaser
        id: run-goreleaser
        uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
        with:
          version: latest
          args: release --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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
      - name: Setup Kustomize
        uses: fluxcd/pkg/actions/kustomize@bf02f0a2d612cc07e0892166369fa8f63246aabb # main
      - name: Setup Flux CLI
        uses: ./action/
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
      - 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@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
        with:
          registry: ghcr.io
          username: fluxcdbot
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Login to DockerHub
        uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.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@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
      - 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@v2.1.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@v2.1.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@v2.1.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.GITHUB_TOKEN }}
