1name: �� Auto set milestone on PR
2
3on:
4  pull_request_target:
5    types:
6      - opened
7
8env:
9  QGIS_MAJOR_VERSION: 3
10
11jobs:
12  pr-without-milestones:
13    runs-on: ubuntu-latest
14    if: github.repository == 'qgis/QGIS'
15    steps:
16      # list the tags and milestones
17      - uses: octokit/graphql-action@v2.x
18        id: graphql_request
19        with:
20          query: |
21            query {
22              repository(owner: "qgis", name: "QGIS") {
23                pullRequests(states: OPEN, last: 100) {
24                  edges {
25                    node {
26                      number
27                      title
28                      milestone {
29                        number
30                      }
31                      baseRef {
32                        name
33                      }
34                    }
35                  }
36                }
37                milestones(orderBy: {field: CREATED_AT, direction: DESC}, first: 50) {
38                  edges {
39                    node {
40                      title
41                      number
42                    }
43                  }
44                }
45                refs(refPrefix: "refs/tags/", orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: 30) {
46                  edges {
47                    node {
48                      name
49                    }
50                  }
51                }
52              }
53            }
54        env:
55          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
56
57      # take the first unprocessed PR and determine if some remain
58      - name: Filter PR to check
59        id: extract_data
60        env:
61          JSON_DATA: ${{ steps.graphql_request.outputs.data }}
62        run: |
63          # get PRs without milestones
64          PRS_TO_PROCESS=$(echo "${JSON_DATA}" | jq '.repository.pullRequests.edges[] | select( .node.milestone.number | not ) | .node.number')
65
66          NUMBER_OF_PRS=$(echo "${PRS_TO_PROCESS}" | jq -s '. | length')
67          echo "NUMBER_OF_PRS: ${NUMBER_OF_PRS}"
68          # early exit
69          [[ ${NUMBER_OF_PRS} == 0 ]] && echo "::set-output name=has_milestone_to_set::0" && exit 0
70
71          # Take the first
72          PR_NUMBER=$(echo "${PRS_TO_PROCESS}" | jq -s '. | first')
73          echo "PR_NUMBER: ${PR_NUMBER}"
74
75          # Not used for now
76          RE_RUN_JOB=$(echo "${JSON_DATA}" | jq -s '. | length > 1')
77          echo "RE_RUN_JOB: ${RE_RUN_JOB}"
78
79          # Get the base branch
80          BASE_BRANCH=$(echo "${JSON_DATA}" | jq -r ".repository.pullRequests.edges[] | select( .node.number == ${PR_NUMBER} ) | .node.baseRef.name")
81          echo "BASE_BRANCH: ${BASE_BRANCH}"
82
83          # master => NOTHING, release_3-10 => _10
84          MINOR_VERSION=$(echo ${BASE_BRANCH} | sed -r -e 's/^release-[0-9]_([0-9]+)/_\1/;t;d')
85          echo "MINOR_VERSION: ${MINOR_VERSION}"
86
87          # get the max release from the tags
88          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')
89          echo "MAX_RELEASE: ${MAX_RELEASE}"
90
91          # increase the number to get milestone: round+2 for master, +0.1 for release_xxx branches
92          INCREASE_OPERATION=$([[ -z ${MINOR_VERSION} ]] && echo "${MAX_RELEASE%.*} + 2.0" || echo "${MAX_RELEASE} + 0.1" )
93          echo "INCREASE_OPERATION: ${INCREASE_OPERATION}"
94          MILESTONE_TITLE="${QGIS_MAJOR_VERSION}."$(echo "${INCREASE_OPERATION}" | bc)
95          echo "MILESTONE_TITLE: ${MILESTONE_TITLE}"
96
97          MILESTONE_NUMBER=$(echo "${JSON_DATA}" | jq ".repository.milestones.edges[] | select( .node.title == \"${MILESTONE_TITLE}\" ) | .node.number")
98          echo "MILESTONE_NUMBER: ${MILESTONE_NUMBER}"
99
100          HAS_MILESTONE_TO_CREATE=$([[ -z ${MILESTONE_NUMBER} ]] && echo "1" || echo "0" )
101          echo "HAS_MILESTONE_TO_CREATE: ${HAS_MILESTONE_TO_CREATE}"
102
103          echo "::set-output name=has_milestone_to_set::1"
104          echo "::set-output name=pr_number::${PR_NUMBER}"
105          echo "::set-output name=milestone_title::${MILESTONE_TITLE}"
106          echo "::set-output name=milestone_number::${MILESTONE_NUMBER}"
107          echo "::set-output name=has_milestone_to_create::${HAS_MILESTONE_TO_CREATE}"
108
109      # create the milestone if needed
110      - name: Create milestone if needed
111        id: create_milestone
112        if: steps.extract_data.outputs.has_milestone_to_set == 1 && steps.extract_data.outputs.has_milestone_to_create == 1
113        uses: octokit/request-action@v2.x
114        with:
115          route: POST /repos/qgis/QGIS/milestones
116          title: ${{ steps.extract_data.outputs.milestone_title }}
117        env:
118          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
119
120      # Compute the milestone number
121      - name: Compute milestone number from existing or created
122        id: compute_milestone
123        if: always() && steps.extract_data.outputs.has_milestone_to_set == 1
124        env:
125          MILESTONE_NUMBER_EXISTING: ${{ steps.extract_data.outputs.milestone_number }}
126          MILESTONE_NUMBER_CREATED_JSON: ${{ steps.create_milestone.outputs.data }}
127        run: |
128          FINAL_MILESTONE_NUMBER=$([[ -n ${MILESTONE_NUMBER_EXISTING} ]] && echo "${MILESTONE_NUMBER_EXISTING}" || echo $(echo "${MILESTONE_NUMBER_CREATED_JSON}" | jq .number ))
129          echo "FINAL_MILESTONE_NUMBER: ${FINAL_MILESTONE_NUMBER}"
130          echo "::set-output name=milestone_number::${FINAL_MILESTONE_NUMBER}"
131
132      # update PR with milestone
133      - name: update PR milestone
134        if: steps.extract_data.outputs.has_milestone_to_set == 1
135        uses: octokit/request-action@v2.x
136        env:
137          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
138        with:
139          route: PATCH /repos/qgis/QGIS/issues/:pull_number
140          pull_number: ${{ steps.extract_data.outputs.pr_number }}
141          milestone: ${{ steps.compute_milestone.outputs.milestone_number }}
142