From 5afd250792faa2808a91fbb7030f2a49f9966510 Mon Sep 17 00:00:00 2001 From: Akuli Date: Fri, 14 May 2021 22:28:34 +0300 Subject: [PATCH] mypy_primer: use 'needs: mypy_primer' for comment job (#5428) --- .github/workflows/mypy_primer.yml | 54 +++++++++- .github/workflows/mypy_primer_comment.yml | 124 ---------------------- 2 files changed, 51 insertions(+), 127 deletions(-) delete mode 100644 .github/workflows/mypy_primer_comment.yml diff --git a/.github/workflows/mypy_primer.yml b/.github/workflows/mypy_primer.yml index 4d00d0c75..ec7a771a9 100644 --- a/.github/workflows/mypy_primer.yml +++ b/.github/workflows/mypy_primer.yml @@ -51,10 +51,58 @@ jobs: --num-shards 2 --shard-index ${{ matrix.shard-index }} \ --debug \ --output concise \ - | tee diff.txt + | tee diff_${{ matrix.shard-index }}.txt ) || [ $? -eq 1 ] - name: Upload mypy_primer diff uses: actions/upload-artifact@v2 with: - name: mypy_primer_diff_${{ matrix.shard-index }} - path: diff.txt + name: mypy_primer_diffs + path: diff_${{ matrix.shard-index }}.txt + + comment: + name: Comment + runs-on: ubuntu-latest + needs: mypy_primer + permissions: + pull-requests: write + steps: + - name: Download diffs + uses: actions/download-artifact@v2 + with: + name: mypy_primer_diffs + + - name: Post comment + uses: actions/github-script@v3 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const fs = require('fs') + const data = ( + ['diff_0.txt', 'diff_1.txt'] + .map(fileName => fs.readFileSync(fileName, { encoding: 'utf8' })) + .join('') + .substr(0, 30000) // About 300 lines + ) + + console.log("Diff from mypy_primer:") + console.log(data) + + let body + if (data.trim()) { + body = 'Diff from [mypy_primer](https://github.com/hauntsaninja/mypy_primer), showing the effect of this PR on open source code:\n```diff\n' + data + '```' + } else { + body = 'According to [mypy_primer](https://github.com/hauntsaninja/mypy_primer), this change has no effect on the checked open source code. 🤖🎉' + } + + await github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body + }) + + - uses: kanga333/comment-hider@9141763feccc8da773595675adc567d6616b6e6f + name: Hide old comments + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + leave_visible: 1 diff --git a/.github/workflows/mypy_primer_comment.yml b/.github/workflows/mypy_primer_comment.yml deleted file mode 100644 index 27e2bc891..000000000 --- a/.github/workflows/mypy_primer_comment.yml +++ /dev/null @@ -1,124 +0,0 @@ -name: Comment with mypy_primer diff - -on: - # pull_request_target gives us access to a write token which we need to post a comment - # The presence of a write token means that we can't run any untrusted code (i.e. malicious PRs), - # which is why this its own workflow. Github Actions doesn't make it easy for workflows to talk to - # each other, so the approach here is to poll for workflow runs, find the mypy_primer run for our - # commit, wait till it's completed, and download and post the diff. - pull_request_target: - # Since modular typeshed, mypy primer doesn't check third party stubs. Till that is changed, - # only run it on stdlib changes to avoid false confidence and wasted CI minutes. - paths: - - 'stdlib/**' - -permissions: - contents: read - pull-requests: write - -jobs: - mypy_primer: - name: Comment - runs-on: ubuntu-latest - steps: - - name: Install dependencies - run: npm install adm-zip - - name: Post comment - uses: actions/github-script@v3 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const AdmZip = require(`${process.env.GITHUB_WORKSPACE}/node_modules/adm-zip`) - - // Because of pull_request_target, context.sha is the PR base branch - // So we need to ask Github for the SHA of the PR's head commit - const pull_request = await github.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.issue.number, - }) - const pr_commit_sha = pull_request.data.head.sha - console.log("Looking for mypy_primer run for commit:", pr_commit_sha) - - // Find the mypy_primer run for our commit and wait till it's completed - // We wait up to an hour before timing out - async function check_mypy_primer() { - // We're only looking at the first page, so in theory if we open enough PRs around - // the same time, this will fail to find the run. - const response = await github.actions.listWorkflowRuns({ - owner: context.repo.owner, - repo: context.repo.repo, - workflow_id: "mypy_primer.yml", - }) - if (response) { - workflow_runs = response.data.workflow_runs - // Sort by reverse updated_at - workflow_runs.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime()) - return workflow_runs.find(run => run.head_sha == pr_commit_sha) - } - return undefined - } - - // Timeout after half an hour - const end_time = Number(new Date()) + 30 * 60 * 1000 - let primer_run = await check_mypy_primer() - // Sleep longer, initially - let sleep = 8 * 60 * 1000 - while (!primer_run || primer_run.status != "completed" || primer_run.conclusion != "success") { - if (Number(new Date()) > end_time) { - throw Error("Timed out waiting for mypy_primer") - } - console.log("Waiting for mypy_primer to complete...") - await new Promise(r => setTimeout(r, sleep)) - primer_run = await check_mypy_primer() - sleep = 60 * 1000 - } - console.log("Found mypy_primer run!") - console.log(primer_run) - - // Download artifact(s) from the run - const artifacts = await github.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: primer_run.id, - }) - const filtered_artifacts = artifacts.data.artifacts.filter( - a => a.name.startsWith("mypy_primer_diff") - ) - console.log("Artifacts from mypy_primer:") - console.log(filtered_artifacts) - - async function get_artifact_data(artifact) { - const zip = await github.actions.downloadArtifact({ - owner: context.repo.owner, - repo: context.repo.repo, - artifact_id: artifact.id, - archive_format: "zip", - }) - const adm = new AdmZip(Buffer.from(zip.data)) - return adm.readAsText(adm.getEntry("diff.txt")) - } - - const all_data = await Promise.all(filtered_artifacts.map(get_artifact_data)) - const data = all_data.join("\n") - - console.log("Diff from mypy_primer:") - console.log(data) - let body; - if (data.trim()) { - body = 'Diff from [mypy_primer](https://github.com/hauntsaninja/mypy_primer), showing the effect of this PR on open source code:\n```diff\n' + data + '```' - } else { - body = 'According to [mypy_primer](https://github.com/hauntsaninja/mypy_primer), this change has no effect on the checked open source code. 🤖🎉' - } - await github.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: body.substr(0, 30000), // About 300 lines - }) - - - uses: kanga333/comment-hider@9141763feccc8da773595675adc567d6616b6e6f - name: Hide old comments - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - leave_visible: 1