|
| 1 | +name: Reusable Issue Management Bot |
| 2 | + |
| 3 | +on: |
| 4 | + workflow_call: |
| 5 | + inputs: |
| 6 | + # --- Feedback Handler --- |
| 7 | + enable-feedback: |
| 8 | + description: "Enable the feedback label handler (add/remove feedback-label)." |
| 9 | + type: boolean |
| 10 | + required: false |
| 11 | + default: true |
| 12 | + feedback-label: |
| 13 | + description: "Label to add when a maintainer comments, and remove when a user comments." |
| 14 | + type: string |
| 15 | + required: false |
| 16 | + default: "await-user-feedback" |
| 17 | + |
| 18 | + # --- Auto-close on "Invalid" Label --- |
| 19 | + enable-invalid: |
| 20 | + description: 'Enable closing issues automatically when the "invalid" label is added.' |
| 21 | + type: boolean |
| 22 | + required: false |
| 23 | + default: true |
| 24 | + invalid-label-name: |
| 25 | + description: 'When this label is added, close the issue with a comment. (e.g., "invalid", "wontfix")' |
| 26 | + type: string |
| 27 | + required: false |
| 28 | + default: "invalid" |
| 29 | + invalid-label-comment: |
| 30 | + description: "The comment to post when closing an issue based on the label." |
| 31 | + type: string |
| 32 | + required: false |
| 33 | + default: "Hello @${{ github.event.issue.user.login }}. This issue is marked as `invalid` and closed. Please make sure you are reporting an issue and following the issue template." |
| 34 | + |
| 35 | + # --- Duplicate Marker --- |
| 36 | + enable-duplicate: |
| 37 | + description: "Enable the feature to mark issues as duplicates." |
| 38 | + type: boolean |
| 39 | + required: false |
| 40 | + default: true |
| 41 | + duplicate-label: |
| 42 | + description: "Label to add to an issue when it is marked as a duplicate." |
| 43 | + type: string |
| 44 | + required: false |
| 45 | + default: "duplicate" |
| 46 | + close-duplicates: |
| 47 | + description: "Whether to close the issue when it is marked as a duplicate." |
| 48 | + type: boolean |
| 49 | + required: false |
| 50 | + default: true |
| 51 | + |
| 52 | + # --- Stale Issue Management --- |
| 53 | + enable-stale: |
| 54 | + description: "Enable the job to check for and close stale issues." |
| 55 | + type: boolean |
| 56 | + required: false |
| 57 | + default: true |
| 58 | + stale-check-only-labels: |
| 59 | + description: "Only check issues with these labels for staleness. Comma-separated." |
| 60 | + type: string |
| 61 | + required: false |
| 62 | + default: "await-user-feedback" |
| 63 | + days-before-issue-stale: |
| 64 | + description: "Number of days of inactivity before an issue is marked as stale." |
| 65 | + type: number |
| 66 | + required: false |
| 67 | + default: 30 |
| 68 | + days-before-issue-close: |
| 69 | + description: "Number of days of inactivity after being marked stale before an issue is closed." |
| 70 | + type: number |
| 71 | + required: false |
| 72 | + default: 7 |
| 73 | + stale-issue-label: |
| 74 | + description: "The label to apply to stale issues." |
| 75 | + type: string |
| 76 | + required: false |
| 77 | + default: "stale" |
| 78 | + stale-issue-message: |
| 79 | + description: "The comment to post when an issue is marked as stale." |
| 80 | + type: string |
| 81 | + required: false |
| 82 | + default: "This issue is stale because it has been open for 30 days with no activity." |
| 83 | + close-issue-message: |
| 84 | + description: "The comment to post when a stale issue is closed." |
| 85 | + type: string |
| 86 | + required: false |
| 87 | + default: "This issue was closed because it has been inactive for 7 days since being marked as stale." |
| 88 | + |
| 89 | + # --- Lock Old Threads --- |
| 90 | + enable-lock: |
| 91 | + description: "Enable the job to lock old, inactive threads." |
| 92 | + type: boolean |
| 93 | + required: false |
| 94 | + default: true |
| 95 | + issue-inactive-days-before-lock: |
| 96 | + description: "Number of days of inactivity before a closed issue is locked." |
| 97 | + type: number |
| 98 | + required: false |
| 99 | + default: 30 |
| 100 | + exclude-lock-issue-labels: |
| 101 | + description: "Do not lock issues with these labels. Comma-separated." |
| 102 | + type: string |
| 103 | + required: false |
| 104 | + default: "keep-open" |
| 105 | + |
| 106 | + # secrets: |
| 107 | + # github-token: |
| 108 | + # description: "GITHUB_TOKEN for API requests." |
| 109 | + # required: true |
| 110 | + |
| 111 | +permissions: |
| 112 | + issues: write |
| 113 | + pull-requests: write |
| 114 | + # discussions: write |
| 115 | + |
| 116 | +jobs: |
| 117 | + feedback: |
| 118 | + runs-on: ubuntu-latest |
| 119 | + if: ${{ inputs.enable-feedback && github.event_name == 'issue_comment' }} |
| 120 | + steps: |
| 121 | + - name: Add "feedback" label |
| 122 | + if: ${{ contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association) }} |
| 123 | + uses: actions-cool/issues-helper@v3 |
| 124 | + with: |
| 125 | + actions: add-labels |
| 126 | + token: ${{ secrets.GITHUB_TOKEN }} |
| 127 | + issue-number: ${{ github.event.issue.number }} |
| 128 | + labels: ${{ inputs.feedback-label }} |
| 129 | + - name: Remove "feedback" label |
| 130 | + if: ${{ !contains(fromJson('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.comment.author_association) }} |
| 131 | + uses: actions-cool/issues-helper@v3 |
| 132 | + with: |
| 133 | + actions: remove-labels |
| 134 | + token: ${{ secrets.GITHUB_TOKEN }} |
| 135 | + issue-number: ${{ github.event.issue.number }} |
| 136 | + labels: ${{ inputs.feedback-label }} |
| 137 | + |
| 138 | + invalid: |
| 139 | + name: Close issue on "invalid" label |
| 140 | + if: ${{ inputs.enable-invalid && github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == inputs.invalid-label-name }} |
| 141 | + runs-on: ubuntu-latest |
| 142 | + steps: |
| 143 | + - uses: actions-cool/issues-helper@v3 |
| 144 | + with: |
| 145 | + actions: close-issue, create-comment |
| 146 | + token: ${{ secrets.GITHUB_TOKEN }} |
| 147 | + body: ${{ inputs.invalid-label-comment }} |
| 148 | + |
| 149 | + duplicate: |
| 150 | + name: Mark issue as duplicate |
| 151 | + if: ${{ inputs.enable-duplicate && github.event_name == 'issue_comment' }} |
| 152 | + runs-on: ubuntu-latest |
| 153 | + steps: |
| 154 | + - uses: actions-cool/issues-helper@v3 |
| 155 | + with: |
| 156 | + actions: mark-duplicate |
| 157 | + token: ${{ secrets.GITHUB_TOKEN }} |
| 158 | + labels: ${{ inputs.duplicate-label }} |
| 159 | + close-issue: ${{ inputs.close-duplicates }} |
| 160 | + |
| 161 | + stale: |
| 162 | + name: Handle Stale Issues |
| 163 | + runs-on: ubuntu-latest |
| 164 | + if: ${{ inputs.enable-stale && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') }} |
| 165 | + permissions: |
| 166 | + issues: write |
| 167 | + pull-requests: write |
| 168 | + steps: |
| 169 | + - name: Close stale issues |
| 170 | + uses: actions/stale@v10 |
| 171 | + with: |
| 172 | + repo-token: ${{ secrets.GITHUB_TOKEN }} |
| 173 | + only-labels: ${{ inputs.stale-check-only-labels }} |
| 174 | + days-before-issue-stale: ${{ inputs.days-before-issue-stale }} |
| 175 | + days-before-issue-close: ${{ inputs.days-before-issue-close }} |
| 176 | + stale-issue-label: ${{ inputs.stale-issue-label }} |
| 177 | + stale-issue-message: ${{ inputs.stale-issue-message }} |
| 178 | + close-issue-message: ${{ inputs.close-issue-message }} |
| 179 | + days-before-pr-stale: -1 |
| 180 | + days-before-pr-close: -1 |
| 181 | + |
| 182 | + lock: |
| 183 | + name: Lock Old Threads |
| 184 | + runs-on: ubuntu-latest |
| 185 | + if: ${{ inputs.enable-lock && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') }} |
| 186 | + permissions: |
| 187 | + issues: write |
| 188 | + pull-requests: write |
| 189 | + steps: |
| 190 | + - name: Lock closed threads |
| 191 | + uses: dessant/lock-threads@v5 |
| 192 | + with: |
| 193 | + github-token: ${{ secrets.GITHUB_TOKEN }} |
| 194 | + issue-inactive-days: ${{ inputs.issue-inactive-days-before-lock }} |
| 195 | + exclude-any-issue-labels: ${{ inputs.exclude-lock-issue-labels }} |
| 196 | + pr-inactive-days: 30 |
0 commit comments