Skip to content

Spread tests results PR commenter #21863

Spread tests results PR commenter

Spread tests results PR commenter #21863

name: Spread tests results PR commenter
on:
workflow_run:
workflows: [Tests]
types:
- completed
jobs:
report-spread-failures:
if: ${{ github.event.workflow_run.event == 'pull_request' }}
runs-on: ubuntu-latest
permissions:
pull-requests: write
env:
GH_TOKEN: ${{ github.token }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Get PR number
uses: actions/github-script@v9
with:
script: |
let page = 1;
let per_page = 100;
let allArtifacts = [];
let response;
do {
response = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
per_page: per_page,
page: page
});
allArtifacts = allArtifacts.concat(response.data.artifacts);
page++;
} while (allArtifacts.length < response.data.total_count);
let matchArtifact = allArtifacts.filter((artifact) => {
return artifact.name == "pr_number"
})[0];
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/pr_number.zip`, Buffer.from(download.data));
- name: Unzip PR number
run: unzip pr_number.zip
- name: Get generated data
uses: actions/github-script@v9
with:
script: |
let page = 1;
let per_page = 100;
let allArtifacts = [];
let response;
do {
response = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.payload.workflow_run.id,
per_page: per_page,
page: page
});
allArtifacts = allArtifacts.concat(response.data.artifacts);
page++;
} while (allArtifacts.length < response.data.total_count);
let matchingArtifacts = allArtifacts.filter((artifact) => {
return artifact.name.startsWith(`spread-results-${context.payload.workflow_run.id}-${context.payload.workflow_run.run_attempt}`);
});
for (let artifact of matchingArtifacts) {
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
console.log(`Downloaded artifact: ${artifact.name}.zip`);
}
let matchingSkips = allArtifacts.filter((artifact) => {
return artifact.name.startsWith(`skipped-tests-list-${context.payload.workflow_run.id}`);
});
for (let artifact of matchingSkips) {
let download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
let fs = require('fs');
fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
console.log(`Downloaded artifact: ${artifact.name}.zip`);
}
- name: Unzip spread json files
run: |
find . -name "spread-results-${{ github.event.workflow_run.id }}*.zip" | while read filename; do
dir="${filename%.zip}"
mkdir "$dir"
unzip "$filename" -d "$dir"
done
- name: Unzip spread skip files
run: |
find . -name "skipped-tests-list-${{ github.event.workflow_run.id }}*.zip" | while read filename; do
dir="${filename%.zip}"
mkdir "$dir"
unzip "$filename" -d "$dir"
done
- name: Echo collected output
run: |
# generate report
(
date
# The 'skip spread' label was added to the pull request
if gh api /repos/${{ github.repository }}/issues/"$(cat pr_number)" | jq '.labels.[].name' | grep -iq '"skip spread"'; then
echo "## Spread tests skipped"
exit 0
fi
echo "The following results are from: https://github.com/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}"
# There are no logged spread failures
if ! ls spread-results-${{ github.event.workflow_run.id }}-*/*.json &> /dev/null; then
echo '## No spread failures reported'
else
# Consolidate all json files into one
jq -s '{items: (map(.items[]) )}' spread-results-${{ github.event.workflow_run.id }}*/*.json > consolidated-report.json
echo "## Failures:"
if [[ $(jq -r '.items[] | select(.verb == "preparing" and .success == false)' consolidated-report.json) ]]; then
echo "### Preparing:"
jq -r '.items[] | select(.verb == "preparing" and .success == false) | "\(.backend):\(.system):\(.name)\(if .variant != "" then ":\(.variant)" else "" end)"' consolidated-report.json |\
awk ' { print "- " $0 }'
fi
if [[ $(jq -r '.items[] | select(.verb == "executing" and .success == false)' consolidated-report.json) ]]; then
echo "### Executing:"
jq -r '.items[] | select(.verb == "executing" and .success == false) | "\(.backend):\(.system):\(.name)\(if .variant != "" then ":\(.variant)" else "" end)"' consolidated-report.json |\
awk ' { print "- " $0 }'
fi
if [[ $(jq -r '.items[] | select(.verb == "restoring" and .success == false)' consolidated-report.json) ]]; then
echo "### Restoring:"
jq -r '.items[] | select(.verb == "restoring" and .success == false) | "\(.backend):\(.system):\(.name)\(if .variant != "" then ":\(.variant)" else "" end)"' consolidated-report.json |\
awk ' { print "- " $0 }'
fi
fi
) > report
if find . -name skipped_tests_list.txt | grep -q .; then
echo "## Skipped tests from [snapd-testing-skip](https://github.com/canonical/snapd-testing-skip)" >> report
echo "*If you wish to have any of the below tests run in your PR, in your PR description, add 'unskip:' followed by a copy-and-pasted list of the below tests you wish to run (unskip plus test list must be valid yaml)*" >> report
find . -name skipped_tests_list.txt -exec cat {} \; | tr ' ' '\n' | grep . | sed 's/:[^/:]*$//' | sort -u | awk '{print "- "$1}' >> report
fi
# display the report
grep -n '' report
- name: Comment report to PR
run: |
if ! gh pr comment "$(cat pr_number)" --body "$(cat report)" --edit-last; then
gh pr comment "$(cat pr_number)" --body "$(cat report)"
fi