aboutsummaryrefslogtreecommitdiff
path: root/.github/workflows/label-next-release-issues.yml
blob: 3480089bf0b9eda03adeee62b0e2e80729f6033f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
name: Close pending-release issues

on:
  push:
    branches: [master]

permissions:
  contents: read
  issues: write

env:
  NEXT_RELEASE_LABEL: pending-release

jobs:
  close:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
        with:
          fetch-depth: 0
          persist-credentials: false

      - name: Close issues referenced by pushed commits
        shell: bash
        env:
          GH_TOKEN: ${{ secrets.KANGAL_GITHUB_TOKEN }}
        run: |
          set -euo pipefail

          echo "Using GitHub token for $(gh api user --jq .login)."

          BEFORE="${{ github.event.before }}"
          AFTER="${{ github.sha }}"
          ZERO_SHA="0000000000000000000000000000000000000000"

          if [ "$BEFORE" = "$ZERO_SHA" ]; then
            RANGE_ARGS=(-1 "$AFTER")
            echo "Scanning latest commit $AFTER for refs #<issue> lines."
          else
            RANGE_ARGS=("$BEFORE..$AFTER")
            echo "Scanning pushed commits in $BEFORE..$AFTER for refs #<issue> lines."
          fi

          mapfile -t ISSUES < <(
            git log --format=%b "${RANGE_ARGS[@]}" \
              | perl -ne 'print "$1\n" if /^\s*refs\s+#([0-9]+)\s*$/i' \
              | sort -nu
          )

          if [ "${#ISSUES[@]}" -eq 0 ]; then
            echo "No issue refs found."
            exit 0
          fi

          if ! gh api "repos/${GITHUB_REPOSITORY}/labels/${NEXT_RELEASE_LABEL}" >/dev/null 2>&1; then
            gh api -X POST "repos/${GITHUB_REPOSITORY}/labels" \
              -f name="$NEXT_RELEASE_LABEL" \
              -f color="5319E7" \
              -f description="Implemented on master and pending a published release." \
              >/dev/null \
              || gh api "repos/${GITHUB_REPOSITORY}/labels/${NEXT_RELEASE_LABEL}" >/dev/null
          fi

          PENDING_COMMENT_MARKER="<!-- herdr:pending-release -->"
          PENDING_COMMENT="${PENDING_COMMENT_MARKER}"$'\n'"Implemented on master and queued for the next release. This is not available in a published Herdr release yet."

          issue_has_comment_marker() {
            local issue="$1"
            local marker="$2"
            local comments
            if ! comments="$(gh api --paginate "repos/${GITHUB_REPOSITORY}/issues/${issue}/comments?per_page=100" --jq '.[].body')"; then
              echo "::warning::Could not read comments for issue #$issue."
              return 2
            fi
            grep -F -- "$marker" >/dev/null <<<"$comments"
          }

          for issue in "${ISSUES[@]}"; do
            echo "Checking #$issue"
            if ! data="$(gh api "repos/${GITHUB_REPOSITORY}/issues/${issue}")"; then
              echo "::warning::Could not read issue #$issue; skipping."
              continue
            fi

            if jq -e 'has("pull_request")' <<<"$data" >/dev/null; then
              echo "Skipping #$issue because it is a pull request."
              continue
            fi

            ISSUE_STATE="$(jq -r '.state' <<<"$data")"

            HAS_NEXT_RELEASE_LABEL="$(jq -r --arg label "$NEXT_RELEASE_LABEL" 'any(.labels[].name; . == $label)' <<<"$data")"
            if [ "$HAS_NEXT_RELEASE_LABEL" != "true" ]; then
              if ! gh issue edit "$issue" --repo "$GITHUB_REPOSITORY" --add-label "$NEXT_RELEASE_LABEL"; then
                echo "::warning::Could not label issue #$issue."
                continue
              fi
            fi

            MARKER_STATUS=0
            issue_has_comment_marker "$issue" "$PENDING_COMMENT_MARKER" || MARKER_STATUS="$?"
            if [ "$MARKER_STATUS" -eq 2 ]; then
              continue
            fi
            HAS_PENDING_COMMENT="false"
            if [ "$MARKER_STATUS" -eq 0 ]; then
              HAS_PENDING_COMMENT="true"
            fi

            if [ "$ISSUE_STATE" = "open" ]; then
              if [ "$HAS_PENDING_COMMENT" = "true" ]; then
                if ! gh issue close "$issue" --repo "$GITHUB_REPOSITORY" --reason completed; then
                  echo "::warning::Could not close issue #$issue."
                  continue
                fi
              elif ! gh issue close "$issue" --repo "$GITHUB_REPOSITORY" --reason completed --comment "$PENDING_COMMENT"; then
                echo "::warning::Could not close issue #$issue."
                continue
              fi
            elif [ "$HAS_PENDING_COMMENT" != "true" ]; then
              if ! gh issue comment "$issue" --repo "$GITHUB_REPOSITORY" --body "$PENDING_COMMENT"; then
                echo "::warning::Could not comment on closed issue #$issue."
                continue
              fi
            else
              echo "Skipping pending-release comment for #$issue because it already exists."
            fi
          done