Close issues with no tasks and a specific label #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Close issues with no tasks and a specific label | |
on: | |
schedule: | |
- cron: '0 0 * * 0' # Runs every Sunday at midnight | |
repository_dispatch: | |
types: close-issues-ocwm | |
jobs: | |
close-issues: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up Node 20 | |
uses: actions/setup-node@v4 | |
with: | |
node-version: '20' | |
- name: Get Token | |
uses: actions/create-github-app-token@v1 | |
id: get_workflow_token | |
with: | |
app-id: ${{ vars.APP_ID }} | |
private-key: ${{ secrets.PRIVATE_KEY }} | |
- name: Install dependencies | |
run: npm install @octokit/[email protected] | |
- name: Close issues | |
env: | |
MY_TOKEN: ${{ steps.get_workflow_token.outputs.token }} | |
MY_LABEL: ${{ vars.OCWM_LABEL }} | |
OWNER: ${{ vars.ORGANISATION }} | |
REPO_NAMES: ${{ vars.REPOSITORIES }} | |
uses: actions/github-script@v7 | |
with: | |
github-token: ${{ secrets.GITHUB_TOKEN }} | |
script: | | |
const octokit = require('@octokit/core').Octokit | |
const mygithub = new octokit({ | |
request: { fetch: fetch,}, | |
auth: process.env.MY_TOKEN | |
}); | |
const label = process.env.MY_LABEL; | |
const sevenDaysAgo = new Date(); | |
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); | |
const dateString = sevenDaysAgo.toISOString().split('T')[0]; | |
const pattern = `label:"${label}" is:open created:<${dateString} repo:${process.env.REPO_NAMES} org:${process.env.OWNER}`; | |
try { | |
const response = await mygithub.request('GET /search/issues', { | |
q: pattern, | |
per_page: 100, | |
}); | |
const issues = response.data.items; | |
console.log(`Number of issues found: ${issues.length}`); | |
for (const issue of issues) { | |
console.log('Issue:' + JSON.stringify(issue)); | |
const repo = issue.repository_url.split('/').slice(-1)[0]; | |
const issue_number = issue.number; | |
console.log('Repo:' + repo); | |
const taskListRegex = /^\s*- \[[\sX]\]\s+/gm; | |
const incompleteTaskRegex = /-\s+\[[ ]\]\s+.+/g; | |
const hasTasks = taskListRegex.test(issue.body); | |
const hasIncompleteTasks = incompleteTaskRegex.test(issue.body); | |
if (!hasTasks || !hasIncompleteTasks) { | |
console.log(`Closing issue: ${issue.number}`); | |
try { | |
await mygithub.request(`POST /repos/${process.env.OWNER}/${repo}/issues/${issue.number}/comments`, { | |
body: 'Closing this issue as all tasks are completed. Thanks for your contributions!', | |
}); | |
console.log(`POST /repos/${process.env.OWNER}/${repo}/issues/${issue.number}/comments`); | |
await mygithub.request(`PATCH /repos/${process.env.OWNER}/${repo}/issues/${issue.number}`, { | |
state: 'closed', | |
}); | |
console.log(`PATCH /repos/${process.env.OWNER}/${repo}/issues/${issue.number}`); | |
console.log(`Issue updated`); | |
} catch (error) { | |
console.error('Error occurred updating issue:', error); | |
process.exit(1); | |
} | |
} | |
} | |
} catch (error) { | |
console.error('Error occurred:', error.message); | |
process.exit(1); | |
} |