Add initial support for schedule, and refactor accordingly
diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts
index e237067..819d5d4 100644
--- a/__tests__/main.test.ts
+++ b/__tests__/main.test.ts
@@ -7,16 +7,19 @@
// shows how the runner will run a javascript action with env / stdout protocol
// test('test runs', () => {
// const ip = path.join(__dirname, '..', 'lib', 'main.js')
-// process.env['INPUT_TOKEN'] = ''
-// process.env['GITHUB_RUN_ID'] = '35588693' //'33782469'
-// process.env['GITHUB_REPOSITORY'] = ''
-// process.env['GITHUB_HEAD_REF'] = 'refs/heads/n1hility-patch-5'
-// process.env['GITHUB_EVENT_NAME'] = 'pull_request'
+// process.env['INPUT_TOKEN'] = ''
+// //process.env['INPUT_WORKFLOW'] = 'ci-actions.yml'
+// process.env['GITHUB_RUN_ID'] = '41374869' //'33782469'
+// process.env['GITHUB_REPOSITORY'] = ''
+// //process.env['GITHUB_HEAD_REF'] = 'refs/heads/n1hility-patch-5'
+// process.env['GITHUB_REF'] = 'refs/heads/master'
+// process.env['GITHUB_EVENT_NAME'] = 'push'
+// // process.env['GITHUB_EVENT_NAME'] = 'schedule'
-// // process.env['GITHUB_RUN_ID'] = '35599067'
-// // process.env['GITHUB_REPOSITORY'] = ''
-// // process.env['GITHUB_REF'] = 'refs/heads/master'
-// // process.env['GITHUB_EVENT_NAME'] = 'push'
+// // process.env['GITHUB_RUN_ID'] = '35599067'
+// // process.env['GITHUB_REPOSITORY'] = ''
+// // process.env['GITHUB_REF'] = 'refs/heads/master'
+// // process.env['GITHUB_EVENT_NAME'] = 'push'
// const options: cp.ExecSyncOptions = {
// env: process.env
diff --git a/dist/index.js b/dist/index.js
index a5661b6..16c7215 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1465,17 +1465,104 @@
Object.defineProperty(exports, "__esModule", { value: true });
const github = __importStar(__webpack_require__(469));
const core = __importStar(__webpack_require__(393));
-function run() {
+function cancelDuplicates(token, selfRunId, owner, repo, workflowId, branch, event) {
var e_1, _a;
return __awaiter(this, void 0, void 0, function* () {
+ const octokit = new github.GitHub(token);
+ // Deteermind the workflow to reduce the result set, or reference anothre workflow
+ let resolvedId;
+ if (workflowId === undefined) {
+ const reply = yield octokit.actions.getWorkflowRun({
+ owner,
+ repo,
+ // eslint-disable-next-line @typescript-eslint/camelcase
+ run_id: Number.parseInt(selfRunId)
+ });
+ resolvedId = reply.data.workflow_url.split('/').pop();
+ }
+ else {
+ resolvedId = workflowId;
+ }
+ core.info(`Workflow ID is: ${resolvedId}`);
+ const request = branch === undefined
+ ? {
+ owner,
+ repo,
+ // eslint-disable-next-line @typescript-eslint/camelcase
+ workflow_id: resolvedId
+ }
+ : {
+ owner,
+ repo,
+ // eslint-disable-next-line @typescript-eslint/camelcase
+ workflow_id: resolvedId,
+ branch,
+ event
+ };
+ const listRuns = octokit.actions.listWorkflowRuns.endpoint.merge(request);
+ // If a workflow was provided process everything
+ let matched = workflowId !== undefined;
+ const heads = new Set();
+ try {
+ for (var _b = __asyncValues(octokit.paginate.iterator(listRuns)), _c; _c = yield _b.next(), !_c.done;) {
+ const item = _c.value;
+ // There is some sort of bug where the pagination URLs point to a
+ // different endpoint URL which trips up the resulting representation
+ // In that case, fallback to the actual REST 'workflow_runs' property
+ const elements = item.data.length === undefined ? item.data.workflow_runs : item.data;
+ for (const element of elements) {
+ core.info(`${element.id} : ${element.workflow_url} : ${element.status} : ${element.run_number}`);
+ if (!matched) {
+ if (element.id.toString() !== selfRunId) {
+ // Skip everything up to this run
+ continue;
+ }
+ matched = true;
+ core.info(`Matched ${selfRunId}`);
+ }
+ if ('completed' === element.status.toString()) {
+ continue;
+ }
+ // This is a set of one in the non-schedule case, otherwise everything is a candidate
+ const head = `${element.head_repository.full_name}/${element.head_branch}`;
+ if (!heads.has(head)) {
+ core.info(`First: ${head}`);
+ heads.add(head);
+ continue;
+ }
+ core.info(`Cancelling: ${head}`);
+ yield cancelRun(octokit, owner, repo, element.id);
+ }
+ }
+ }
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
+ finally {
+ try {
+ if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
+ }
+ finally { if (e_1) throw e_1.error; }
+ }
+ });
+}
+function run() {
+ return __awaiter(this, void 0, void 0, function* () {
try {
const token = core.getInput('token');
+ core.info(token);
const selfRunId = getRequiredEnv('GITHUB_RUN_ID');
const repository = getRequiredEnv('GITHUB_REPOSITORY');
const eventName = getRequiredEnv('GITHUB_EVENT_NAME');
const [owner, repo] = repository.split('/');
const branchPrefix = 'refs/heads/';
const tagPrefix = 'refs/tags/';
+ if ('schedule' === eventName) {
+ const workflowId = core.getInput('workflow');
+ if (!(workflowId.length > 0)) {
+ throw new Error('Workflow must be specified for schedule event type');
+ }
+ yield cancelDuplicates(token, selfRunId, owner, repo, workflowId);
+ return;
+ }
if (!['push', 'pull_request'].includes(eventName)) {
core.info('Skipping unsupported event');
return;
@@ -1492,50 +1579,7 @@
}
branch = branch.replace(branchPrefix, '');
core.info(`Branch is ${branch}, repo is ${repo}, and owner is ${owner}, and id is ${selfRunId}`);
- const octokit = new github.GitHub(token);
- const listRuns = octokit.actions.listRepoWorkflowRuns.endpoint.merge({
- owner,
- repo,
- branch,
- event: pullRequest ? 'pull_request' : 'push'
- });
- let matched = false;
- let workflow = '';
- let headRepoName = '';
- try {
- for (var _b = __asyncValues(octokit.paginate.iterator(listRuns)), _c; _c = yield _b.next(), !_c.done;) {
- const item = _c.value;
- // There is some sort of bug where the pagination URLs point to a
- // different endpoint URL which trips up the resulting representation
- // In that case, fallback to the actual REST 'workflow_runs' property
- const elements = item.data.length === undefined ? item.data.workflow_runs : item.data;
- for (const element of elements) {
- core.info(`${element.id} : ${element.workflow_url} : ${element.status} : ${element.run_number}`);
- if (!matched) {
- if (element.id.toString() === selfRunId) {
- matched = true;
- workflow = element.workflow_url;
- headRepoName = pullRequest ? element.head_repository.full_name : '';
- }
- // Skip everything up to and matching this run
- continue;
- }
- // Only cancel jobs with the same workflow
- if (workflow === element.workflow_url &&
- element.status.toString() !== 'completed' &&
- (!pullRequest || headRepoName === element.head_repository.full_name)) {
- yield cancelRun(octokit, owner, repo, element.id);
- }
- }
- }
- }
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
- finally {
- try {
- if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
- }
- finally { if (e_1) throw e_1.error; }
- }
+ cancelDuplicates(token, selfRunId, owner, repo, undefined, branch, eventName);
}
catch (error) {
core.setFailed(error.message);
diff --git a/src/main.ts b/src/main.ts
index c99a264..9ae7083 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,10 +1,103 @@
import * as github from '@actions/github'
import * as core from '@actions/core'
+async function cancelDuplicates(
+ token: string,
+ selfRunId: string,
+ owner: string,
+ repo: string,
+ workflowId?: string,
+ branch?: string,
+ event?: string
+): Promise<void> {
+ const octokit = new github.GitHub(token)
+
+ // Deteermind the workflow to reduce the result set, or reference anothre workflow
+ let resolvedId
+ if (workflowId === undefined) {
+ const reply = await octokit.actions.getWorkflowRun({
+ owner,
+ repo,
+ // eslint-disable-next-line @typescript-eslint/camelcase
+ run_id: Number.parseInt(selfRunId)
+ })
+
+ resolvedId = reply.data.workflow_url.split('/').pop()
+ } else {
+ resolvedId = workflowId
+ }
+
+ core.info(`Workflow ID is: ${resolvedId}`)
+
+ const request =
+ branch === undefined
+ ? {
+ owner,
+ repo,
+ // eslint-disable-next-line @typescript-eslint/camelcase
+ workflow_id: resolvedId
+ }
+ : {
+ owner,
+ repo,
+ // eslint-disable-next-line @typescript-eslint/camelcase
+ workflow_id: resolvedId,
+ branch,
+ event
+ }
+
+ const listRuns = octokit.actions.listWorkflowRuns.endpoint.merge(request)
+
+ // If a workflow was provided process everything
+ let matched = workflowId !== undefined
+ const heads = new Set()
+ for await (const item of octokit.paginate.iterator(listRuns)) {
+ // There is some sort of bug where the pagination URLs point to a
+ // different endpoint URL which trips up the resulting representation
+ // In that case, fallback to the actual REST 'workflow_runs' property
+ const elements =
+ item.data.length === undefined ? item.data.workflow_runs : item.data
+
+ for (const element of elements) {
+ core.info(
+ `${element.id} : ${element.workflow_url} : ${element.status} : ${element.run_number}`
+ )
+
+ if (!matched) {
+ if (element.id.toString() !== selfRunId) {
+ // Skip everything up to this run
+ continue
+ }
+
+ matched = true
+ core.info(`Matched ${selfRunId}`)
+ }
+
+ if ('completed' === element.status.toString()) {
+ continue
+ }
+
+ // This is a set of one in the non-schedule case, otherwise everything is a candidate
+ const head = `${element.head_repository.full_name}/${element.head_branch}`
+ if (!heads.has(head)) {
+ core.info(`First: ${head}`)
+ heads.add(head)
+ continue
+ }
+
+ core.info(`Cancelling: ${head}`)
+
+ await cancelRun(octokit, owner, repo, element.id)
+ }
+ }
+}
+
async function run(): Promise<void> {
try {
const token = core.getInput('token')
+ core.info(token)
+
const selfRunId = getRequiredEnv('GITHUB_RUN_ID')
const repository = getRequiredEnv('GITHUB_REPOSITORY')
const eventName = getRequiredEnv('GITHUB_EVENT_NAME')
@@ -13,6 +106,15 @@
const branchPrefix = 'refs/heads/'
const tagPrefix = 'refs/tags/'
+ if ('schedule' === eventName) {
+ const workflowId = core.getInput('workflow')
+ if (!(workflowId.length > 0)) {
+ throw new Error('Workflow must be specified for schedule event type')
+ }
+ await cancelDuplicates(token, selfRunId, owner, repo, workflowId)
+ return
+ }
+
if (!['push', 'pull_request'].includes(eventName)) {
core.info('Skipping unsupported event')
return
@@ -35,49 +137,15 @@
`Branch is ${branch}, repo is ${repo}, and owner is ${owner}, and id is ${selfRunId}`
)
- const octokit = new github.GitHub(token)
- const listRuns = octokit.actions.listRepoWorkflowRuns.endpoint.merge({
+ cancelDuplicates(
+ token,
+ selfRunId,
owner,
repo,
+ undefined,
branch,
- event: pullRequest ? 'pull_request' : 'push'
- })
-
- let matched = false
- let workflow = ''
- let headRepoName = ''
- for await (const item of octokit.paginate.iterator(listRuns)) {
- // There is some sort of bug where the pagination URLs point to a
- // different endpoint URL which trips up the resulting representation
- // In that case, fallback to the actual REST 'workflow_runs' property
- const elements =
- item.data.length === undefined ? item.data.workflow_runs : item.data
-
- for (const element of elements) {
- core.info(
- `${element.id} : ${element.workflow_url} : ${element.status} : ${element.run_number}`
- )
-
- if (!matched) {
- if (element.id.toString() === selfRunId) {
- matched = true
- workflow = element.workflow_url
- headRepoName = pullRequest ? element.head_repository.full_name : ''
- }
- // Skip everything up to and matching this run
- continue
- }
-
- // Only cancel jobs with the same workflow
- if (
- workflow === element.workflow_url &&
- element.status.toString() !== 'completed' &&
- (!pullRequest || headRepoName === element.head_repository.full_name)
- ) {
- await cancelRun(octokit, owner, repo, element.id)
- }
- }
- }
+ eventName
+ )
} catch (error) {
core.setFailed(error.message)
}