CI: Notify PRs when coverage report is available
This commit is contained in:
parent
728f56e581
commit
d7fbea62f9
|
|
@ -37,10 +37,13 @@ jobs:
|
||||||
build:
|
build:
|
||||||
name: Build content
|
name: Build content
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
outputs:
|
||||||
|
coverage-pr-run-ids: ${{ steps.build.outputs.coverage-pr-run-ids }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
- name: Build pages
|
- name: Build pages
|
||||||
|
id: build
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -62,3 +65,28 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: actions/deploy-pages@v4
|
uses: actions/deploy-pages@v4
|
||||||
|
|
||||||
|
notify:
|
||||||
|
name: Notify
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
- deploy
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: ${{ github.repository == 'verilator/verilator' }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
# Use the Verilator CI app to post the comment
|
||||||
|
- name: Generate access token
|
||||||
|
id: generate-token
|
||||||
|
uses: actions/create-github-app-token@v2.1.4
|
||||||
|
with:
|
||||||
|
app-id: ${{ vars.VERILATOR_CI_ID }}
|
||||||
|
private-key: ${{ secrets.VERILATOR_CI_KEY }}
|
||||||
|
permission-actions: write
|
||||||
|
permission-pull-requests: write
|
||||||
|
- name: Comment on PR
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
|
COVERAGE_PR_RUN_IDS: ${{ needs.build.outputs.coverage-pr-run-ids }}
|
||||||
|
run: bash -x ./ci/ci-pages-notify.bash
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# DESCRIPTION: Verilator: CI script for 'pages.yml', notifies PRs
|
||||||
|
#
|
||||||
|
# Copyright 2025 by Geza Lore. This program is free software; you
|
||||||
|
# can redistribute it and/or modify it under the terms of either the GNU
|
||||||
|
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||||
|
# Version 2.0.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
# Notify PRs via comment that their coverage reports are available
|
||||||
|
|
||||||
|
# Get the current repo URL - might differ on a fork
|
||||||
|
readonly REPO_URL=$(gh repo view --json url --jq .url)
|
||||||
|
|
||||||
|
# Create artifacts root directory
|
||||||
|
ARTIFACTS_ROOT=artifacts
|
||||||
|
mkdir -p ${ARTIFACTS_ROOT}
|
||||||
|
|
||||||
|
for RUN_ID in ${COVERAGE_PR_RUN_IDS//,/ }; do
|
||||||
|
echo "@@@ Processing run ${RUN_ID}"
|
||||||
|
|
||||||
|
# Create workflow artifacts directory
|
||||||
|
ARTIFACTS_DIR=${ARTIFACTS_ROOT}/${RUN_ID}
|
||||||
|
mkdir -p ${ARTIFACTS_DIR}
|
||||||
|
|
||||||
|
# Download artifact of this run, if exists
|
||||||
|
gh run download ${RUN_ID} --name coverage-pr-notification --dir ${ARTIFACTS_DIR} || true
|
||||||
|
ls -lsha ${ARTIFACTS_DIR}
|
||||||
|
|
||||||
|
# Move on if no notification is required
|
||||||
|
if [ ! -f ${ARTIFACTS_DIR}/pr-number.txt ]; then
|
||||||
|
echo "No notification found"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "Posting notification found"
|
||||||
|
|
||||||
|
cat ${ARTIFACTS_DIR}/body.txt
|
||||||
|
gh pr comment $(cat ${ARTIFACTS_DIR}/pr-number.txt) --body-file ${ARTIFACTS_DIR}/body.txt
|
||||||
|
|
||||||
|
# Get the artifact ID
|
||||||
|
ARTIFACT_ID=$(gh api "repos/{owner}/{repo}/actions/runs/${RUN_ID}/artifacts" --jq '.artifacts[] | select(.name == "coverage-pr-notification") | .id')
|
||||||
|
|
||||||
|
# Delete it, so we only notify once
|
||||||
|
gh api --method DELETE "repos/{owner}/{repo}/actions/artifacts/${ARTIFACT_ID}"
|
||||||
|
done
|
||||||
|
|
@ -24,9 +24,13 @@ mkdir -p ${PAGES_ROOT}
|
||||||
# Get the current repo URL - might differ on a fork
|
# Get the current repo URL - might differ on a fork
|
||||||
readonly REPO_URL=$(gh repo view --json url --jq .url)
|
readonly REPO_URL=$(gh repo view --json url --jq .url)
|
||||||
|
|
||||||
|
# Set GITHUB_OUTPUT when run locally for testing
|
||||||
|
if [[ -z "$GITHUB_OUTPUT" ]]; then
|
||||||
|
GITHUB_OUTPUT=github-output.txt
|
||||||
|
fi
|
||||||
|
|
||||||
# Populates ${PAGES_ROOT}/coverage-reports
|
# Populates ${PAGES_ROOT}/coverage-reports
|
||||||
compile_coverage_reports() {
|
compile_coverage_reports() {
|
||||||
|
|
||||||
# We will process all runs up to and including this date. This is chosen to be
|
# We will process all runs up to and including this date. This is chosen to be
|
||||||
# slightly less than the artifact retention period for simplicity.
|
# slightly less than the artifact retention period for simplicity.
|
||||||
local OLDEST=$(date --date="28 days ago" --iso-8601=date)
|
local OLDEST=$(date --date="28 days ago" --iso-8601=date)
|
||||||
|
|
@ -50,8 +54,11 @@ compile_coverage_reports() {
|
||||||
mkdir -p ${COVERAGE_ROOT}
|
mkdir -p ${COVERAGE_ROOT}
|
||||||
|
|
||||||
# Create index page contents fragment
|
# Create index page contents fragment
|
||||||
local CONTENTSS=contents.tmp
|
local CONTENTS=contents.tmp
|
||||||
echo > ${CONTENTSS}
|
echo > ${CONTENTS}
|
||||||
|
|
||||||
|
# Run IDs of PR jobs processed
|
||||||
|
local PR_RUN_IDS=""
|
||||||
|
|
||||||
# Iterate over all unique event types that triggered the workflows
|
# Iterate over all unique event types that triggered the workflows
|
||||||
for EVENT in $(jq -r 'map(.event) | sort | unique | .[]' completedRuns.json); do
|
for EVENT in $(jq -r 'map(.event) | sort | unique | .[]' completedRuns.json); do
|
||||||
|
|
@ -61,19 +68,28 @@ compile_coverage_reports() {
|
||||||
EMIT_SECTION_HEADER=1
|
EMIT_SECTION_HEADER=1
|
||||||
|
|
||||||
# For each worfklow run that was triggered by this event type
|
# For each worfklow run that was triggered by this event type
|
||||||
for WORKFLOW_ID in $(jq ".[] | select(.event == \"${EVENT}\") |.databaseId" completedRuns.json); do
|
for RUN_ID in $(jq ".[] | select(.event == \"${EVENT}\") |.databaseId" completedRuns.json); do
|
||||||
echo "@@@ Processing run ${WORKFLOW_ID}"
|
echo "@@@ Processing run ${RUN_ID}"
|
||||||
|
|
||||||
# Extract the info of this run
|
# Extract the info of this run
|
||||||
jq ".[] | select(.databaseId == $WORKFLOW_ID)" completedRuns.json > workflow.json
|
jq ".[] | select(.databaseId == $RUN_ID)" completedRuns.json > workflow.json
|
||||||
jq "." workflow.json
|
jq "." workflow.json
|
||||||
|
|
||||||
|
# Record run ID of PR job
|
||||||
|
if [[ $EVENT == "pull_request" ]]; then
|
||||||
|
if [[ -z "$PR_RUN_IDS" ]]; then
|
||||||
|
PR_RUN_IDS="$RUN_ID"
|
||||||
|
else
|
||||||
|
PR_RUN_IDS="$PR_RUN_IDS,$RUN_ID"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Create workflow artifacts directory
|
# Create workflow artifacts directory
|
||||||
local ARTIFACTS_DIR=${ARTIFACTS_ROOT}/${WORKFLOW_ID}
|
local ARTIFACTS_DIR=${ARTIFACTS_ROOT}/${RUN_ID}
|
||||||
mkdir -p ${ARTIFACTS_DIR}
|
mkdir -p ${ARTIFACTS_DIR}
|
||||||
|
|
||||||
# Download artifacts of this run, if exists
|
# Download artifacts of this run, if exists
|
||||||
gh run download ${WORKFLOW_ID} --name coverage-report --dir ${ARTIFACTS_DIR} || true
|
gh run download ${RUN_ID} --name coverage-report --dir ${ARTIFACTS_DIR} || true
|
||||||
ls -lsha ${ARTIFACTS_DIR}
|
ls -lsha ${ARTIFACTS_DIR}
|
||||||
|
|
||||||
# Move on if no coverage report is available
|
# Move on if no coverage report is available
|
||||||
|
|
@ -86,26 +102,34 @@ compile_coverage_reports() {
|
||||||
# Emit section header
|
# Emit section header
|
||||||
if [[ -n $EMIT_SECTION_HEADER ]]; then
|
if [[ -n $EMIT_SECTION_HEADER ]]; then
|
||||||
unset EMIT_SECTION_HEADER
|
unset EMIT_SECTION_HEADER
|
||||||
echo "<h4>Coverage reports for '${EVENT}' runs:</h4>" >> ${CONTENTSS}
|
if [[ $EVENT == "pull_request" ]]; then
|
||||||
|
echo "<h4>Patch coverage reports for '${EVENT}' runs:</h4>" >> ${CONTENTS}
|
||||||
|
else
|
||||||
|
echo "<h4>Code coverage reports for '${EVENT}' runs:</h4>" >> ${CONTENTS}
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#Create pages subdirectory
|
# Create pages subdirectory
|
||||||
mv ${ARTIFACTS_DIR}/report ${COVERAGE_ROOT}/${WORKFLOW_ID}
|
mv ${ARTIFACTS_DIR}/report ${COVERAGE_ROOT}/${RUN_ID}
|
||||||
|
|
||||||
# Add index page content
|
# Add index page content
|
||||||
local WORKFLOW_CREATED=$(jq -r '.createdAt' workflow.json)
|
local WORKFLOW_CREATED=$(jq -r '.createdAt' workflow.json)
|
||||||
local WOFKRLOW_NUMBER=$(jq -r '.number' workflow.json)
|
local WOFKRLOW_NUMBER=$(jq -r '.number' workflow.json)
|
||||||
cat >> ${CONTENTSS} <<CONTENTS_TEMPLATE
|
cat >> ${CONTENTS} <<CONTENTS_TEMPLATE
|
||||||
Run <a href="${WORKFLOW_ID}/index.html">#${WOFKRLOW_NUMBER}</a>
|
Run <a href="${RUN_ID}/index.html">#${WOFKRLOW_NUMBER}</a>
|
||||||
| GitHub: <a href="${REPO_URL}/actions/runs/${WORKFLOW_ID}">${WORKFLOW_ID}</a>
|
| GitHub: <a href="${REPO_URL}/actions/runs/${RUN_ID}">${RUN_ID}</a>
|
||||||
| started at: ${WORKFLOW_CREATED}
|
| started at: ${WORKFLOW_CREATED}
|
||||||
<br>
|
|
||||||
CONTENTS_TEMPLATE
|
CONTENTS_TEMPLATE
|
||||||
|
if [ -e ${ARTIFACTS_DIR}/pr-number.txt ]; then
|
||||||
|
local PRNUMBER=$(cat ${ARTIFACTS_DIR}/pr-number.txt)
|
||||||
|
echo " | Pull request: <a href=\"${REPO_URL}/pull/${PRNUMBER}\">#${PRNUMBER}</a>" >> ${CONTENTS}
|
||||||
|
fi
|
||||||
|
echo "<br>" >> ${CONTENTS}
|
||||||
done
|
done
|
||||||
|
|
||||||
# Section break
|
# Section break
|
||||||
if [[ -z $EMIT_SECTION_HEADER ]]; then
|
if [[ -z "$EMIT_SECTION_HEADER" ]]; then
|
||||||
echo "<hr>" >> ${CONTENTSS}
|
echo "<hr>" >> ${CONTENTS}
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
@ -118,7 +142,7 @@ CONTENTS_TEMPLATE
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: courier, serif;
|
font-family: courier, serif;
|
||||||
background-color: #dddddd;
|
background-color: #f3f3f3;
|
||||||
a {
|
a {
|
||||||
color: #008fd7;
|
color: #008fd7;
|
||||||
}
|
}
|
||||||
|
|
@ -127,12 +151,19 @@ CONTENTS_TEMPLATE
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
$(cat ${CONTENTSS})
|
$(cat ${CONTENTS})
|
||||||
<h4>Assembled $(date --iso-8601=minutes --utc)</h1>
|
<h4>Assembled $(date --iso-8601=minutes --utc)</h1>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
INDEX_TEMPLATE
|
INDEX_TEMPLATE
|
||||||
|
|
||||||
|
# Report size
|
||||||
|
${COVERAGE_ROOT}
|
||||||
|
du -shc *
|
||||||
|
|
||||||
|
# Set output
|
||||||
|
echo "coverage-pr-run-ids=${PR_RUN_IDS}" >> $GITHUB_OUTPUT
|
||||||
}
|
}
|
||||||
|
|
||||||
# Compilie coverage reports
|
# Compilie coverage reports
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue