name: Close Unauthorized Issues on: workflow_dispatch: issues: types: [opened] jobs: close-unauthorized-issues: runs-on: ubuntu-latest permissions: issues: write steps: # XXX: This *could* be done in Bash by abusing GitHub's own tool to interact with its API # but that's too much of a hack, and we'll be adding a layer of abstraction. github-script # is a workflow that eases interaction with GitHub API in the workflow run context. - name: "Close 'unauthorized' issues" uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const ALLOWED_USERS = ['vaxerski', 'fufexan', 'NotAShelf']; const CLOSING_COMMENT = 'Users are no longer allowed to open issues themselves, please open a discussion instead.\n\nPlease see the [wiki](https://wiki.hyprland.org/Contributing-and-Debugging/Issue-Guidelines/) on why this is the case.\n\nWe are volunteers, and we need your cooperation to make the best software we can. Thank you for understanding! ❤️\n\n[Open a discussion here](https://github.com/hyprwm/Hyprland/discussions)'; async function closeUnauthorizedIssue(issueNumber, userName) { if (ALLOWED_USERS.includes(userName)) { console.log(`Issue #${issueNumber} - Created by authorized user ${userName}`); return; } console.log(`Issue #${issueNumber} - Unauthorized, closing`); await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, state: 'closed', state_reason: 'not_planned' }); await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: issueNumber, body: CLOSING_COMMENT }); } if (context.eventName === 'issues' && context.payload.action === 'opened') { // Direct access to the issue that triggered the workflow const issue = context.payload.issue; // Skip if this is a PR if (issue.pull_request) { console.log(`Issue #${issue.number} - Skipping, this is a pull request`); return; } // Process the single issue that triggered the workflow await closeUnauthorizedIssue(issue.number, issue.user.login); } else { // For manual runs, we need to handle pagination async function* fetchAllOpenIssues() { let page = 1; let hasNextPage = true; while (hasNextPage) { const response = await github.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, state: 'open', per_page: 100, page: page }); if (response.data.length === 0) { hasNextPage = false; } else { for (const issue of response.data) { yield issue; } page++; } } } // Process issues one by one for await (const issue of fetchAllOpenIssues()) { try { // Skip pull requests if (issue.pull_request) { console.log(`Issue #${issue.number} - Skipping, this is a pull request`); continue; } await closeUnauthorizedIssue(issue.number, issue.user.login); } catch (error) { console.error(`Error processing issue #${issue.number}: ${error.message}`); } } }