name: Release

permissions:
  contents: read
  issues: write
  pull-requests: write
  actions: write
  checks: write
  deployments: write
  statuses: write

on:
  workflow_dispatch:
    inputs:
      tag:
        description: Release (Uses this non-existing semantic version tag.)
        required: true
        type: string
        default: v0.99.0
      dryrun:
        description: Dry Run (Verifies workflow without pushing a release.)
        type: boolean
        required: false
        default: true

jobs:
  release:
    name: Create Release
    runs-on: ubuntu-latest
    permissions:
      contents: write
    timeout-minutes: 60
    outputs:
      latesttag: ${{ steps.tag.outputs.islatest }}
    steps:
      - name: Docker Login
        run: docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_PASSWORD }}
      - name: Checkout Repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          fetch-depth: 0 # for CHANGELOG
          ref: ${{ github.ref }} # branch provided on dispatch
      - name: Validate Branch and Tag
        run: |
          # do not allow release on main branch
          if [[ ${{ github.ref }} == refs/heads/main ]]; then
            echo "::error:: release must be done on a release branch"
            exit 1
          fi

          # check it starts with "v"
          if [[ ${{ inputs.tag }} != v* ]]; then
            echo "::error:: tag must have a \"v\" prefix"
            exit 1
          fi

          # check it does not exist
          if [[ $(git tag -l ${{ inputs.tag }} ) ]]; then
            echo "::error:: tag already exists"
            exit 1
          fi

          # set tag environment variable
          echo "TAG=${{ inputs.tag }}" >> $GITHUB_ENV
      - name: Setup Go
        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0
        with:
          go-version: '1.23'
      - name: Update version.go
        run: |
          # strip semantic v
          export GOVMOMI_VERSION=${TAG#"v"}

          sed -i "s/ClientVersion =.*/ClientVersion = \"$GOVMOMI_VERSION\"/" internal/version/version.go
          git --no-pager diff internal/version/version.go

          # configure author
          # https://github.community/t/github-actions-bot-email-address/17204/6
          git config --local user.email 41898282+github-actions[bot]@users.noreply.github.com
          git config --local user.name "GitHub Action"

          # commit changes
          git add internal/version/version.go
          git commit -s -m "chore: Update version.go for ${TAG}"
      - name: Create Tag
        id: tag
        run: |
          # create new tag
          git tag -a ${TAG} -m "Release ${TAG}"

          # find latest tag sorted by semver ref
          LATEST=$(git tag --sort=v:refname | tail -1)

          # check whether the new tag is also the latest
          if [[ $LATEST == $TAG ]]; then
            echo "islatest=true >> $GITHUB_OUTPUT"
          else
            echo "islatest=false >> $GITHUB_OUTPUT"
          fi
      - name: Push to Release Branch
        if: ${{ !inputs.dryrun }}
        env:
          GOVMOMI_RELEASE: ${{ secrets.GOVMOMI_RELEASE }}
        run: |
          git remote set-url origin https://x-access-token:${GOVMOMI_RELEASE}@github.com/${{ github.repository }}
          git push --atomic --follow-tags origin ${{ github.ref }}
      - name: Create Release CHANGELOG
        env:
          IMAGE: quay.io/git-chglog/git-chglog
          # https://quay.io/repository/git-chglog/git-chglog from tag v0.14.2
          IMAGE_SHA: 998e89dab8dd8284cfff5f8cfb9e9af41fe3fcd4671f2e86a180e453c20959e3
        run: |
          # generate CHANGELOG for this Github release tag only
          docker run --rm -v $PWD:/workdir ${IMAGE}@sha256:${IMAGE_SHA} -o RELEASE_CHANGELOG.md --sort semver --tag-filter-pattern '^v[0-9]+' ${TAG}
      - name: Archive CHANGELOG
        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
        continue-on-error: true
        with:
          name: CHANGELOG
          path: |
            ./RELEASE_CHANGELOG.md
          retention-days: 14
      - name: Simulate Release without Pushing Artifacts
        if: ${{ inputs.dryrun }}
        uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          version: latest
          args: release --snapshot --clean --release-notes RELEASE_CHANGELOG.md
      - name: Create Release
        if: ${{ !inputs.dryrun }}
        uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
        env:
          GITHUB_TOKEN: ${{ secrets.GOVMOMI_RELEASE }}
        with:
          version: latest
          args: release --clean --release-notes RELEASE_CHANGELOG.md # will push artefacts and container images
  pull-request:
    needs: release
    name: Create CHANGELOG.md PR
    runs-on: ubuntu-latest
    permissions:
      contents: write
    continue-on-error: true
    # Only update CHANGELOG for latest semver tag.
    if: ${{ !inputs.dryrun && needs.release.outputs.latesttag == 'true' }}
    steps:
      - name: Checkout Repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          fetch-depth: 0 # for CHANGELOG
          ref: main
      - name: Commit CHANGELOG
        env:
          IMAGE: quay.io/git-chglog/git-chglog
          # https://quay.io/repository/git-chglog/git-chglog from tag v0.14.2
          IMAGE_SHA: 998e89dab8dd8284cfff5f8cfb9e9af41fe3fcd4671f2e86a180e453c20959e3
        run: |
          # update CHANGELOG
          docker run --rm -v $PWD:/workdir ${IMAGE}@sha256:${IMAGE_SHA} -o CHANGELOG.md --sort semver --tag-filter-pattern '^v[0-9]+' -t .chglog/CHANGELOG.tpl.md
      - name: Create Pull Request
        id: cpr
        uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
        with:
          commit-message: "Update CHANGELOG for ${{ inputs.tag }}"
          delete-branch: true
          title: "Update CHANGELOG for ${{ inputs.tag }}"
          signoff: true
          draft: false
          body: |
            ### Update CHANGELOG.md for new release.

            > **Note**
            > Due to a [limitation](https://github.com/peter-evans/create-pull-request/blob/master/docs/concepts-guidelines.md#triggering-further-workflow-runs) in Github Actions please **close and immediately reopen** this PR to trigger the required workflow checks before merging.
      - name: Pull Request Information
        run: |
          echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}"
          echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}"
