diff --git a/.github/workflows/spread-results-reporter.yaml b/.github/workflows/spread-results-reporter.yaml new file mode 100644 index 00000000000..86b9b0db193 --- /dev/null +++ b/.github/workflows/spread-results-reporter.yaml @@ -0,0 +1,112 @@ +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@v4 + + - name: Get PR number + uses: actions/github-script@v6 + with: + script: | + let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + let matchArtifact = allArtifacts.data.artifacts.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@v6 + with: + script: | + let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + let matchingArtifacts = allArtifacts.data.artifacts.filter((artifact) => { + return artifact.name.startsWith(`spread-json-${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`); + } + + - name: Unzip spread json files + run: | + find . -name "spread-json-${{ 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 + if ! ls spread-json-${{ github.event.workflow_run.id }}-*/*.json &> /dev/null; then + echo "## No spread failures" + else + jq -s 'add' spread-json-${{ github.event.workflow_run.id }}*/*.json > consolidated-report.json + + echo "## Failures:" + if [[ $(jq -r '.[] | select( .info_type == "Error" ) | select( .verb == "preparing" )' consolidated-report.json) ]]; then + echo "### Prepare:" + jq -r '.[] | select( .info_type == "Error" ) | select( .verb == "preparing" ) .task' consolidated-report.json |\ + awk ' { print "- " $0 }' + fi + if [[ $(jq -r '.[] | select( .info_type == "Error" ) | select( .verb == "executing" )' consolidated-report.json) ]]; then + echo "### Executing:" + jq -r '.[] | select( .info_type == "Error" ) | select( .verb == "executing" ) .task' consolidated-report.json |\ + awk ' { print "- " $0 }' + fi + if [[ $(jq -r '.[] | select( .info_type == "Error" ) | select( .verb == "restoring" )' consolidated-report.json) ]]; then + echo "### Restoring:" + jq -r '.[] | select( .info_type == "Error" ) | select( .verb == "restoring" ) .task' consolidated-report.json |\ + awk ' { print "- " $0 }' + fi + fi + ) > report + # 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 diff --git a/.github/workflows/spread-tests.yaml b/.github/workflows/spread-tests.yaml index 69d908b61d1..f2da538a2e9 100644 --- a/.github/workflows/spread-tests.yaml +++ b/.github/workflows/spread-tests.yaml @@ -342,3 +342,11 @@ jobs: with: path: "${{ github.workspace }}/.test-results" key: "${{ github.job }}-results-${{ github.run_id }}-${{ inputs.group }}-${{ github.run_attempt }}" + + - name: Save spread.json as an artifact + if: ${{ always() && github.event.pull_request.number }} + uses: actions/upload-artifact@v4 + with: + name: "spread-json-${{ github.run_id }}-${{ github.run_attempt }}-${{ inputs.group }}" + path: "spread-results.json" + if-no-files-found: ignore diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 4c1eaddbc62..3d3a51ec0bd 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -409,3 +409,21 @@ jobs: systems: 'ubuntu-24.04-64' tasks: 'tests/nested/...' rules: 'nested' + + # The spread-results-reporter needs the PR number to be able to + # comment on the relevant PR with spread failures. Because the PR + # number is not in the github.event object during the + # spread-results-reporter.yaml job run, we upload it along side other + # artifacts to be subsequently downloaded by spread-results-reporter. + upload_pr_number: + if: ${{ github.event.pull_request.number }} + runs-on: ubuntu-latest + steps: + - name: Create PR number file + run: echo "${{ github.event.pull_request.number }}" > pr_number + + - name: Upload PR number + uses: actions/upload-artifact@v4 + with: + name: pr_number + path: pr_number