---
name: CI/CD

on:
  push:
    branches:
      - master
      - release/**


# default token permissions = none
permissions: {}


jobs:

  eval-changes:
    name: Evaluate changes
    runs-on: ubuntu-latest

    steps:
      - name: Setup | Checkout Repository
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8  # v6.0.1
        with:
          fetch-depth: 0

      - name: Evaluate | Check common file types for changes
        id: core-changed-files
        uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891  #v47.0.1
        with:
          base_sha: ${{ github.event.push.before }}
          files_yaml_from_source_file: .github/changed-files-spec.yml

      - name: Evaluate | Check specific file types for changes
        id: ci-changed-files
        uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891  #v47.0.1
        with:
          base_sha: ${{ github.event.push.before }}
          files_yaml: |
            ci:
              - .github/workflows/cicd.yml
              - .github/workflows/validate.yml

      - name: Evaluate | Detect if any of the combinations of file sets have changed
        id: all-changes
        run: |
          printf '%s\n' "any_changed=false" >> $GITHUB_OUTPUT
          if [ "${{ steps.core-changed-files.outputs.build_any_changed }}" == "true" ] || \
             [ "${{ steps.ci-changed-files.outputs.ci_any_changed }}" == "true" ] || \
             [ "${{ steps.core-changed-files.outputs.docs_any_changed }}" == "true" ] || \
             [ "${{ steps.core-changed-files.outputs.src_any_changed }}" == "true" ] || \
             [ "${{ steps.core-changed-files.outputs.tests_any_changed }}" == "true" ] || \
             [ "${{ steps.core-changed-files.outputs.gha_src_any_changed }}" == "true" ] || \
             [ "${{ steps.core-changed-files.outputs.gha_tests_any_changed }}" == "true" ]; then
              printf '%s\n' "any_changed=true" >> $GITHUB_OUTPUT
          fi

    outputs:
      any-file-changes: ${{ steps.all-changes.outputs.any_changed }}
      build-changes: ${{ steps.core-changed-files.outputs.build_any_changed }}
      ci-changes: ${{ steps.ci-changed-files.outputs.ci_any_changed }}
      doc-changes: ${{ steps.core-changed-files.outputs.docs_any_changed }}
      src-changes: ${{ steps.core-changed-files.outputs.src_any_changed }}
      test-changes: ${{ steps.core-changed-files.outputs.tests_any_changed }}
      gha-src-changes: ${{ steps.core-changed-files.outputs.gha_src_any_changed }}
      gha-test-changes: ${{ steps.core-changed-files.outputs.gha_tests_any_changed }}


  validate:
    uses: ./.github/workflows/validate.yml
    needs: eval-changes
    concurrency:
      group: ${{ github.workflow }}-validate-${{ github.ref_name }}
      cancel-in-progress: true
    with:
      # It was a bit of overkill before testing every minor version, and since this project is all about
      # SemVer, we should expect Python to adhere to that model to. Therefore Only test across 2 OS's but
      # the lowest supported minor version and the latest stable minor version.
      python-versions-linux: '["3.8", "3.14"]'
      python-versions-windows: '["3.8", "3.14"]'
      files-changed: ${{ needs.eval-changes.outputs.any-file-changes }}
      build-files-changed: ${{ needs.eval-changes.outputs.build-changes }}
      ci-files-changed: ${{ needs.eval-changes.outputs.ci-changes }}
      doc-files-changed: ${{ needs.eval-changes.outputs.doc-changes }}
      src-files-changed: ${{ needs.eval-changes.outputs.src-changes }}
      test-files-changed: ${{ needs.eval-changes.outputs.test-changes }}
      gha-src-files-changed: ${{ needs.eval-changes.outputs.gha-src-changes }}
      gha-test-files-changed: ${{ needs.eval-changes.outputs.gha-test-changes }}
    permissions: {}
    secrets: {}


  release:
    name: Semantic Release
    runs-on: ubuntu-latest
    needs: validate
    if: ${{ needs.validate.outputs.new-release-detected == 'true' }}

    concurrency:
      group: ${{ github.workflow }}-release-${{ github.ref_name }}
      cancel-in-progress: false

    permissions:
      contents: write

    env:
      GITHUB_ACTIONS_AUTHOR_NAME: github-actions
      GITHUB_ACTIONS_AUTHOR_EMAIL: actions@users.noreply.github.com

    steps:
      # Note: We checkout the repository at the branch that triggered the workflow
      # with the entire history to ensure to match PSR's release branch detection
      # and history evaluation.
      # However, we forcefully reset the branch to the workflow sha because it is
      # possible that the branch was updated while the workflow was running. This
      # prevents accidentally releasing un-evaluated changes.
      - name: Setup | Checkout Repository on Release Branch
        uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8  # v6.0.1
        with:
          ref: ${{ github.ref_name }}
          fetch-depth: 0

      - name: Setup | Force release branch to be at workflow sha
        run: |
          git reset --hard ${{ github.sha }}

      - name: Setup | Download Build Artifacts
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131  # v7.0.0
        id: artifact-download
        with:
          name: ${{ needs.validate.outputs.distribution-artifacts }}
          path: dist

      - name: Release | Bump Version in Docs
        if: needs.validate.outputs.new-release-is-prerelease == 'false'
        env:
          NEW_VERSION: ${{ needs.validate.outputs.new-release-version }}
          NEW_RELEASE_TAG: ${{ needs.validate.outputs.new-release-tag }}
        run: |
          python -m scripts.bump_version_in_docs
          git add docs/*

      - name: Release | Python Semantic Release
        id: release
        uses: python-semantic-release/python-semantic-release@02f2a5c74dbb6aa2989f10fc4af12cd8e6bf025f  # v10.5.2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          verbosity: 1
          build: false

      - name: Release | Add distribution artifacts to GitHub Release Assets
        uses: python-semantic-release/publish-action@948bb8fccc5e8072f2c52464b45c76a8bb3878e6  # v10.5.2
        if: steps.release.outputs.released == 'true'
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          tag: ${{ steps.release.outputs.tag }}

    outputs:
      released: ${{ steps.release.outputs.released || 'false' }}
      new-release-version: ${{ steps.release.outputs.version }}
      new-release-tag: ${{ steps.release.outputs.tag }}


  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    if: ${{ needs.release.outputs.released == 'true' && github.repository == 'python-semantic-release/python-semantic-release' }}
    needs:
      - validate
      - release

    environment:
      name: pypi
      url: https://pypi.org/project/python-semantic-release/

    permissions:
      # https://docs.github.com/en/rest/overview/permissions-required-for-github-apps?apiVersion=2022-11-28#metadata
      id-token: write  # needed for PyPI upload

    steps:
      - name: Setup | Download Build Artifacts
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131  # v7.0.0
        id: artifact-download
        with:
          name: ${{ needs.validate.outputs.distribution-artifacts }}
          path: dist

      # see https://docs.pypi.org/trusted-publishers/
      - name: Publish package distributions to PyPI
        id: pypi-publish
        uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e  # v1.13.0
        with:
          packages-dir: dist
          print-hash: true
          verbose: true
