Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: Add '@github-actions' bot #3503

Merged
merged 1 commit into from Mar 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 0 additions & 10 deletions .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
Expand Down
@@ -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
Expand All @@ -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,
Expand All @@ -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);

Expand All @@ -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.**
Expand Down
57 changes: 57 additions & 0 deletions .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 = `
<details>
<summary> Benchmark output </summary>

${ fs.readFileSync('./benchmark.log', 'utf-8') }
</details>
`;
core.setOutput('replyMessage', replyMessage);
145 changes: 145 additions & 0 deletions .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: |
<details>
<summary> Supported commands </summary>

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
</details>

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) }}
26 changes: 0 additions & 26 deletions .github/workflows/pull_request.yml
Expand Up @@ -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
Expand Down