Skip to content
This repository has been archived by the owner. It is now read-only.
Permalink
Browse files
Add triggering by workflow_run (#4)
  • Loading branch information
TobKed committed Oct 28, 2020
1 parent 7a38952 commit 7872312da76508d29f98d4fa68843ea91754cc59
Showing 4 changed files with 106 additions and 212 deletions.
@@ -15,8 +15,9 @@
- [Outputs](#outputs)
- [Examples](#examples)
- [Workflow Run event](#workflow-run-event)
- [Development environment](#development-environment)
- [License](#license)
- [Pull Request Review event](#pull-request-review-event)
- [Development environment](#development-environment)
- [License](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

@@ -31,6 +32,13 @@ The required input `require_committers_approval` says is approval can be done by
or by anyone. It may be useful in repositories which requires committers approvals like [Apache Software Foundation](https://github.com/apache/)
projects.

It can be used in workflows triggered by "pull_request_review" or "workflow_run".
When used on "pull_request_review" any workflows triggered from pull request created from fork will fail
due to insufficient permissions. Because of this support for "workflow_run" was added.
It should be triggered by workflows "pull_request_review" and requires additional input `pullRequestNumber`.
Pull request number can be obtained by using [potiuk/get-workflow-origin)](https://github.com/potiuk/get-workflow-origin) action (see example [workflow-run-event](#workflow-run-event)).


# Inputs and outputs

## Inputs
@@ -41,6 +49,7 @@ projects.
| `label` | no | `Approved by committers` | Label to be added/removed to the Pull Request if approved/not approved |
| `require_committers_approval` | no | `true` | Is approval from user with write permission required |
| `comment` | no | `PR approved by at least one committer and no changes requested.` | Add optional comment to the PR when approved (requires label input to be set) |
| `pullRequestNumber` | no | `${{ steps.source-run-info.outputs.pullRequestNumber }}` | Pull request number if triggered by "worfklow_run" |

## Outputs

@@ -54,6 +63,38 @@ projects.

### Workflow Run event

```yaml
name: "Label when approved"
on:
workflow_run:
workflows: ["Workflow triggered on pull_request_review"]
types: ['requested']
jobs:
label-when-approved:
name: "Label when approved"
runs-on: ubuntu-latest
steps:
- name: "Get information about the original trigger of the run"
uses: potiuk/get-workflow-origin@v1_2
id: source-run-info
with:
token: ${{ secrets.GITHUB_TOKEN }}
sourceRunId: ${{ github.event.workflow_run.id }}
- name: Label when approved by anyone
uses: TobKed/label-when-approved-action@v1.2
id: label-when-approved-by-anyone
with:
token: ${{ secrets.GITHUB_TOKEN }}
require_committers_approval: 'true'
label: 'Approved by committer'
comment: 'PR approved by at least one committer and no changes requested.'
pullRequestNumber: ${{ steps.source-run-info.outputs.pullRequestNumber }}
```

### Pull Request Review event

```yaml
name: Label when approved
on: pull_request_review
@@ -68,27 +109,26 @@ jobs:
isApprovedByAnyone: ${{ steps.label-when-approved-by-anyone.outputs.isApproved }}
steps:
- name: Label when approved by commiters
uses: TobKed/label-when-approved-action@v1.1
uses: TobKed/label-when-approved-action@v1.2
id: label-when-approved-by-commiters
with:
token: ${{ secrets.GITHUB_TOKEN }}
label: 'ready to merge (committers)'
require_committers_approval: 'true'
comment: 'PR approved by at least one committer and no changes requested.'
- name: Label when approved by anyone
uses: TobKed/label-when-approved-action@v1.1
uses: TobKed/label-when-approved-action@v1.2
id: label-when-approved-by-anyone
with:
token: ${{ secrets.GITHUB_TOKEN }}
```


## Development environment
# Development environment

It is highly recommended tu use [pre commit](https://pre-commit.com). The pre-commits
installed via pre-commit tool handle automatically linting (including automated fixes) as well
as building and packaging Javascript index.js from the main.ts Typescript code, so you do not have
to run it yourself.

## License
# License
[MIT License](LICENSE) covers the scripts and documentation in this project.
@@ -14,6 +14,9 @@ inputs:
comment:
description: 'Comment to be added to Pull Request if approved'
required: false
pullRequestNumber:
description: 'Pull request number if triggered by "worfklow_run"'
required: false
outputs:
isApproved:
description: 'Is Pull Reqeuest approved'
@@ -1470,15 +1470,9 @@ function verboseOutput(name, value) {
core.info(`Setting output: ${name}: ${value}`);
core.setOutput(name, value);
}
function getPullRequest(octokit, context, owner, repo) {
function getPullRequest(octokit, owner, repo, pullRequestNumber) {
return __awaiter(this, void 0, void 0, function* () {
const pullRequestNumber = context.payload.pull_request
? context.payload.pull_request.number
: null;
if (pullRequestNumber === null) {
throw Error(`Could not find PR number in context payload.`);
}
core.info(`pullRequestNumber: ${pullRequestNumber}`);
core.info(`Fetching pull request with number: ${pullRequestNumber}`);
const pullRequest = yield octokit.pulls.get({
owner,
repo,
@@ -1597,92 +1591,49 @@ function addComment(octokit, owner, repo, pullRequestNumber, comment) {
});
});
}
function getWorkflowId(octokit, runId, owner, repo) {
return __awaiter(this, void 0, void 0, function* () {
const reply = yield octokit.actions.getWorkflowRun({
owner,
repo,
// eslint-disable-next-line @typescript-eslint/camelcase
run_id: runId
});
core.info(`The source run ${runId} is in ${reply.data.workflow_url} workflow`);
const workflowIdString = reply.data.workflow_url.split('/').pop() || '';
if (!(workflowIdString.length > 0)) {
throw new Error('Could not resolve workflow');
}
return parseInt(workflowIdString);
});
}
function getPrWorkflowRunsIds(octokit, owner, repo, branch, sha, skipRunId) {
return __awaiter(this, void 0, void 0, function* () {
const workflowRuns = yield octokit.actions.listRepoWorkflowRuns({
owner,
repo,
branch,
event: 'pull_request',
status: 'completed',
// eslint-disable-next-line @typescript-eslint/camelcase
per_page: 100
});
// may be no need to rerun pending/queued runs
const filteredRunsIds = [];
const filteredWorklowRunsIds = [];
for (const workflowRun of workflowRuns.data.workflow_runs) {
const workflowId = parseInt(workflowRun.workflow_url.split('/').pop() || '0');
if (workflowRun.head_sha === sha &&
!filteredRunsIds.includes(workflowId) &&
workflowId !== skipRunId) {
filteredRunsIds.push(workflowId);
filteredWorklowRunsIds.push(workflowRun.id);
}
}
return filteredWorklowRunsIds;
});
}
function rerunWorkflows(octokit, owner, repo, runIds) {
return __awaiter(this, void 0, void 0, function* () {
core.info(`Rerun worklowws: ${runIds}`);
for (const runId of runIds) {
yield octokit.actions.reRunWorkflow({
owner,
repo,
// eslint-disable-next-line @typescript-eslint/camelcase
run_id: runId
});
}
});
}
function printDebug(item, description) {
function printDebug(item, description = '') {
return __awaiter(this, void 0, void 0, function* () {
const itemJson = JSON.stringify(item);
core.info(`\n ######### ${description} ######### \n: ${itemJson}\n\n`);
core.debug(`\n ######### ${description} ######### \n: ${itemJson}\n\n`);
});
}
function run() {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
const token = core.getInput('token', { required: true });
const userLabel = core.getInput('label') || 'not set';
const requireCommittersApproval = core.getInput('require_committers_approval') === 'true';
const comment = core.getInput('comment') || '';
const pullRequestNumberInput = core.getInput('pullRequestNumber') || 'not set';
const octokit = new github.GitHub(token);
const context = github.context;
const repository = getRequiredEnv('GITHUB_REPOSITORY');
const eventName = getRequiredEnv('GITHUB_EVENT_NAME');
const selfRunId = parseInt(getRequiredEnv('GITHUB_RUN_ID'));
const [owner, repo] = repository.split('/');
const selfWorkflowId = yield getWorkflowId(octokit, selfRunId, owner, repo);
const branch = (_a = context.payload.pull_request) === null || _a === void 0 ? void 0 : _a.head.ref;
const sha = (_b = context.payload.pull_request) === null || _b === void 0 ? void 0 : _b.head.sha;
let pullRequestNumber;
core.info(`\n############### Set Label When Approved start ##################\n` +
`label: "${userLabel}"\n` +
`requireCommittersApproval: ${requireCommittersApproval}\n` +
`comment: ${comment}`);
if (eventName !== 'pull_request_review') {
throw Error(`This action is only useful in "pull_request_review" triggered runs and you used it in "${eventName}"`);
`comment: ${comment}\n` +
`pullRequestNumber: ${pullRequestNumberInput}`);
if (eventName === 'pull_request_review') {
pullRequestNumber = context.payload.pull_request
? context.payload.pull_request.number
: undefined;
if (pullRequestNumber === undefined) {
throw Error(`Could not find PR number in context payload.`);
}
}
else if (eventName === 'workflow_run') {
if (pullRequestNumberInput === 'not set') {
throw Error(`If action is triggered by "workflow_run" then input "pullRequestNumber" is required.`);
}
pullRequestNumber = parseInt(pullRequestNumberInput);
}
else {
throw Error(`This action is only useful in "pull_request_review" or "workflow_run" triggered runs and you used it in "${eventName}"`);
}
// PULL REQUEST
const pullRequest = yield getPullRequest(octokit, context, owner, repo);
const pullRequest = yield getPullRequest(octokit, owner, repo, pullRequestNumber);
// LABELS
const labelNames = getPullRequestLabels(pullRequest);
// REVIEWS
@@ -1704,23 +1655,6 @@ function run() {
yield removeLabel(octokit, owner, repo, pullRequest.number, userLabel);
}
}
//// Future option to rerun workflows if PR approved
//// Rerun workflow can have dynamic matrixes which check presence of labels
//// it is not possible to rerun successful runs
//// https://github.community/t/cannot-re-run-a-successful-workflow-run-using-the-rest-api/123661
//
// if (isLabelShouldBeSet) {
// const prWorkflowRunsIds = await getPrWorkflowRunsIds(
// octokit,
// owner,
// repo,
// branch,
// sha,
// selfWorkflowId
// )
//
// await rerunWorkflows(octokit, owner, repo, prWorkflowRunsIds)
// }
// OUTPUT
verboseOutput('isApproved', String(isApproved));
verboseOutput('labelSet', String(isLabelShouldBeSet));

0 comments on commit 7872312

Please sign in to comment.