name: Release - Feature Freeze Ceremony

#
# Feature Freeze
# 
# prereqs: 
# 0. needs approval from another person to run the action (environment)
# 1. ensure the correct branch is used to execute the action
#   a. if the run was triggered from the `main` branch, the NEXT_VERSION must be a new minor (end with a .0)
#   b. if NEXT_VERSION is a patch release, then the branch the action was triggered on must be a release branch: `^[0-9]+\.[0-9]+\.x$`
# 2. ensure the next version does not exist as tag yet
# 
# Tasks
# 0. bump minor -dev version in version.config on main, if and only if it's a .0 release
# 1. creates the release branch X.Y.x, if and if the branch does not exist yet
# 2. generates CHANGELOG and opens PR for it
# 3. generates the release artefacts for the next versions
# 4. bumps the version in version.config to minor + 1 if and only if a .0 release is done
#

on:
  workflow_dispatch:

# The workflow needs the permission to push branches
permissions:
  contents: write
  pull-requests: write

jobs:
  validate-conditions:
    name: Validate Run Conditions
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Check Release Conditions
        run: |
          NEXT_VERSION=$(head -1 version.config | cut -d ' ' -f 3 | cut -d '-' -f 1)
          RELEASE_BRANCH="${NEXT_VERSION/%.[0-9]/.x}"
          
          echo "Checking run conditions for release: $NEXT_VERSION" >> $GITHUB_STEP_SUMMARY
          echo "Current branch: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
          echo "Expected release branch: $RELEASE_BRANCH" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          
          # Condition: version tag can not exist
          if git tag -l | grep -q "^$NEXT_VERSION$"; then
            echo "❌ \`$NEXT_VERSION\` tag already exists" >> $GITHUB_STEP_SUMMARY
            exit 1
          fi

          # Condition: minor releases (.0) must be triggered from the main branch
          if [[ "$NEXT_VERSION" =~ \.0$ ]] && [[ "${{ github.ref_name }}" != "main" ]]; then
            echo "❌ for minor releases, \`$NEXT_VERSION\` the \`main\` branch is required, but got \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
            exit 1
          fi

          # Condition: patch releases must be triggered from the release branch
          if [[ ! "$NEXT_VERSION" =~ \.0$ ]] && [[ "${{ github.ref_name }}" != "$RELEASE_BRANCH" ]]; then
            echo "❌ the patch releases, \`$NEXT_VERSION\` the action must be started from the release branch \`$RELEASE_BRANCH\`, but got \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
            exit 1
          fi

          echo "✅ All release conditions satisfied for \`$NEXT_RELEASE\`" >> $GITHUB_STEP_SUMMARY

  release-feature-freeze-ceremony:
    name: Release - Feature Freeze
    runs-on: ubuntu-latest
    needs: validate-conditions
    environment:
      name: Release Ceremonies

    steps:
      - name: Checkout TimescaleDB
        uses: actions/checkout@v4

      # git user config timescale-automation
      - run: |
          git config user.name "timescale-automation"
          git config user.email "123763385+github-actions[bot]@users.noreply.github.com"

      - name: Install Dependencies
        run: |
          sudo apt-get update
          sudo apt-get install pip
          pip install PyGithub requests

      # Read the next version and build the next versions
      - name: Set version configuration
        run: |
          NEXT_VERSION=$(head -1 version.config | cut -d ' ' -f 3 | cut -d '-' -f 1)
          CURRENT_VERSION=$(tail -1 version.config | cut -d ' ' -f 3 | cut -d '-' -f 1)
          RELEASE_BRANCH="${NEXT_VERSION/%.[0-9]/.x}"

          echo "RELEASE_BRANCH=${RELEASE_BRANCH}" >> $GITHUB_ENV
          echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_ENV
          echo "NEXT_VERSION=${NEXT_VERSION}" >> $GITHUB_ENV

          echo "# 🚀 Release v${NEXT_VERSION}" >> $GITHUB_STEP_SUMMARY
          echo "Previous version: \`$CURRENT_VERSION\`" >> $GITHUB_STEP_SUMMARY
          echo "Release branch: \`$RELEASE_BRANCH\`" >> $GITHUB_STEP_SUMMARY
          echo "Workflow branch: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY

      # -------------------------------------------------------
      #
      # Only running for new minor releases
      #
      # -------------------------------------------------------
      
      # Bump minor in main for minor releases
      - uses: actions/checkout@v4
        with:
          ref: main

      - name: Bump minor version on main if next release is a new minor
        if: endsWith(env.NEXT_VERSION, '.0')
        env:
          GITHUB_TOKEN: ${{ secrets.ORG_AUTOMATION_TOKEN }}
        run: |
          NEXT_MAIN_VERSION=$(head -1 version.config | cut -d ' ' -f 3 | cut -d '-' -f 1)
          NEXT_MAIN_VERSION=$(echo "$NEXT_MAIN_VERSION" | awk -F. '{printf "%d.%d.0-dev", $1, $2 + 1}')
          sed -i "s/^version = .*/version = $NEXT_MAIN_VERSION/" version.config

          BRANCH="release/bump-main-to-$NEXT_MAIN_VERSION"
          git checkout -b $BRANCH
          git add version.config
          git commit -m "Increase minor version $NEXT_MAIN_VERSION"
          git push origin $BRANCH

          PR_URL=$(gh pr create \
            --title "Increase minor version $NEXT_MAIN_VERSION" \
            --body "Bump to next minor for the upcoming ${{ env.CURRENT_VERSION }} release" \
            --base main \
            --head $BRANCH \
            --label "release")
          echo "* ✅ minor version increase on main: $PR_URL" >> $GITHUB_STEP_SUMMARY
      
      # Create `2.XX.x` release branch of `main`
      # Release branch is a dependency for the next steps
      # only execute this step on .0 releases
      - name: Create Release Branch
        env:
          GITHUB_TOKEN: ${{ secrets.ORG_AUTOMATION_TOKEN }}
        run: |
          if git ls-remote --heads origin "${{ env.RELEASE_BRANCH }}" | grep -q "${{ env.RELEASE_BRANCH }}"; then
            echo "* ✓ the \`${{ env.RELEASE_BRANCH }}\` release branch exists" >> $GITHUB_STEP_SUMMARY
          else
            gh api repos/${{ github.repository }}/git/refs \
              --method POST \
              --field ref="refs/heads/${{ env.RELEASE_BRANCH }}" \
              --field sha="${{ github.sha }}"
            echo "* ✅ the \`${{ env.RELEASE_BRANCH }}\` release branch created" >> $GITHUB_STEP_SUMMARY
          fi

      # -------------------------------------------------------
      #
      # Runs for every release
      #
      # -------------------------------------------------------

      # Generate the CHANGELOG and submit it in a separate PR
      - uses: actions/checkout@v4
        with:
          ref: ${{ env.RELEASE_BRANCH }}

      - name: Generate and create Pull Request for CHANGELOG
        env:
          GITHUB_TOKEN: ${{ secrets.ORG_AUTOMATION_TOKEN }}
        run: |
          ./scripts/changelog/generate.sh 
          BODY=$(head -n 19 CHANGELOG.md | tail -n 20)

          BRANCH="release/${{ env.NEXT_VERSION }}-changelog"
          git checkout -b $BRANCH
          git add .unreleased/* CHANGELOG.md
          git commit -m "CHANGELOG ${{ env.NEXT_VERSION }}"
          git push origin $BRANCH

          PR_URL=$(gh pr create \
            --title "Release ${{ env.NEXT_VERSION }}" \
            --body "$BODY" \
            --base ${{ env.RELEASE_BRANCH }} \
            --head $BRANCH \
            --label "release,changelog")
          echo "* ✅ CHANGELOG: $PR_URL" >> $GITHUB_STEP_SUMMARY

      # Rework version.config and up & down grade scripts
      - uses: actions/checkout@v4
        with:
          ref: ${{ env.RELEASE_BRANCH }}
      - name: Generate release artefacts
        env:
          GITHUB_TOKEN: ${{ secrets.ORG_AUTOMATION_TOKEN }}
        run: |
          ./scripts/release/build_release_artefacts.sh ${{ env.CURRENT_VERSION }} ${{ env.NEXT_VERSION }}

          BRANCH="release/${{ env.CURRENT_VERSION }}-${{ env.NEXT_VERSION }}"
          git checkout -b $BRANCH
          git add version.config sql/updates/*.sql sql/CMakeLists.txt
          git commit -m "release artefacts from ${{ env.CURRENT_VERSION }} to ${{ env.NEXT_VERSION }}"
          git push origin $BRANCH

          BODY="- CHANGELOG\n- set previous_version in version.config\n- adjust CMakeList.txt with up & down grade files"

          PR_URL=$(gh pr create \
            --title "Release artefacts ${{ env.NEXT_VERSION }}" \
            --body "${BODY//\\n/$\n}" \
            --base ${{ env.RELEASE_BRANCH }} \
            --head $BRANCH \
            --label "release")
          echo "* ✅ Release artefacts: $PR_URL" >> $GITHUB_STEP_SUMMARY
