mirror of
https://github.com/electron/electron.git
synced 2026-01-07 22:54:25 -05:00
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](1af3b93b68...8e8c483db8)
---
updated-dependencies:
- dependency-name: actions/checkout
dependency-version: 6.0.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
162 lines
6.3 KiB
YAML
162 lines
6.3 KiB
YAML
name: Audit CI on Branches
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
schedule:
|
|
# Run every 2 hours
|
|
- cron: '0 */2 * * *'
|
|
|
|
permissions: {}
|
|
|
|
jobs:
|
|
audit_branch_ci:
|
|
name: Audit CI on Branches
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
steps:
|
|
- name: Setup Node.js
|
|
uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
|
|
with:
|
|
node-version: 22.17.x
|
|
- name: Sparse checkout repository
|
|
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
|
|
with:
|
|
sparse-checkout: |
|
|
.
|
|
.github
|
|
.yarn
|
|
- run: yarn workspaces focus @electron/gha-workflows
|
|
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
|
id: audit-errors
|
|
with:
|
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
script: |
|
|
const { chdir } = require('node:process');
|
|
chdir('${{ github.workspace }}/.github/workflows');
|
|
|
|
const cache = require('@actions/cache');
|
|
const { ElectronVersions } = require('@electron/fiddle-core');
|
|
|
|
const runsWithErrors = [];
|
|
|
|
// Only want the most recent workflow run that wasn't skipped or cancelled
|
|
const isValidWorkflowRun = (run) => !['skipped', 'cancelled'].includes(run.conclusion);
|
|
|
|
const versions = await ElectronVersions.create({ ignoreCache: true });
|
|
const branches = versions.supportedMajors.map((branch) => `${branch}-x-y`);
|
|
|
|
for (const branch of ["main", ...branches]) {
|
|
const latestCheckRuns = new Map();
|
|
const allCheckRuns = await github.paginate(github.rest.checks.listForRef, {
|
|
owner: "electron",
|
|
repo: "electron",
|
|
ref: branch,
|
|
status: 'completed',
|
|
});
|
|
|
|
// Sort the check runs by completed_at so that multiple check runs on the
|
|
// same ref (like a scheduled workflow) only looks at the most recent one
|
|
for (const checkRun of allCheckRuns.filter(
|
|
(run) => !['skipped', 'cancelled'].includes(run.conclusion),
|
|
).sort((a, b) => new Date(b.completed_at) - new Date(a.completed_at))) {
|
|
if (!latestCheckRuns.has(checkRun.name)) {
|
|
latestCheckRuns.set(checkRun.name, checkRun);
|
|
}
|
|
}
|
|
|
|
// Check for runs which had error annotations
|
|
for (const checkRun of Array.from(latestCheckRuns.values())) {
|
|
if (checkRun.name === "Audit CI on Branches") {
|
|
continue; // Skip the audit workflow itself
|
|
}
|
|
|
|
const annotations = (await github.rest.checks.listAnnotations({
|
|
owner: "electron",
|
|
repo: "electron",
|
|
check_run_id: checkRun.id,
|
|
})).data ?? [];
|
|
|
|
if (
|
|
annotations.find(
|
|
({ annotation_level, message }) =>
|
|
annotation_level === "failure" &&
|
|
!message.startsWith("Process completed with exit code") &&
|
|
!message.startsWith("Response status code does not indicate success") &&
|
|
!message.startsWith("The hosted runner lost communication with the server") &&
|
|
!message.startsWith("Dependabot encountered an error performing the update") &&
|
|
!/Unable to make request/.test(message) &&
|
|
!/The requested URL returned error/.test(message),
|
|
)
|
|
) {
|
|
checkRun.hasErrorAnnotations = true;
|
|
} else {
|
|
continue;
|
|
}
|
|
|
|
// Check if this is a known failure from a previous audit run
|
|
const cacheKey = `check-run-error-annotations-${checkRun.id}`;
|
|
const cacheHit =
|
|
(await cache.restoreCache(['/dev/null'], cacheKey, undefined, {
|
|
lookupOnly: true,
|
|
})) !== undefined;
|
|
|
|
if (cacheHit) {
|
|
checkRun.isStale = true;
|
|
}
|
|
|
|
checkRun.branch = branch;
|
|
runsWithErrors.push(checkRun);
|
|
|
|
// Create a cache entry (only the name matters) to keep track of
|
|
// failures we've seen from previous runs to mark them as stale
|
|
if (!cacheHit) {
|
|
await cache.saveCache(['/dev/null'], cacheKey);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (runsWithErrors.length > 0) {
|
|
core.summary.addHeading('⚠️ Runs with Errors');
|
|
core.summary.addTable([
|
|
[
|
|
{ data: 'Branch', header: true },
|
|
{ data: 'Workflow Run', header: true },
|
|
{ data: 'Status', header: true },
|
|
],
|
|
...runsWithErrors
|
|
.sort(
|
|
(a, b) =>
|
|
a.branch.localeCompare(b.branch) ||
|
|
a.name.localeCompare(b.name),
|
|
)
|
|
.map((run) => [
|
|
run.branch,
|
|
`<a href="${run.html_url}">${run.name}</a>`,
|
|
run.isStale
|
|
? '📅 Stale'
|
|
: run.hasErrorAnnotations
|
|
? '⚠️ Errors'
|
|
: '✅ Succeeded',
|
|
]),
|
|
]);
|
|
|
|
// Set this as failed so it's easy to scan runs to find failures
|
|
if (runsWithErrors.find((run) => !run.isStale)) {
|
|
core.setOutput('errorsFound', true);
|
|
process.exitCode = 1;
|
|
}
|
|
} else {
|
|
core.summary.addRaw('🎉 No runs with errors');
|
|
}
|
|
|
|
await core.summary.write();
|
|
- name: Send Slack message if errors
|
|
if: ${{ always() && steps.audit-errors.outputs.errorsFound && github.ref == 'refs/heads/main' }}
|
|
uses: slackapi/slack-github-action@91efab103c0de0a537f72a35f6b8cda0ee76bf0a # v2.1.1
|
|
with:
|
|
payload: |
|
|
link: "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
|
|
webhook: ${{ secrets.CI_ERRORS_SLACK_WEBHOOK_URL }}
|
|
webhook-type: webhook-trigger
|