Check required jobs #290
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: Check required jobs | |
# This workflow is triggered when a workflow run for the CI is completed. | |
# It checks if the "All required checks done" job was actually successful | |
# (and not just skipped) and creates a check run if that is the case. The | |
# check run can be used to protect the main branch from being merged if the | |
# CI is not passing. We need to use a GitHub app token to create the check | |
# run because otherwise the check suite will be assigned to the first workflow | |
# run for the CI, which might not be the latest one. See | |
# https://github.com/orgs/community/discussions/24616#discussioncomment-6088422 | |
# for more details. | |
on: | |
workflow_run: | |
workflows: [CI] | |
permissions: | |
actions: read | |
checks: write | |
jobs: | |
required-jobs: | |
name: Check required jobs | |
if: ${{ !github.event.repository.fork }} | |
environment: create-check | |
runs-on: ubuntu-latest | |
steps: | |
- name: Generate an app token | |
id: app-token | |
uses: actions/create-github-app-token@v1 | |
with: | |
app-id: ${{ secrets.APP_ID }} | |
private-key: ${{ secrets.APP_PRIVATE_KEY }} | |
- uses: actions/github-script@v6 | |
with: | |
github-token: ${{ steps.app-token.outputs.token }} | |
script: | | |
const name = 'All required checks succeeded'; | |
const head_sha = context.payload.workflow_run.head_sha; | |
const owner = context.payload.repository.owner.login; | |
const repo = context.payload.repository.name; | |
const url = `${context.payload.workflow_run.html_url}/attempts/${context.payload.workflow_run.run_attempt}`; | |
const summary = `See [workflow run](${url}) for details.`; | |
const status = context.payload.workflow_run.status; | |
core.info(`Workflow run ${url} has status '${status}'.`) | |
if (status === 'in_progress' || status === 'queued') { | |
core.info(`Creating check run with status '${status}'.`) | |
await github.rest.checks.create({ | |
owner: owner, | |
repo: repo, | |
name: name, | |
head_sha: head_sha, | |
status: status, | |
started_at: context.payload.workflow_run.started_at, | |
output: { | |
title: name, | |
summary: summary, | |
}, | |
}); | |
} else if (status === 'completed') { | |
// list jobs for worklow run attempt | |
const { data: { jobs } } = await github.rest.actions.listJobsForWorkflowRunAttempt({ | |
owner: owner, | |
repo: repo, | |
run_id: context.payload.workflow_run.id, | |
attempt_number: context.payload.workflow_run.run_attempt, | |
}); | |
// check if required job was successful | |
var success = false; | |
core.info("Checking jobs"); | |
jobs.forEach(job => { | |
var mark = '-' | |
if (job.name === 'All required checks done') { | |
if (job.conclusion === 'success') { | |
success = true; | |
mark = '✅'; | |
} else { | |
mark = '❌'; | |
} | |
} | |
core.info(`${mark} ${job.name}: ${job.conclusion}`); | |
}); | |
// create check run if job was successful | |
if (success) { | |
core.info(`All required jobs succeeded, creating check run with status 'completed' and conclusion 'success'.`) | |
await github.rest.checks.create({ | |
owner: owner, | |
repo: repo, | |
name: name, | |
head_sha: head_sha, | |
status: 'completed', | |
conclusion: 'success', | |
completed_at: context.payload.workflow_run.completed_at, | |
output: { | |
title: name, | |
summary: summary, | |
}, | |
}); | |
} else { | |
core.warning('Not all required jobs succeeded, not creating check run.'); | |
} | |
} else { | |
core.warning(`Unknown status '${status}', not creating check run.`); | |
} |