Code change:
<ins> name: DevTools Check for bug repro on: issues: types: [opened, edited] issue_comment: types: [created, edited] jobs: check-repro: runs-on: ubuntu-latest steps: - uses: actions/github-script@v3 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const URL_REGEXP = /### Website or app[rn]+([^#]+)###/m; const REPRO_STEPS_REGEXP = /### Repro steps[rn]+([^#]+)###/m; const LABEL_NEEDS_MORE_INFORMATION = "Resolution: Needs More Information"; const LABEL_UNCONFIRMED = "Status: Unconfirmed"; function debug(...args) { core.info(args.map(JSON.stringify).join(' ')); } if (context.payload.comment) { debug('Ignoring comment update.'); return; } const user = context.payload.sender.login; const issue = context.payload.issue; const body = issue.body; const urlMatch = body.match(URL_REGEXP); const reproStepsMatch = body.match(REPRO_STEPS_REGEXP); const url = urlMatch !== null ? urlMatch[1].trim() : null; const reproSteps = reproStepsMatch !== null ? reproStepsMatch[1].trim() : null; if (!url || !reproSteps) { debug('This issue is not a DevTools bug report.'); return; } debug(`found URL "${url}"`); debug(`found repro steps "${reproSteps}"`); function formatComment(comment) { return comment .split("n") .map((line) => line.trim()) .join("n") .trim(); } async function getGitHubActionComments() { debug(`Loading existing comments...`); const comments = await github.issues.listComments({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); return comments.data.filter(comment => { debug(`comment by user: "${comment.user.login}"`); return comment.user.login === 'github-actions[bot]'; }); } async function getIssueLabels() { const issues = await github.issues.listLabelsOnIssue({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, }); return issues.data; } async function closeWithComment(comment) { if (issue.state !== 'open') { debug(`Issue is not open`); return; } const labels = await getIssueLabels(); const label = labels.find(label => label.name === LABEL_UNCONFIRMED); if (!label) { debug(`Issue was not opened via DevTools bug report template`); return; } const comments = await getGitHubActionComments(); if (comments.length > 0) { debug(`Already commented on issue; won't comment again`); return; } debug(`Missing required information`); await github.issues.addLabels({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, labels: [LABEL_NEEDS_MORE_INFORMATION], }); await github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: formatComment(comment), }); await github.issues.update({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, state: 'closed', }); } async function openWithComment(comment) { if (issue.state !== 'closed') { debug(`Issue is already open`); return; } const labels = await getIssueLabels(); const label = labels.find(label => label.name === LABEL_NEEDS_MORE_INFORMATION); if (!label) { debug(`Issue was not tagged as needs information`); return; } const comments = await getGitHubActionComments(); if (comments.length === 0) { debug(`Issue was closed by someone else; won't reopen`); return; } debug(`Re-opening closed issue`); await github.issues.removeLabel({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, name: LABEL_NEEDS_MORE_INFORMATION, }); await github.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: formatComment(comment), }); await github.issues.update({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, state: 'open', }); } const PROBABLY_NOT_A_URL_REGEX = /(^Chrome$|^Firefox$| Website)/i; const COMMENT_HEADER = ` @${user}: We're sorry you've seen this error. ❤️ `.trim(); const COMMENT_FOOTER = ` Please help us by providing a link to a CodeSandbox (https://codesandbox.io/s/new), a repository on GitHub, or a minimal code example that reproduces the problem. (Screenshots or videos can also be helpful if they help provide context on how to repro the bug.) Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve Issues without repros are automatically closed but we will re-open if you update with repro info. `.trim(); if (url.includes("/localhost")) { closeWithComment(` ${COMMENT_HEADER} Unfortunately the URL you provided ("localhost") is not publicly accessible. (This means that we will not be able to reproduce the problem you're reporting.) ${COMMENT_FOOTER} `); } else if (url.length < 10 || url.match(PROBABLY_NOT_A_URL_REGEX)) { closeWithComment(` ${COMMENT_HEADER} It looks like you forgot to specify a valid URL. (This means that we will not be able to reproduce the problem you're reporting.) ${COMMENT_FOOTER} `); } else if (reproSteps.length < 25) { closeWithComment(` ${COMMENT_HEADER} Unfortunately, it doesn't look like this issue has enough info for one of us to reproduce and fix it though. ${COMMENT_FOOTER} `); } else { openWithComment(` Thank you for providing repro steps! Re-opening issue now for triage. `); } </ins>

Related discussion:
text: Many of the issues created with the with the  template are missing repro information (e.g. a "localhost" or otherwise invalid URL, missing or no repro description). I usually have to review, label, comment, and close this by hand. It would be nice if we had an automated action that checked: Was the issue made with the  template? Does the URL section have an invalid URL (e.g. "localhost" or "company website") Does the repro steps section have invalid steps (e.g. "don't know") For issues that pass all of the above text, the bot should: Assign the "Resolution: Needs More Information" label Close the issue Leave a comment explaining that repro information was missing and that we'll re-open it if information is provided
Related action:
Going to play with this idea here: