diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93ec36b91b..adfa1c5bd7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,16 +1,6 @@ name: CI on: workflow_call jobs: - save-github-event: - name: "Save `github.event` as an artifact to use in subsequent 'workflow_run' actions" - runs-on: ubuntu-latest - steps: - - name: Upload event.json - uses: actions/upload-artifact@v2 - with: - name: event.json - path: ${{ github.event_path }} - lint: name: Lint source files runs-on: ubuntu-latest diff --git a/.github/workflows/canary.yaml b/.github/workflows/cmd-publish-pr-on-npm.yml similarity index 61% rename from .github/workflows/canary.yaml rename to .github/workflows/cmd-publish-pr-on-npm.yml index cc988a8496..75bb78bf34 100644 --- a/.github/workflows/canary.yaml +++ b/.github/workflows/cmd-publish-pr-on-npm.yml @@ -1,16 +1,48 @@ -name: Canary Release +name: publish-pr-on-npm on: - workflow_run: - workflows: - - PullRequest - types: - - completed + workflow_call: + inputs: + pullRequestJSON: + required: true + type: string + outputs: + replyMessage: + value: ${{ jobs.publish-canary.outputs.replyMessage }} jobs: + build-npm-dist: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + persist-credentials: false + ref: ${{ fromJSON(inputs.pullRequestJSON).merge_commit_sha }} + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + cache: npm + node-version-file: '.node-version' + + - name: Install Dependencies + run: npm ci --ignore-scripts + + - name: Build NPM package + run: npm run build:npm + + - name: Upload npmDist package + uses: actions/upload-artifact@v2 + with: + name: npmDist + path: ./npmDist + publish-canary: runs-on: ubuntu-latest name: Publish Canary - if: github.event.workflow_run.event == 'pull_request' environment: canary-pr-npm + outputs: + replyMessage: ${{ steps.set_replyMessage.outputs.replyMessage }} + needs: [build-npm-dist] steps: - name: Checkout repo uses: actions/checkout@v2 @@ -25,38 +57,33 @@ jobs: # 'registry-url' is required for 'npm publish' registry-url: 'https://registry.npmjs.org' - - name: Download event.json - run: gh run download "$WORKFLOW_ID" -n event.json - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WORKFLOW_ID: ${{github.event.workflow_run.id}} - - - name: Download NPM package artifact - run: gh run download "$WORKFLOW_ID" -n npmDist -D npmDist - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WORKFLOW_ID: ${{github.event.workflow_run.id}} + - uses: actions/download-artifact@v2 + with: + name: npmDist + path: npmDist - name: Modify NPM package to be canary release + env: + PULL_REQUEST_JSON: ${{ inputs.pullRequestJSON }} uses: actions/github-script@v5 with: script: | const fs = require('fs'); const assert = require('assert'); + const pull_request = JSON.parse(process.env.PULL_REQUEST_JSON); const packageJSONPath = './npmDist/package.json'; const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8')); - const { pull_request } = JSON.parse(fs.readFileSync('./event.json', 'utf-8')); // Override entire 'publishConfig' since it can contain untrusted data. packageJSON.publishConfig = { tag: `canary-pr-${pull_request.number}` }; assert(!packageJSON.version.includes('+'), 'Can not append after metadata'); packageJSON.version += packageJSON.version.includes('-') ? '.' : '-'; - packageJSON.version += `canary.pr.${pull_request.number}.${pull_request.head.sha}`; + packageJSON.version += `canary.pr.${pull_request.number}.${pull_request.merge_commit_sha}`; packageJSON.deprecated = - `You are using canary version build from ${pull_request.url}, no gurantees provided so please use your own discretion.`; + `You are using canary version build from ${pull_request.html_url}, no gurantees provided so please use your own discretion.`; assert( packageJSON.scripts == null, @@ -69,7 +96,6 @@ jobs: 'utf-8', ); - core.exportVariable('PR_NUMBER', pull_request.number); core.exportVariable('NPM_TAG', packageJSON.publishConfig.tag); core.exportVariable('NPM_VERSION', packageJSON.version); @@ -78,19 +104,11 @@ jobs: env: NODE_AUTH_TOKEN: ${{ secrets.NPM_CANARY_PR_PUBLISH_TOKEN }} - - name: Add comment on PR - uses: actions/github-script@v5 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - github.rest.issues.createComment({ - issue_number: process.env.PR_NUMBER, - owner: context.repo.owner, - repo: context.repo.repo, - body: process.env.COMMENT_BODY, - }) + - name: Set 'replyMessage' output variable + id: set_replyMessage + run: echo "::set-output replyMessage=$REPLY_MESSAGE" env: - COMMENT_BODY: | + REPLY_MESSAGE: | The latest changes of this PR are available on NPM as [graphql@${{env.NPM_VERSION}}](https://www.npmjs.com/package/graphql/v/${{env.NPM_VERSION}}) **Note: no gurantees provided so please use your own discretion.** diff --git a/.github/workflows/cmd-run-benchmark.yml b/.github/workflows/cmd-run-benchmark.yml new file mode 100644 index 0000000000..2064d5b5be --- /dev/null +++ b/.github/workflows/cmd-run-benchmark.yml @@ -0,0 +1,57 @@ +name: run-benchmark +on: + workflow_call: + inputs: + pullRequestJSON: + required: true + type: string + outputs: + replyMessage: + value: ${{ jobs.benchmark.outputs.replyMessage }} +jobs: + benchmark: + name: Run benchmark + outputs: + replyMessage: ${{ steps.set_replyMessage.outputs.replyMessage }} + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v2 + with: + persist-credentials: false + ref: ${{ fromJSON(inputs.pullRequestJSON).merge_commit_sha }} + + - name: Deepen cloned repo + env: + BASE_SHA: ${{ fromJSON(inputs.pullRequestJSON).base.sha }} + run: 'git fetch --depth=1 origin $BASE_SHA:refs/tags/BASE' + + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + cache: npm + node-version-file: '.node-version' + + - name: Install Dependencies + run: npm ci --ignore-scripts + + - name: Run Benchmark + run: | + npm run benchmark -- --revs HEAD BASE | tee benchmark.log + + - name: Set 'replyMessage' output variable + id: set_replyMessage + uses: actions/github-script@v5 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const fs = require('fs'); + + const replyMessage = ` +
+ Benchmark output + + ${ fs.readFileSync('./benchmark.log', 'utf-8') } +
+ `; + core.setOutput('replyMessage', replyMessage); diff --git a/.github/workflows/github-actions-bot.yml b/.github/workflows/github-actions-bot.yml new file mode 100644 index 0000000000..d56cdcada5 --- /dev/null +++ b/.github/workflows/github-actions-bot.yml @@ -0,0 +1,145 @@ +name: GitHubActionsBot +on: + issue_comment: + types: + - created + + # We need to be call in context of the main branch to have write permissions + # "pull_request" target is called in context of a fork + # "pull_request_target" is called in context of the repository but not necessary latest main + workflow_run: + workflows: + - PullRequestOpened + types: + - completed +jobs: + hello-message: + if: github.event_name == 'workflow_run' + runs-on: ubuntu-latest + steps: + - name: Download event.json + run: gh run download "$WORKFLOW_ID" --repo "$REPO" --name event.json + env: + REPO: ${{ github.repository }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WORKFLOW_ID: ${{github.event.workflow_run.id}} + + - name: Add comment on PR + uses: actions/github-script@v5 + with: + script: | + const fs = require('fs'); + + const event = JSON.parse(fs.readFileSync('./event.json', 'utf8')); + github.rest.issues.createComment({ + ...context.repo, + issue_number: event.pull_request.number, + body: + `Hi @${event.sender.login}, I'm @github-actions bot happy to help you with this PR 👋\n\n` + + process.env.SUPPORTED_COMMANDS, + }) + env: + SUPPORTED_COMMANDS: | +
+ Supported commands + + Please post this commands in separate comments and only one per comment: + * `@github-actions run-benchmark` - Run benchmark comparing base and merge commits for this PR + * `@github-actions publish-pr-on-npm` - Build package from this PR and publish it on NPM +
+ + accept-cmd: + if: | + github.event_name == 'issue_comment' && + github.event.issue.pull_request && + startsWith(github.event.comment.body, '@github-actions ') + runs-on: ubuntu-latest + outputs: + cmd: ${{ steps.parse-cmd.outputs.cmd }} + replyMessage: ${{ steps.parse-cmd.outputs.replyMessage }} + pullRequestJSON: ${{ steps.get-pull_request-json.outputs.data }} + steps: + - uses: actions/github-script@v5 + with: + script: | + github.rest.reactions.createForIssueComment({ + ...context.repo, + comment_id: context.payload.comment.id, + content: 'eyes', + }); + + - id: parse-cmd + uses: actions/github-script@v5 + with: + script: | + const cmd = context.payload.comment.body.replace('@github-actions', '').trim(); + core.setOutput('cmd', cmd); + + - id: get-pull_request-json + uses: octokit/request-action@v2.x + with: + route: GET ${{ github.event.issue.pull_request.url }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + cmd-publish-pr-on-npm: + needs: [accept-cmd] + if: needs.accept-cmd.outputs.cmd == 'publish-pr-on-npm' + uses: ./.github/workflows/cmd-publish-pr-on-npm.yml + with: + pullRequestJSON: ${{ needs.accept-cmd.outputs.pullRequestJSON }} + + cmd-run-benchmark: + needs: [accept-cmd] + if: needs.accept-cmd.outputs.cmd == 'run-benchmark' + uses: ./.github/workflows/cmd-run-benchmark.yml + with: + pullRequestJSON: ${{ needs.accept-cmd.outputs.pullRequestJSON }} + + respond-to-cmd: + needs: + - cmd-publish-pr-on-npm + - cmd-run-benchmark + if: github.event_name == 'issue_comment' && always() + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v5 + with: + script: | + const { issue, comment, sender } = context.payload; + const needs = JSON.parse(process.env.NEEDS); + + let replyMessage; + let allSkipped = true; + for (const { result, outputs } of Object.values(needs)) { + allSkipped = allSkipped && result === 'skipped'; + replyMessage = replyMessage || outputs.replyMessage; + } + + if (!replyMessage) { + replyMessage = allSkipped + ? 'Unknown command, please check help message at the top of PR.' + : `Something went wrong, please check logs here:\n${process.env.RUN_URL}`; + } + + const quoteRequest = comment.body + .split('\n') + .map((line) => '> ' + line) + .join('\n'); + + github.rest.issues.createComment({ + ...context.repo, + issue_number: issue.number, + body: quoteRequest + `\n\n@${sender.login} ` + replyMessage, + }); + + // `github.rest` doesn't have this method :( so use graphql instead + github.graphql(` + mutation ($subjectId: ID!) { + minimizeComment(input: { subjectId: $subjectId, classifier: RESOLVED}) + { __typename } + } + `, { subjectId: comment.node_id }); + env: + RUN_URL: ${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}} + NEEDS: ${{ toJSON(needs) }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 93b17eddc0..f7e0f14bbb 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -4,32 +4,6 @@ jobs: ci: uses: ./.github/workflows/ci.yml - benchmark: - name: Run benchmark - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v2 - with: - persist-credentials: false - - - name: Deepen cloned repo - env: - BASE_SHA: ${{ github.event.pull_request.base.sha }} - run: 'git fetch --depth=1 origin $BASE_SHA:refs/tags/BASE' - - - name: Setup Node.js - uses: actions/setup-node@v2 - with: - cache: npm - node-version-file: '.node-version' - - - name: Install Dependencies - run: npm ci --ignore-scripts - - - name: Run Benchmark - run: 'npm run benchmark -- --revs HEAD BASE' - diff-npm-package: name: Diff content of NPM package runs-on: ubuntu-latest diff --git a/.github/workflows/pull_request_opened.yml b/.github/workflows/pull_request_opened.yml new file mode 100644 index 0000000000..3970aca533 --- /dev/null +++ b/.github/workflows/pull_request_opened.yml @@ -0,0 +1,14 @@ +name: PullRequestOpened +on: + pull_request: + types: [opened] +jobs: + save-github-event: + name: "Save `github.event` as an artifact to use in subsequent 'workflow_run' actions" + runs-on: ubuntu-latest + steps: + - name: Upload event.json + uses: actions/upload-artifact@v2 + with: + name: event.json + path: ${{ github.event_path }}