infra/terraform/modules/workflow_files/periodic-reporter.yaml (129 lines of code) (raw):

# Copyright 2023-2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # NOTE: This file is automatically generated from: # https://github.com/GoogleCloudPlatform/cloud-foundation-toolkit/blob/main/infra/terraform/modules/workflow_files/periodic-reporter.yaml name: 'reporter' on: schedule: # 2 hours after scheduled periodic and once again in the evening - cron: '0 5,17 * * *' workflow_dispatch: jobs: report: if: github.repository_owner == 'GoogleCloudPlatform' || github.repository_owner == 'terraform-google-modules' permissions: issues: 'write' runs-on: 'ubuntu-latest' steps: - uses: 'actions/github-script@v7' with: script: |- // label for all issues opened by reporter const periodicLabel = 'periodic-failure'; // check if any reporter opened any issues previously const prevIssues = await github.paginate(github.rest.issues.listForRepo, { ...context.repo, state: 'open', creator: 'github-actions[bot]', labels: [periodicLabel] }); // createOrCommentIssue creates a new issue or comments on an existing issue. const createOrCommentIssue = async function (title, txt) { if (prevIssues.length < 1) { console.log('no previous issues found, creating one'); await github.rest.issues.create({ ...context.repo, title: title, body: txt, labels: [periodicLabel] }); return; } if (prevIssues.length > 1) { console.warn( `found ${prevIssues.length} issues but only adding comment to ${prevIssues[0].html_url}` ); } console.log( `found previous issue ${prevIssues[0].html_url}, adding comment` ); await github.rest.issues.createComment({ ...context.repo, issue_number: prevIssues[0].number, body: txt }); }; // updateAndCloseIssues comments on any existing issues and closes them. No-op if no issue exists. const updateAndCloseIssues = async function (txt) { if (prevIssues.length < 1) { console.log('no previous issues found, skipping close'); return; } for (const prevIssue of prevIssues) { console.log(`found previous issue ${prevIssue.html_url}, adding comment`); await github.rest.issues.createComment({ ...context.repo, issue_number: prevIssue.number, body: txt }); console.log(`closing ${prevIssue.html_url}`); await github.rest.issues.update({ ...context.repo, issue_number: prevIssue.number, body: txt, state: 'closed' }); } }; // Find status of check runs. // We will find check runs for each commit and then filter for the periodic. // Checks API only allows for ref and if we use main there could be edge cases where // the check run happened on a SHA that is different from head. const commits = await github.paginate(github.rest.repos.listCommits, { ...context.repo }); var foundCheck = false; let periodicCheck = {}; for (const commit of commits) { console.log( `checking runs at ${commit.html_url}: ${commit.commit.message}` ); const checks = await github.rest.checks.listForRef({ ...context.repo, ref: commit.sha }); // find runs for this commit for (const check of checks.data.check_runs) { console.log(`found run ${check.name} for ${commit.html_url}`); if (check.name.includes('periodic-int-trigger')) { foundCheck = true; periodicCheck = check; break; } } if (foundCheck) { if ( periodicCheck.status === 'completed' && periodicCheck.conclusion === 'success' ) { updateAndCloseIssues( `[Passing periodic](${periodicCheck.html_url}) at ${commit.html_url}. Closing this issue.` ); } else if (periodicCheck.status === 'in_progress') { console.log( `Check is pending ${periodicCheck.html_url} for ${commit.html_url}. Retry again later.` ); } // error case else { createOrCommentIssue( 'Failing periodic', `[Failing periodic](${periodicCheck.html_url}) at ${commit.html_url}.` ); } // exit early as check was found return; } } // no periodic-int-trigger checks found across all commits, report it createOrCommentIssue( 'Missing periodic', `Periodic test has not run in the past 24hrs. Last checked from ${ commits[0].html_url } to ${commits[commits.length - 1].html_url}.` );