Skip to content

Commit 6bcd241

Browse files
authoredMar 28, 2022
ci: Add '@github-actions' bot (#3503)
1 parent e1726df commit 6bcd241

6 files changed

+268
-70
lines changed
 

‎.github/workflows/ci.yml

-10
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
name: CI
22
on: workflow_call
33
jobs:
4-
save-github-event:
5-
name: "Save `github.event` as an artifact to use in subsequent 'workflow_run' actions"
6-
runs-on: ubuntu-latest
7-
steps:
8-
- name: Upload event.json
9-
uses: actions/upload-artifact@v2
10-
with:
11-
name: event.json
12-
path: ${{ github.event_path }}
13-
144
lint:
155
name: Lint source files
166
runs-on: ubuntu-latest

‎.github/workflows/canary.yaml ‎.github/workflows/cmd-publish-pr-on-npm.yml

+52-34
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,48 @@
1-
name: Canary Release
1+
name: publish-pr-on-npm
22
on:
3-
workflow_run:
4-
workflows:
5-
- PullRequest
6-
types:
7-
- completed
3+
workflow_call:
4+
inputs:
5+
pullRequestJSON:
6+
required: true
7+
type: string
8+
outputs:
9+
replyMessage:
10+
value: ${{ jobs.publish-canary.outputs.replyMessage }}
811
jobs:
12+
build-npm-dist:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout repo
16+
uses: actions/checkout@v2
17+
with:
18+
persist-credentials: false
19+
ref: ${{ fromJSON(inputs.pullRequestJSON).merge_commit_sha }}
20+
21+
- name: Setup Node.js
22+
uses: actions/setup-node@v2
23+
with:
24+
cache: npm
25+
node-version-file: '.node-version'
26+
27+
- name: Install Dependencies
28+
run: npm ci --ignore-scripts
29+
30+
- name: Build NPM package
31+
run: npm run build:npm
32+
33+
- name: Upload npmDist package
34+
uses: actions/upload-artifact@v2
35+
with:
36+
name: npmDist
37+
path: ./npmDist
38+
939
publish-canary:
1040
runs-on: ubuntu-latest
1141
name: Publish Canary
12-
if: github.event.workflow_run.event == 'pull_request'
1342
environment: canary-pr-npm
43+
outputs:
44+
replyMessage: ${{ steps.set_replyMessage.outputs.replyMessage }}
45+
needs: [build-npm-dist]
1446
steps:
1547
- name: Checkout repo
1648
uses: actions/checkout@v2
@@ -25,38 +57,33 @@ jobs:
2557
# 'registry-url' is required for 'npm publish'
2658
registry-url: 'https://registry.npmjs.org'
2759

28-
- name: Download event.json
29-
run: gh run download "$WORKFLOW_ID" -n event.json
30-
env:
31-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
32-
WORKFLOW_ID: ${{github.event.workflow_run.id}}
33-
34-
- name: Download NPM package artifact
35-
run: gh run download "$WORKFLOW_ID" -n npmDist -D npmDist
36-
env:
37-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38-
WORKFLOW_ID: ${{github.event.workflow_run.id}}
60+
- uses: actions/download-artifact@v2
61+
with:
62+
name: npmDist
63+
path: npmDist
3964

4065
- name: Modify NPM package to be canary release
66+
env:
67+
PULL_REQUEST_JSON: ${{ inputs.pullRequestJSON }}
4168
uses: actions/github-script@v5
4269
with:
4370
script: |
4471
const fs = require('fs');
4572
const assert = require('assert');
4673
74+
const pull_request = JSON.parse(process.env.PULL_REQUEST_JSON);
4775
const packageJSONPath = './npmDist/package.json';
4876
const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath, 'utf-8'));
49-
const { pull_request } = JSON.parse(fs.readFileSync('./event.json', 'utf-8'));
5077
5178
// Override entire 'publishConfig' since it can contain untrusted data.
5279
packageJSON.publishConfig = { tag: `canary-pr-${pull_request.number}` };
5380
5481
assert(!packageJSON.version.includes('+'), 'Can not append after metadata');
5582
packageJSON.version += packageJSON.version.includes('-') ? '.' : '-';
56-
packageJSON.version += `canary.pr.${pull_request.number}.${pull_request.head.sha}`;
83+
packageJSON.version += `canary.pr.${pull_request.number}.${pull_request.merge_commit_sha}`;
5784
5885
packageJSON.deprecated =
59-
`You are using canary version build from ${pull_request.url}, no gurantees provided so please use your own discretion.`;
86+
`You are using canary version build from ${pull_request.html_url}, no gurantees provided so please use your own discretion.`;
6087
6188
assert(
6289
packageJSON.scripts == null,
@@ -69,7 +96,6 @@ jobs:
6996
'utf-8',
7097
);
7198
72-
core.exportVariable('PR_NUMBER', pull_request.number);
7399
core.exportVariable('NPM_TAG', packageJSON.publishConfig.tag);
74100
core.exportVariable('NPM_VERSION', packageJSON.version);
75101
@@ -78,19 +104,11 @@ jobs:
78104
env:
79105
NODE_AUTH_TOKEN: ${{ secrets.NPM_CANARY_PR_PUBLISH_TOKEN }}
80106

81-
- name: Add comment on PR
82-
uses: actions/github-script@v5
83-
with:
84-
github-token: ${{secrets.GITHUB_TOKEN}}
85-
script: |
86-
github.rest.issues.createComment({
87-
issue_number: process.env.PR_NUMBER,
88-
owner: context.repo.owner,
89-
repo: context.repo.repo,
90-
body: process.env.COMMENT_BODY,
91-
})
107+
- name: Set 'replyMessage' output variable
108+
id: set_replyMessage
109+
run: echo "::set-output replyMessage=$REPLY_MESSAGE"
92110
env:
93-
COMMENT_BODY: |
111+
REPLY_MESSAGE: |
94112
The latest changes of this PR are available on NPM as
95113
[graphql@${{env.NPM_VERSION}}](https://www.npmjs.com/package/graphql/v/${{env.NPM_VERSION}})
96114
**Note: no gurantees provided so please use your own discretion.**
+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: run-benchmark
2+
on:
3+
workflow_call:
4+
inputs:
5+
pullRequestJSON:
6+
required: true
7+
type: string
8+
outputs:
9+
replyMessage:
10+
value: ${{ jobs.benchmark.outputs.replyMessage }}
11+
jobs:
12+
benchmark:
13+
name: Run benchmark
14+
outputs:
15+
replyMessage: ${{ steps.set_replyMessage.outputs.replyMessage }}
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout repo
19+
uses: actions/checkout@v2
20+
with:
21+
persist-credentials: false
22+
ref: ${{ fromJSON(inputs.pullRequestJSON).merge_commit_sha }}
23+
24+
- name: Deepen cloned repo
25+
env:
26+
BASE_SHA: ${{ fromJSON(inputs.pullRequestJSON).base.sha }}
27+
run: 'git fetch --depth=1 origin $BASE_SHA:refs/tags/BASE'
28+
29+
- name: Setup Node.js
30+
uses: actions/setup-node@v2
31+
with:
32+
cache: npm
33+
node-version-file: '.node-version'
34+
35+
- name: Install Dependencies
36+
run: npm ci --ignore-scripts
37+
38+
- name: Run Benchmark
39+
run: |
40+
npm run benchmark -- --revs HEAD BASE | tee benchmark.log
41+
42+
- name: Set 'replyMessage' output variable
43+
id: set_replyMessage
44+
uses: actions/github-script@v5
45+
with:
46+
github-token: ${{secrets.GITHUB_TOKEN}}
47+
script: |
48+
const fs = require('fs');
49+
50+
const replyMessage = `
51+
<details>
52+
<summary> Benchmark output </summary>
53+
54+
${ fs.readFileSync('./benchmark.log', 'utf-8') }
55+
</details>
56+
`;
57+
core.setOutput('replyMessage', replyMessage);
+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
name: GitHubActionsBot
2+
on:
3+
issue_comment:
4+
types:
5+
- created
6+
7+
# We need to be call in context of the main branch to have write permissions
8+
# "pull_request" target is called in context of a fork
9+
# "pull_request_target" is called in context of the repository but not necessary latest main
10+
workflow_run:
11+
workflows:
12+
- PullRequestOpened
13+
types:
14+
- completed
15+
jobs:
16+
hello-message:
17+
if: github.event_name == 'workflow_run'
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Download event.json
21+
run: gh run download "$WORKFLOW_ID" --repo "$REPO" --name event.json
22+
env:
23+
REPO: ${{ github.repository }}
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
WORKFLOW_ID: ${{github.event.workflow_run.id}}
26+
27+
- name: Add comment on PR
28+
uses: actions/github-script@v5
29+
with:
30+
script: |
31+
const fs = require('fs');
32+
33+
const event = JSON.parse(fs.readFileSync('./event.json', 'utf8'));
34+
github.rest.issues.createComment({
35+
...context.repo,
36+
issue_number: event.pull_request.number,
37+
body:
38+
`Hi @${event.sender.login}, I'm @github-actions bot happy to help you with this PR 👋\n\n` +
39+
process.env.SUPPORTED_COMMANDS,
40+
})
41+
env:
42+
SUPPORTED_COMMANDS: |
43+
<details>
44+
<summary> Supported commands </summary>
45+
46+
Please post this commands in separate comments and only one per comment:
47+
* `@github-actions run-benchmark` - Run benchmark comparing base and merge commits for this PR
48+
* `@github-actions publish-pr-on-npm` - Build package from this PR and publish it on NPM
49+
</details>
50+
51+
accept-cmd:
52+
if: |
53+
github.event_name == 'issue_comment' &&
54+
github.event.issue.pull_request &&
55+
startsWith(github.event.comment.body, '@github-actions ')
56+
runs-on: ubuntu-latest
57+
outputs:
58+
cmd: ${{ steps.parse-cmd.outputs.cmd }}
59+
replyMessage: ${{ steps.parse-cmd.outputs.replyMessage }}
60+
pullRequestJSON: ${{ steps.get-pull_request-json.outputs.data }}
61+
steps:
62+
- uses: actions/github-script@v5
63+
with:
64+
script: |
65+
github.rest.reactions.createForIssueComment({
66+
...context.repo,
67+
comment_id: context.payload.comment.id,
68+
content: 'eyes',
69+
});
70+
71+
- id: parse-cmd
72+
uses: actions/github-script@v5
73+
with:
74+
script: |
75+
const cmd = context.payload.comment.body.replace('@github-actions', '').trim();
76+
core.setOutput('cmd', cmd);
77+
78+
- id: get-pull_request-json
79+
uses: octokit/request-action@v2.x
80+
with:
81+
route: GET ${{ github.event.issue.pull_request.url }}
82+
env:
83+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
84+
85+
cmd-publish-pr-on-npm:
86+
needs: [accept-cmd]
87+
if: needs.accept-cmd.outputs.cmd == 'publish-pr-on-npm'
88+
uses: ./.github/workflows/cmd-publish-pr-on-npm.yml
89+
with:
90+
pullRequestJSON: ${{ needs.accept-cmd.outputs.pullRequestJSON }}
91+
92+
cmd-run-benchmark:
93+
needs: [accept-cmd]
94+
if: needs.accept-cmd.outputs.cmd == 'run-benchmark'
95+
uses: ./.github/workflows/cmd-run-benchmark.yml
96+
with:
97+
pullRequestJSON: ${{ needs.accept-cmd.outputs.pullRequestJSON }}
98+
99+
respond-to-cmd:
100+
needs:
101+
- cmd-publish-pr-on-npm
102+
- cmd-run-benchmark
103+
if: github.event_name == 'issue_comment' && always()
104+
runs-on: ubuntu-latest
105+
steps:
106+
- uses: actions/github-script@v5
107+
with:
108+
script: |
109+
const { issue, comment, sender } = context.payload;
110+
const needs = JSON.parse(process.env.NEEDS);
111+
112+
let replyMessage;
113+
let allSkipped = true;
114+
for (const { result, outputs } of Object.values(needs)) {
115+
allSkipped = allSkipped && result === 'skipped';
116+
replyMessage = replyMessage || outputs.replyMessage;
117+
}
118+
119+
if (!replyMessage) {
120+
replyMessage = allSkipped
121+
? 'Unknown command, please check help message at the top of PR.'
122+
: `Something went wrong, please check logs here:\n${process.env.RUN_URL}`;
123+
}
124+
125+
const quoteRequest = comment.body
126+
.split('\n')
127+
.map((line) => '> ' + line)
128+
.join('\n');
129+
130+
github.rest.issues.createComment({
131+
...context.repo,
132+
issue_number: issue.number,
133+
body: quoteRequest + `\n\n@${sender.login} ` + replyMessage,
134+
});
135+
136+
// `github.rest` doesn't have this method :( so use graphql instead
137+
github.graphql(`
138+
mutation ($subjectId: ID!) {
139+
minimizeComment(input: { subjectId: $subjectId, classifier: RESOLVED})
140+
{ __typename }
141+
}
142+
`, { subjectId: comment.node_id });
143+
env:
144+
RUN_URL: ${{github.server_url}}/${{github.repository}}/actions/runs/${{github.run_id}}
145+
NEEDS: ${{ toJSON(needs) }}

‎.github/workflows/pull_request.yml

-26
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,6 @@ jobs:
44
ci:
55
uses: ./.github/workflows/ci.yml
66

7-
benchmark:
8-
name: Run benchmark
9-
runs-on: ubuntu-latest
10-
steps:
11-
- name: Checkout repo
12-
uses: actions/checkout@v2
13-
with:
14-
persist-credentials: false
15-
16-
- name: Deepen cloned repo
17-
env:
18-
BASE_SHA: ${{ github.event.pull_request.base.sha }}
19-
run: 'git fetch --depth=1 origin $BASE_SHA:refs/tags/BASE'
20-
21-
- name: Setup Node.js
22-
uses: actions/setup-node@v2
23-
with:
24-
cache: npm
25-
node-version-file: '.node-version'
26-
27-
- name: Install Dependencies
28-
run: npm ci --ignore-scripts
29-
30-
- name: Run Benchmark
31-
run: 'npm run benchmark -- --revs HEAD BASE'
32-
337
diff-npm-package:
348
name: Diff content of NPM package
359
runs-on: ubuntu-latest

0 commit comments

Comments
 (0)
Please sign in to comment.