name: update

on:
  workflow_dispatch:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  update-components:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      pull-requests: write
    steps:
      - name: Check out code
        uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
      - name: Setup Go
        uses: actions/setup-go@44694675825211faa026b3c33043df3e48a5fa00 # v6.0.0
        with:
          go-version: 1.25.x
          cache-dependency-path: |
            **/go.sum
            **/go.mod
      - name: Update component versions
        id: update
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          PR_BODY=$(mktemp)

          bump_version() {
            local LATEST_VERSION=$(curl -s -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/fluxcd/$1/releases | jq -r 'sort_by(.published_at) | .[-1] | .tag_name')

            if [[ "$LATEST_VERSION" == *"-rc"* ]]; then
              echo "Skipping release candidate version for $1: $LATEST_VERSION"
              return
            fi

            local CTRL_VERSION=$(sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p;n" manifests/bases/$1/kustomization.yaml)
            local CRD_VERSION=$(sed -n "s/.*$1\/releases\/download\/\(.*\)\/.*/\1/p" manifests/crds/kustomization.yaml)
          
            local API_PKG="github.com/fluxcd/$1/api"
            if [[ "$1" == "source-watcher" ]]; then
              API_PKG="github.com/fluxcd/$1/api/v2"
            fi
            local MOD_VERSION=$(go list -m -f '{{ .Version }}' "$API_PKG")

            local changed=false

            if [[ "${CTRL_VERSION}" != "${LATEST_VERSION}" ]]; then
              sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${LATEST_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
              changed=true
            fi

            if [[ "${CRD_VERSION}" != "${LATEST_VERSION}" ]]; then
              sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${LATEST_VERSION}\2/g" "manifests/crds/kustomization.yaml"
              changed=true
            fi

            if [[ "${MOD_VERSION}" != "${LATEST_VERSION}" ]]; then
              go mod edit -require="$API_PKG@${LATEST_VERSION}"
              make tidy
              changed=true
            fi

            if [[ "$changed" == true ]]; then
              echo "- $1 to ${LATEST_VERSION}" >> $PR_BODY
              echo "  https://github.com/fluxcd/$1/blob/${LATEST_VERSION}/CHANGELOG.md" >> $PR_BODY
            fi
          }

          {
            # bump controller versions
            bump_version helm-controller
            bump_version kustomize-controller
            bump_version source-controller
            bump_version notification-controller
            bump_version image-reflector-controller
            bump_version image-automation-controller
            bump_version source-watcher

            # diff change
            git diff

            # export PR_BODY for PR and commit
            # NB: this may look strange but it is the way it should be done to
            # maintain our precious newlines
            # Ref: https://github.com/github/docs/issues/21529
            echo 'pr_body<<EOF' >> $GITHUB_OUTPUT
            cat $PR_BODY >> $GITHUB_OUTPUT
            echo 'EOF' >> $GITHUB_OUTPUT
          }

      - name: Create Pull Request
        id: cpr
        uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
        with:
          token: ${{ secrets.BOT_GITHUB_TOKEN }}
          commit-message: |
            Update toolkit components

            ${{ steps.update.outputs.pr_body }}
          committer: GitHub <noreply@github.com>
          author: fluxcdbot <fluxcdbot@users.noreply.github.com>
          signoff: true
          branch: update-components
          title: Update toolkit components
          body: |
            ${{ steps.update.outputs.pr_body }}
          labels: |
            dependencies
          reviewers: ${{ secrets.ASSIGNEES }}

      - name: Check output
        run: |
          echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
          echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
