name: 📅 Auto set milestone on PR

on:
  pull_request_target:
    types:
      - opened

env:
  QGIS_MAJOR_VERSION: 3

jobs:
  pr-without-milestones:
    runs-on: ubuntu-latest
    if: github.repository == 'qgis/QGIS'
    steps:
      # list the tags and milestones
      - uses: octokit/graphql-action@v2.x
        id: graphql_request
        with:
          query: |
            query {
              repository(owner: "qgis", name: "QGIS") {
                pullRequests(states: OPEN, last: 100) {
                  edges {
                    node {
                      number
                      title
                      milestone {
                        number
                      }
                      baseRef {
                        name
                      }
                    }
                  }
                }
                milestones(orderBy: {field: CREATED_AT, direction: DESC}, first: 50) {
                  edges {
                    node {
                      title
                      number
                    }
                  }
                }
                refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 30) {
                  edges {
                    node {
                      name
                    }
                  }
                }
              }
            }
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # take the first unprocessed PR and determine if some remain
      - name: Filter PR to check
        id: extract_data
        env:
          JSON_DATA: ${{ steps.graphql_request.outputs.data }}
        run: |
          # get PRs without milestones
          PRS_TO_PROCESS=$(echo "${JSON_DATA}" | jq '.repository.pullRequests.edges[] | select( .node.milestone.number | not ) | .node.number')

          NUMBER_OF_PRS=$(echo "${PRS_TO_PROCESS}" | jq -s '. | length')
          echo "NUMBER_OF_PRS: ${NUMBER_OF_PRS}"
          # early exit
          [[ ${NUMBER_OF_PRS} == 0 ]] && echo "::set-output name=has_milestone_to_set::0" && exit 0

          # Take the first
          PR_NUMBER=$(echo "${PRS_TO_PROCESS}" | jq -s '. | first')
          echo "PR_NUMBER: ${PR_NUMBER}"

          # Not used for now
          RE_RUN_JOB=$(echo "${JSON_DATA}" | jq -s '. | length > 1')
          echo "RE_RUN_JOB: ${RE_RUN_JOB}"

          # Get the base branch
          BASE_BRANCH=$(echo "${JSON_DATA}" | jq -r ".repository.pullRequests.edges[] | select( .node.number == ${PR_NUMBER} ) | .node.baseRef.name")
          echo "BASE_BRANCH: ${BASE_BRANCH}"

          # master => NOTHING, release_3-10 => _10
          MINOR_VERSION=$(echo ${BASE_BRANCH} | sed -r -e 's/^release-[0-9]_([0-9]+)/_\1/;t;d')
          echo "MINOR_VERSION: ${MINOR_VERSION}"

          # get the max release from the tags
          MAX_RELEASE=$(echo "${JSON_DATA}" | jq ".repository.refs.edges[].node.name | select( . | test(\"^final-${QGIS_MAJOR_VERSION}${MINOR_VERSION}\") ) | sub(\"^final-${QGIS_MAJOR_VERSION}_(?<m>[0-9]+)_(?<p>.)\"; .m+\".\"+.p) | tonumber" | jq -s '. | max')
          echo "MAX_RELEASE: ${MAX_RELEASE}"

          # increase the number to get milestone: round+2 for master, +0.1 for release_xxx branches
          INCREASE_OPERATION=$([[ -z ${MINOR_VERSION} ]] && echo "${MAX_RELEASE%.*} + 2.0" || echo "${MAX_RELEASE} + 0.1" )
          echo "INCREASE_OPERATION: ${INCREASE_OPERATION}"
          MILESTONE_TITLE="${QGIS_MAJOR_VERSION}."$(echo "${INCREASE_OPERATION}" | bc)
          echo "MILESTONE_TITLE: ${MILESTONE_TITLE}"

          MILESTONE_NUMBER=$(echo "${JSON_DATA}" | jq ".repository.milestones.edges[] | select( .node.title == \"${MILESTONE_TITLE}\" ) | .node.number")
          echo "MILESTONE_NUMBER: ${MILESTONE_NUMBER}"

          HAS_MILESTONE_TO_CREATE=$([[ -z ${MILESTONE_NUMBER} ]] && echo "1" || echo "0" )
          echo "HAS_MILESTONE_TO_CREATE: ${HAS_MILESTONE_TO_CREATE}"

          echo "::set-output name=has_milestone_to_set::1"
          echo "::set-output name=pr_number::${PR_NUMBER}"
          echo "::set-output name=milestone_title::${MILESTONE_TITLE}"
          echo "::set-output name=milestone_number::${MILESTONE_NUMBER}"
          echo "::set-output name=has_milestone_to_create::${HAS_MILESTONE_TO_CREATE}"

      # create the milestone if needed
      - name: Create milestone if needed
        id: create_milestone
        if: steps.extract_data.outputs.has_milestone_to_set == 1 && steps.extract_data.outputs.has_milestone_to_create == 1
        uses: octokit/request-action@v2.x
        with:
          route: POST /repos/qgis/QGIS/milestones
          title: ${{ steps.extract_data.outputs.milestone_title }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      # Compute the milestone number
      - name: Compute milestone number from existing or created
        id: compute_milestone
        if: always() && steps.extract_data.outputs.has_milestone_to_set == 1
        env:
          MILESTONE_NUMBER_EXISTING: ${{ steps.extract_data.outputs.milestone_number }}
          MILESTONE_NUMBER_CREATED_JSON: ${{ steps.create_milestone.outputs.data }}
        run: |
          FINAL_MILESTONE_NUMBER=$([[ -n ${MILESTONE_NUMBER_EXISTING} ]] && echo "${MILESTONE_NUMBER_EXISTING}" || echo $(echo "${MILESTONE_NUMBER_CREATED_JSON}" | jq .number ))
          echo "FINAL_MILESTONE_NUMBER: ${FINAL_MILESTONE_NUMBER}"
          echo "::set-output name=milestone_number::${FINAL_MILESTONE_NUMBER}"

      # update PR with milestone
      - name: update PR milestone
        if: steps.extract_data.outputs.has_milestone_to_set == 1
        uses: octokit/request-action@v2.x
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          route: PATCH /repos/qgis/QGIS/issues/:pull_number
          pull_number: ${{ steps.extract_data.outputs.pr_number }}
          milestone: ${{ steps.compute_milestone.outputs.milestone_number }}
