Skip to content

Commit

Permalink
Merge pull request #1 from mrbrannan/main
Browse files Browse the repository at this point in the history
Add DQ by job
  • Loading branch information
mrbrannan authored Aug 23, 2021
2 parents f356bfc + fe2e6d9 commit 2ad5dce
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 16 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,27 @@ jobs:

_Note_ : This is typical when global access is set to be restrictive. Only this job will elevate those permissions.

### Advanced: Disqualifying Jobs

In the case where you may want for an `in_progress` job to stop the cancellation of a workflow you may pass a JSON Array as input to `disqualifying_jobs`. If a job is named in the array and its `status` is `in_progress` the workflow will be removed from the list of jobs to cancel and skipped.

This is useful for operations such as static site deployment where two jobs have the ability to read/write files simultaneously which could cause downtime or runtime errors.

```yml
name: Cancel
on: [push]
jobs:
cancel:
name: 'Cancel Previous Runs'
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: styfle/[email protected]
with:
access_token: ${{ github.token }}
disqualifying_jobs: '["deploy"]'
```

## Contributing

- Clone this repo
Expand Down
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ inputs:
description: "Cancel all actions but the last one"
required: false
default: 'false'
disqualifying_jobs:
description: "A JSON array of named jobs that will stop cancellation if in progress. Usefull for jobs like deployments where cancellation could risk downtime."
required: false
runs:
using: 'node12'
main: 'dist/index.js'
59 changes: 44 additions & 15 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5893,103 +5893,103 @@ module.exports = eval("require")("encoding");
/***/ ((module) => {

"use strict";
module.exports = require("assert");;
module.exports = require("assert");

/***/ }),

/***/ 614:
/***/ ((module) => {

"use strict";
module.exports = require("events");;
module.exports = require("events");

/***/ }),

/***/ 747:
/***/ ((module) => {

"use strict";
module.exports = require("fs");;
module.exports = require("fs");

/***/ }),

/***/ 605:
/***/ ((module) => {

"use strict";
module.exports = require("http");;
module.exports = require("http");

/***/ }),

/***/ 211:
/***/ ((module) => {

"use strict";
module.exports = require("https");;
module.exports = require("https");

/***/ }),

/***/ 631:
/***/ ((module) => {

"use strict";
module.exports = require("net");;
module.exports = require("net");

/***/ }),

/***/ 87:
/***/ ((module) => {

"use strict";
module.exports = require("os");;
module.exports = require("os");

/***/ }),

/***/ 622:
/***/ ((module) => {

"use strict";
module.exports = require("path");;
module.exports = require("path");

/***/ }),

/***/ 413:
/***/ ((module) => {

"use strict";
module.exports = require("stream");;
module.exports = require("stream");

/***/ }),

/***/ 16:
/***/ ((module) => {

"use strict";
module.exports = require("tls");;
module.exports = require("tls");

/***/ }),

/***/ 835:
/***/ ((module) => {

"use strict";
module.exports = require("url");;
module.exports = require("url");

/***/ }),

/***/ 669:
/***/ ((module) => {

"use strict";
module.exports = require("util");;
module.exports = require("util");

/***/ }),

/***/ 761:
/***/ ((module) => {

"use strict";
module.exports = require("zlib");;
module.exports = require("zlib");

/***/ })

Expand Down Expand Up @@ -6068,7 +6068,9 @@ module.exports = require("zlib");;
/******/
/******/ /* webpack/runtime/compat */
/******/
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";/************************************************************************/
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
Expand Down Expand Up @@ -6102,9 +6104,14 @@ async function main() {
console.log({ eventName, sha, headSha, branch, owner, repo, GITHUB_RUN_ID });
const token = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('access_token', { required: true });
const workflow_id = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('workflow_id', { required: false });
const disqualifying_jobs_input = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput('disqualifying_jobs', { required: false });
const disqualifying_jobs = disqualifying_jobs_input ? JSON.parse(disqualifying_jobs_input) : null;
const ignore_sha = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getBooleanInput('ignore_sha', { required: false });
const all_but_latest = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getBooleanInput('all_but_latest', { required: false });
console.log(`Found token: ${token ? 'yes' : 'no'}`);
console.log(disqualifying_jobs
? `Skipping cancel if job in ${disqualifying_jobs}`
: 'No disqualifying jobs');
const workflow_ids = [];
const octokit = _actions_github__WEBPACK_IMPORTED_MODULE_1__.getOctokit(token);
const { data: current_run } = await octokit.actions.getWorkflowRun({
Expand Down Expand Up @@ -6140,7 +6147,29 @@ async function main() {
.reduce((a, b) => Math.max(a, b), cancelBefore.getTime());
cancelBefore = new Date(n);
}
const runningWorkflows = workflow_runs.filter(run => run.head_repository.id === trigger_repo_id &&
if (disqualifying_jobs && !Array.isArray(disqualifying_jobs)) {
_actions_core__WEBPACK_IMPORTED_MODULE_0__.setFailed('Disqualifying jobs found but is not array');
}
const workflow_jobs = (disqualifying_jobs && disqualifying_jobs.length > 0
? await Promise.all(workflow_runs.map(async ({ id, jobs_url }) => {
const { data: { jobs }, } = await octokit.request(`GET ${jobs_url}`, {
owner,
repo,
run_id: id,
});
return {
workflow_run_id: id,
jobs: jobs.filter(({ status, name }) => status === 'in_progress' && disqualifying_jobs.includes(name)),
};
}))
: []).filter(workflow => workflow.jobs.length > 0);
let workflow_runs_to_cancel = [...workflow_runs];
if (workflow_jobs.length) {
console.log('Found disqualifying jobs running, skipping cancel', workflow_jobs);
const workflows_to_skip = workflow_jobs.map(({ workflow_run_id }) => workflow_run_id);
workflow_runs_to_cancel = workflow_runs.filter(({ id }) => !workflows_to_skip.includes(id));
}
const runningWorkflows = workflow_runs_to_cancel.filter(run => run.head_repository.id === trigger_repo_id &&
run.id !== current_run.id &&
(ignore_sha || run.head_sha !== headSha) &&
run.status !== 'completed' &&
Expand Down
47 changes: 46 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,16 @@ async function main() {
console.log({ eventName, sha, headSha, branch, owner, repo, GITHUB_RUN_ID });
const token = core.getInput('access_token', { required: true });
const workflow_id = core.getInput('workflow_id', { required: false });
const disqualifying_jobs_input = core.getInput('disqualifying_jobs', { required: false });
const disqualifying_jobs = disqualifying_jobs_input ? JSON.parse(disqualifying_jobs_input) : null;
const ignore_sha = core.getBooleanInput('ignore_sha', { required: false });
const all_but_latest = core.getBooleanInput('all_but_latest', { required: false });
console.log(`Found token: ${token ? 'yes' : 'no'}`);
console.log(
disqualifying_jobs
? `Skipping cancel if job in ${disqualifying_jobs}`
: 'No disqualifying jobs',
);
const workflow_ids: string[] = [];
const octokit = github.getOctokit(token);

Expand Down Expand Up @@ -77,7 +84,45 @@ async function main() {
.reduce((a, b) => Math.max(a, b), cancelBefore.getTime());
cancelBefore = new Date(n);
}
const runningWorkflows = workflow_runs.filter(

if (disqualifying_jobs && !Array.isArray(disqualifying_jobs)) {
core.setFailed('Disqualifying jobs found but is not array');
}

const workflow_jobs = (
disqualifying_jobs && disqualifying_jobs.length > 0
? await Promise.all(
workflow_runs.map(async ({ id, jobs_url }) => {
const {
data: { jobs },
} = await octokit.request(`GET ${jobs_url}`, {
owner,
repo,
run_id: id,
});
return {
workflow_run_id: id,
jobs: jobs.filter(
({ status, name }: any) =>
status === 'in_progress' && disqualifying_jobs.includes(name),
),
};
}),
)
: []
).filter(workflow => workflow.jobs.length > 0);

let workflow_runs_to_cancel = [...workflow_runs];

if (workflow_jobs.length) {
console.log('Found disqualifying jobs running, skipping cancel', workflow_jobs);
const workflows_to_skip = workflow_jobs.map(({ workflow_run_id }) => workflow_run_id);
workflow_runs_to_cancel = workflow_runs.filter(
({ id }: any) => !workflows_to_skip.includes(id),
);
}

const runningWorkflows = workflow_runs_to_cancel.filter(
run =>
run.head_repository.id === trigger_repo_id &&
run.id !== current_run.id &&
Expand Down

0 comments on commit 2ad5dce

Please sign in to comment.