Skip to content

Commit

Permalink
ci: Add '@github-actions' bot
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanGoncharov committed Mar 28, 2022
1 parent 6407307 commit d170eb7
Show file tree
Hide file tree
Showing 6 changed files with 268 additions and 70 deletions.
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

0 comments on commit d170eb7

Please sign in to comment.