Skip to content

Codecov Notify

Codecov Notify #1204

name: Codecov Notify
# Coverage uploads are split across three workflows with different triggers
# and path filters, so we can't set a static after_n_builds threshold
# (backend-only PRs produce 1 upload, mixed PRs produce 5). Instead,
# .codecov.yml sets manual_trigger: true and this workflow explicitly calls
# send-notifications once every upload-producing workflow has finished for
# the triggering SHA. Workflows that skipped due to path filters don't block
# the notify step.
#
# The merged `frontend` flag that the README badge reads is produced
# server-side: each per-suite frontend upload (`frontend-unit`,
# `frontend-component`, `frontend-e2e`) is tagged with `frontend` as an
# additional flag in its own workflow, so Codecov aggregates the union
# of all three without any cross-workflow lcov merging here.
on:
workflow_run:
workflows:
- "Backend CI"
- "Frontend CI"
- "Frontend E2E Integration"
- "Frontend E2E Extract Pipeline (VCR)"
types: [completed]
concurrency:
group: codecov-notify-${{ github.event.workflow_run.head_sha }}
cancel-in-progress: false
jobs:
notify:
runs-on: ubuntu-latest
permissions:
contents: read
actions: read
steps:
- name: Wait for all coverage workflows
id: check
uses: actions/github-script@v9
with:
script: |
const sha = context.payload.workflow_run.head_sha;
const expected = [
"Backend CI",
"Frontend CI",
"Frontend E2E Integration",
"Frontend E2E Extract Pipeline (VCR)",
];
// Fetch every workflow run attached to this SHA. Sort explicitly
// by created_at desc so we always pick the most recent attempt
// per workflow (after re-runs) rather than relying on undocumented
// API ordering.
const runs = await github.paginate(
github.rest.actions.listWorkflowRunsForRepo,
{
owner: context.repo.owner,
repo: context.repo.repo,
head_sha: sha,
per_page: 100,
}
);
let allDone = true;
for (const name of expected) {
const matching = runs
.filter((r) => r.name === name)
.sort(
(a, b) =>
new Date(b.created_at).getTime() -
new Date(a.created_at).getTime()
);
if (matching.length === 0) {
core.info(`${name}: no run for this SHA (path-filtered) — OK`);
continue;
}
const latest = matching[0];
core.info(
`${name}: status=${latest.status} conclusion=${latest.conclusion} id=${latest.id}`
);
if (latest.status !== "completed") {
allDone = false;
}
}
core.setOutput("all_done", allDone ? "true" : "false");
core.setOutput("sha", sha);
- name: Send notifications to Codecov
if: steps.check.outputs.all_done == 'true'
uses: codecov/codecov-action@v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
run_command: send-notifications
override_commit: ${{ steps.check.outputs.sha }}
fail_ci_if_error: false