# This action requires that any PR targeting the main branch should add a
# changelog fragment file in the .changelog/ directory. If a changelog entry
# is not required, add the "Skip Changelog" label to disable this action.

name: changelog

on:
  pull_request:
    types: [opened, synchronize, reopened, labeled, unlabeled]
    branches:
      - main
  merge_group:

permissions:
  contents: read

jobs:
  changelog:
    runs-on: ubuntu-latest
    if: |
      github.event_name != 'merge_group' &&
      !contains(github.event.pull_request.labels.*.name, 'Skip Changelog')
      && github.actor != 'otelbot[bot]'

    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Fetch base branch
        run: git fetch origin ${{ github.base_ref }} --depth=1

      - name: Ensure no direct changes to CHANGELOG.md
        run: |
          if [[ $(git diff --name-only FETCH_HEAD -- 'CHANGELOG.md') ]]
          then
            echo "CHANGELOG.md should not be directly modified."
            echo "Please add a changelog fragment file to the .changelog/ directory instead."
            echo "See CONTRIBUTING.md for details."
            echo ""
            echo "Or add the \"Skip Changelog\" label if this job should be skipped."
            false
          fi

      - name: Install towncrier
        run: pip install towncrier==25.8.0

      - name: Check for changelog fragment
        run: |
          if ! towncrier check --compare-with origin/${{ github.base_ref }}; then
            echo ""
            echo "No changelog fragment found for this PR."
            echo "Add a file named .changelog/${{ github.event.pull_request.number }}.<type>"
            echo "where <type> is one of: added, changed, deprecated, removed, fixed"
            echo "See CONTRIBUTING.md for details."
            echo ""
            echo "Or add the \"Skip Changelog\" label if this job should be skipped."
            false
          fi

      - name: Validate fragment filenames
        env:
          PR_NUMBER: ${{ github.event.pull_request.number }}
        run: |
          fragments=$(git diff --diff-filter=A --name-only origin/${{ github.base_ref }} -- '.changelog/*' | grep -v '/\.gitignore$' || true)
          [ -z "$fragments" ] && exit 0
          invalid=()
          while IFS= read -r f; do
            base=$(basename "$f")
            if [[ ! "$base" =~ ^([0-9]+)\.(added|changed|deprecated|removed|fixed)$ ]]; then
              invalid+=("$f (expected <PR_NUMBER>.<type>; type one of added, changed, deprecated, removed, fixed)")
              continue
            fi
            if [[ "${BASH_REMATCH[1]}" != "${PR_NUMBER}" ]]; then
              invalid+=("$f (PR number ${BASH_REMATCH[1]} does not match this PR's number ${PR_NUMBER})")
            fi
          done <<< "$fragments"
          if (( ${#invalid[@]} > 0 )); then
            echo "Invalid changelog fragment(s):"
            for msg in "${invalid[@]}"; do
              echo "  $msg"
            done
            exit 1
          fi

      - name: Preview changelog
        run: towncrier build --draft --version Unreleased
