From 9d52aaede325a43612bccb571f640cddfa842bc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 29 Jan 2023 17:16:29 +0000 Subject: [PATCH] Make CI friendlier (#7398) # Objective - Make CI friendlier ## Solution - CI now says hello to new contributor - for some jobs with non obvious solutions to failures, give more context - example run should say which example failed - example doc should say the next action to do (add metadata or run the update script) - MSRV will say when it needs updating I'm not completely sure everything is working and will try to trigger failures in this PR --- .github/workflows/ci-comment-failures.yml | 170 ++++++++++++++++++++++ .github/workflows/ci.yml | 56 +++++-- .github/workflows/welcome.yml | 42 ++++++ 3 files changed, 257 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/ci-comment-failures.yml create mode 100644 .github/workflows/welcome.yml diff --git a/.github/workflows/ci-comment-failures.yml b/.github/workflows/ci-comment-failures.yml new file mode 100644 index 0000000000000..b3a9f0790d230 --- /dev/null +++ b/.github/workflows/ci-comment-failures.yml @@ -0,0 +1,170 @@ +name: CI - PR Comments + + # This workflow has write permissions on the repo + # It must not checkout a PR and run untrusted code + +# Also requesting write permissions on PR to be able to comment +permissions: + pull-requests: 'write' + +on: + workflow_run: + workflows: ["CI"] + types: + - completed + +jobs: + example-run: + runs-on: ubuntu-latest + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'failure' + steps: + - name: 'Download artifact' + id: find-artifact + uses: actions/github-script@v6 + with: + result-encoding: string + script: | + var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{github.event.workflow_run.id }}, + }); + var matchArtifacts = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "example-run" + }); + if (matchArtifacts.length == 0) { return "false" } + var matchArtifact = matchArtifacts[0]; + var download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/example-run.zip', Buffer.from(download.data)); + return "true" + - run: unzip example-run.zip + if: ${{ steps.find-artifact.outputs.result == 'true' }} + - name: 'Comment on PR' + if: ${{ steps.find-artifact.outputs.result == 'true' }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var fs = require('fs'); + var issue_number = Number(fs.readFileSync('./NR')); + var last_example_run = fs.readFileSync('./last_example_run'); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: 'Example ' + last_example_run + ' failed to run, please try running it locally and check the result.' + }); + + missing-examples: + runs-on: ubuntu-latest + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'failure' + steps: + - name: 'Download artifact' + id: find-artifact + uses: actions/github-script@v6 + with: + result-encoding: string + script: | + var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{github.event.workflow_run.id }}, + }); + var matchArtifacts = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "missing-examples" + }); + if (matchArtifacts.length == 0) { return "false" } + var matchArtifact = matchArtifacts[0]; + var download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/missing-examples.zip', Buffer.from(download.data)); + return "true" + - run: unzip missing-examples.zip + if: ${{ steps.find-artifact.outputs.result == 'true' }} + - name: 'Comment on PR' + if: ${{ steps.find-artifact.outputs.result == 'true' }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var fs = require('fs'); + var issue_number = Number(fs.readFileSync('./NR')); + if (existsSync('./missing-metadata')) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: 'You added a new example but didn't add metadata for it. Please update the root Cargo.toml file.' + }); + } + if (existsSync('./missing-update')) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: 'You added a new example but didn't update the readme. Please run `cargo run -p build-example-pages -- update` to update it, and commit the file change.' + }); + } + + msrv: + runs-on: ubuntu-latest + if: > + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.conclusion == 'failure' + steps: + - name: 'Download artifact' + id: find-artifact + uses: actions/github-script@v6 + with: + result-encoding: string + script: | + var artifacts = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: ${{github.event.workflow_run.id }}, + }); + var matchArtifacts = artifacts.data.artifacts.filter((artifact) => { + return artifact.name == "msrv" + }); + if (matchArtifacts.length == 0) { return "false" } + var matchArtifact = matchArtifacts[0]; + var download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifact.id, + archive_format: 'zip', + }); + var fs = require('fs'); + fs.writeFileSync('${{github.workspace}}/msrv.zip', Buffer.from(download.data)); + return "true" + - run: unzip msrv.zip + if: ${{ steps.find-artifact.outputs.result == 'true' }} + - name: 'Comment on PR' + if: ${{ steps.find-artifact.outputs.result == 'true' }} + uses: actions/github-script@v6 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + var fs = require('fs'); + var issue_number = Number(fs.readFileSync('./NR')); + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: 'Your PR increases Bevy Minimum Supported Rust Version. Please update the `rust-version` field in the root Cargo.toml file.' + }); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eafdcfebbde87..e48279ef73bc7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -142,7 +142,7 @@ jobs: markdownlint: runs-on: ubuntu-latest - needs: check-examples-readme-update-needed + needs: check-missing-examples-in-docs if: always() steps: - uses: actions/checkout@v3 @@ -156,8 +156,6 @@ jobs: VALIDATE_ALL_CODEBASE: false VALIDATE_MARKDOWN: true DEFAULT_BRANCH: main - # Not needed here as only one Linter is used. - #GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run-examples: runs-on: ubuntu-latest @@ -193,6 +191,7 @@ jobs: run: | for example in .github/example-run/*.ron; do example_name=`basename $example .ron` + echo $example > last_example_run echo "running $example_name - "`date` time TRACE_CHROME=trace-$example_name.json CI_TESTING_CONFIG=$example xvfb-run cargo run --example $example_name --features "bevy_ci_testing,trace,trace_chrome" sleep 10 @@ -203,6 +202,17 @@ jobs: with: name: example-traces.zip path: traces.zip + - name: Save PR number + if: ${{ failure() && github.event_name == 'pull_request' }} + run: | + mkdir -p ./example-run + echo ${{ github.event.number }} > ./example-run/NR + mv last_example_run > ./example-run/ + - uses: actions/upload-artifact@v2 + if: ${{ failure() && github.event_name == 'pull_request' }} + with: + name: example-run + path: example-run/ check-doc: runs-on: ubuntu-latest @@ -239,19 +249,33 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - run: cargo run -p build-example-pages -- check-missing - - check-examples-readme-update-needed: - needs: check-missing-examples-in-docs - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - run: cargo run -p build-example-pages -- update + - name: check for missing metadata + id: missing-metadata + run: cargo run -p build-example-pages -- check-missing + - name: check for missing update + id: missing-update + run: cargo run -p build-example-pages -- update - name: Check for modified files run: | echo "if this step fails, run the following command and commit the changed file on your PR." echo " > cargo run -p build-example-pages -- update" git diff --quiet HEAD -- + - name: Save PR number + if: ${{ failure() && github.event_name == 'pull_request' }} + run: | + mkdir -p ./missing-examples + echo ${{ github.event.number }} > ./missing-examples/NR + - name: log failed task - missing metadata + if: ${{ failure() && github.event_name == 'pull_request' && steps.missing-metadata.conclusion == 'failure' }} + run: touch ./missing-examples/missing-metadata + - name: log failed task - missing update + if: ${{ failure() && github.event_name == 'pull_request' && steps.missing-update.conclusion == 'failure' }} + run: touch ./missing-examples/missing-update + - uses: actions/upload-artifact@v2 + if: ${{ failure() && github.event_name == 'pull_request' }} + with: + name: missing-examples + path: missing-examples/ check-unused-dependencies: runs-on: ubuntu-latest @@ -301,3 +325,13 @@ jobs: run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev - name: Run cargo check run: cargo check + - name: Save PR number + if: ${{ failure() && github.event_name == 'pull_request' }} + run: | + mkdir -p ./msrv + echo ${{ github.event.number }} > ./msrv/NR + - uses: actions/upload-artifact@v2 + if: ${{ failure() && github.event_name == 'pull_request' }} + with: + name: msrv + path: msrv/ diff --git a/.github/workflows/welcome.yml b/.github/workflows/welcome.yml new file mode 100644 index 0000000000000..ec32f07fa2388 --- /dev/null +++ b/.github/workflows/welcome.yml @@ -0,0 +1,42 @@ +name: Welcome new contributors + +# This workflow has write permissions on the repo +# It must not checkout a PR and run untrusted code + +on: pull_request_target + +jobs: + welcome: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v6 + with: + script: | + // Get a list of all issues created by the PR opener + // See: https://octokit.github.io/rest.js/#pagination + const creator = context.payload.sender.login + const opts = github.rest.issues.listForRepo.endpoint.merge({ + ...context.issue, + creator, + state: 'all' + }) + const issues = await github.paginate(opts) + + for (const issue of issues) { + if (issue.number === context.issue.number) { + continue + } + + if (issue.pull_request) { + return // Creator is already a contributor. + } + } + + await github.rest.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: `**Welcome**, new contributor! + + Please make sure you're read our [contributing guide](CONTRIBUTING.md) and we look forward to reviewing your Pull request shortly ✨` + })