Skip to content

Commit

Permalink
Add Waiting for pipeline
Browse files Browse the repository at this point in the history
  • Loading branch information
LecrisUT committed Aug 24, 2023
1 parent 29f83dd commit fdb2fad
Show file tree
Hide file tree
Showing 4 changed files with 240 additions and 4 deletions.
11 changes: 11 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ inputs:
target-tag:
required: false
description: 'The tag of the target CircleCI project. Will default to the current tag name if set. This or branch should be overwritten if "target-slug" is set. Can be overwritten with "TARGET_TAG" environment variable.'
wait-for-pipeline:
required: false
description: 'Wait for pipeline to finish'
wait-for-pipeline-timeout:
required: false
default: "300"
description: 'Wait for pipeline timeout'
wait-for-pipeline-interval:
required: false
default: "10"
description: 'Wait for pipeline to finish'
outputs:
id:
description: The unique ID of the pipeline.
Expand Down
115 changes: 113 additions & 2 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16375,6 +16375,110 @@ class CircleCIPipelineTrigger extends CircleCIBase_1.CircleCIBase {
exports.CircleCIPipelineTrigger = CircleCIPipelineTrigger;


/***/ }),

/***/ 7860:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {

"use strict";

var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.CircleCIPipelineWait = void 0;
const core_1 = __nccwpck_require__(2186);
const axios_1 = __importDefault(__nccwpck_require__(6545));
const CircleCIBase_1 = __nccwpck_require__(9164);
class CircleCIPipelineWait extends CircleCIBase_1.CircleCIBase {
constructor(context, host = process.env.CCI_HOST || "circleci.com") {
super(context, host);
this.wait_for_pipeline = undefined;
this.base_url = `https://${this.host}/api/v2/project/${this.vcs}/${this.owner}/${this.repo}`;
if (JSON.parse((0, core_1.getInput)("wait-for-pipeline").toLowerCase())) {
this.wait_for_pipeline = {
timeout: Number((0, core_1.getInput)("wait-for-pipeline-timeout")),
interval: Number((0, core_1.getInput)("wait-for-pipeline-interval")),
};
}
}
checkWorkflow(workflow_url, params = undefined) {
return axios_1.default
.get(workflow_url, {
headers: {
"content-type": "application/json",
"x-attribution-login": this.context.actor,
"x-attribution-actor-id": this.context.actor,
"Circle-Token": `${process.env.CCI_TOKEN}`,
},
params: params,
})
.then((response) => {
let finished = true;
// Check status of all workflows
for (const workflow of response.data.items) {
switch (workflow.status) {
// Do not do anything special for failing, wait for failed state
case "failing":
case "running":
case "on_hold":
finished = false;
break;
case "failed":
case "not_run":
case "error":
case "unauthorized":
case "canceled":
// Accumulate any failed workflow states
(0, core_1.setFailed)(`Failed workflow: ${workflow.name} as ${workflow.status}`);
break;
case "success":
break;
default:
(0, core_1.setFailed)(`Unrecognized workflow state: ${workflow.status}\nDetails: ${workflow}`);
}
}
// Accumulate the next page results
if (response.data.next_page_token) {
params = {
"next_page_token": response.data.next_page_token,
};
}
if (params) {
// Finished only when all workflow pages are finished
return finished && this.checkWorkflow(workflow_url, params);
}
return finished;
})
.catch((error) => {
(0, core_1.setFailed)(error);
// Return as finished
return true;
});
}
waitForPipeline(pipeline_id) {
// If not requested to wait for pipeline just return
if (!this.wait_for_pipeline)
return;
const workflow_url = `https://${this.host}/api/v2/pipeline/${pipeline_id}/workflow`;
(0, core_1.startGroup)("Waiting for pipeline to finish");
const waitInterval = setInterval(async () => {
const finished = await this.checkWorkflow(workflow_url);
if (finished) {
clearInterval(waitInterval);
clearTimeout(waitTimeout);
}
}, this.wait_for_pipeline.interval * 1000);
const waitTimeout = setTimeout(() => {
clearInterval(waitInterval);
(0, core_1.setFailed)(`Pipeline did not finish in ${this.wait_for_pipeline?.timeout} (s)`);
}, this.wait_for_pipeline.timeout * 1000);
(0, core_1.endGroup)();
}
}
exports.CircleCIPipelineWait = CircleCIPipelineWait;


/***/ }),

/***/ 2877:
Expand Down Expand Up @@ -16576,8 +16680,15 @@ var exports = __webpack_exports__;
Object.defineProperty(exports, "__esModule", ({ value: true }));
const CircleCIPipelineTrigger_1 = __nccwpck_require__(1373);
const github_1 = __nccwpck_require__(5438);
const trigger = new CircleCIPipelineTrigger_1.CircleCIPipelineTrigger(github_1.context);
trigger.triggerPipeline();
const CircleCIPipelineWait_1 = __nccwpck_require__(7860);
const main = async () => {
const trigger = new CircleCIPipelineTrigger_1.CircleCIPipelineTrigger(github_1.context);
const pipelineID = await trigger.triggerPipeline();
if (pipelineID) {
const waiter = new CircleCIPipelineWait_1.CircleCIPipelineWait(github_1.context);
waiter.waitForPipeline(pipelineID);
}
};

})();

Expand Down
11 changes: 9 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { CircleCIPipelineTrigger } from "./lib/CircleCIPipelineTrigger";
import { context } from "@actions/github";
import { CircleCIPipelineWait } from "./lib/CircleCIPipelineWait";

const trigger = new CircleCIPipelineTrigger(context);
trigger.triggerPipeline();
const main = async () => {
const trigger = new CircleCIPipelineTrigger(context);
const pipelineID = await trigger.triggerPipeline();
if (pipelineID) {
const waiter = new CircleCIPipelineWait(context);
waiter.waitForPipeline(pipelineID);
}
};
107 changes: 107 additions & 0 deletions src/lib/CircleCIPipelineWait.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {
getInput,
setFailed,
startGroup,
endGroup,
} from "@actions/core";
import axios from "axios";
import {Context} from "@actions/github/lib/context";
import {CircleCIBase} from "./CircleCIBase";

export class CircleCIPipelineWait extends CircleCIBase {
wait_for_pipeline?: CircleCIWaitRequest = undefined;

constructor(context: Context, host = process.env.CCI_HOST || "circleci.com") {
super(context, host)
this.base_url = `https://${this.host}/api/v2/project/${this.vcs}/${this.owner}/${this.repo}`;
if (JSON.parse(getInput("wait-for-pipeline").toLowerCase())) {
this.wait_for_pipeline = {
timeout: Number(getInput("wait-for-pipeline-timeout")),
interval: Number(getInput("wait-for-pipeline-interval")),
}
}
}

checkWorkflow(workflow_url: string, params: { [key: string]: string } | undefined = undefined): Promise<boolean> {
return axios
.get(workflow_url, {
headers: {
"content-type": "application/json",
"x-attribution-login": this.context.actor,
"x-attribution-actor-id": this.context.actor,
"Circle-Token": `${process.env.CCI_TOKEN}`,
},
params: params,
})
.then((response) => {
let finished = true;
// Check status of all workflows
for (const workflow of response.data.items) {
switch (workflow.status) {
// Do not do anything special for failing, wait for failed state
case "failing":
case "running":
case "on_hold":
finished = false
break;
case "failed":
case "not_run":
case "error":
case "unauthorized":
case "canceled":
// Accumulate any failed workflow states
setFailed(`Failed workflow: ${workflow.name} as ${workflow.status}`)
break;
case "success":
break;
default:
setFailed(`Unrecognized workflow state: ${workflow.status}\nDetails: ${workflow}`);
}
}
// Accumulate the next page results
if (response.data.next_page_token) {
params = {
"next_page_token": response.data.next_page_token,
}
}
if (params) {
// Finished only when all workflow pages are finished
return finished && this.checkWorkflow(workflow_url, params);
}
return finished;
})
.catch((error) => {
setFailed(error);
// Return as finished
return true
});
}

waitForPipeline(pipeline_id: string) {
// If not requested to wait for pipeline just return
if (!this.wait_for_pipeline)
return
const workflow_url = `https://${this.host}/api/v2/pipeline/${pipeline_id}/workflow`;
startGroup("Waiting for pipeline to finish");
const waitInterval = setInterval(
async () => {
const finished = await this.checkWorkflow(workflow_url);
if (finished) {
clearInterval(waitInterval);
clearTimeout(waitTimeout);
}
}, this.wait_for_pipeline.interval * 1000
);
const waitTimeout = setTimeout(() => {
clearInterval(waitInterval);
setFailed(`Pipeline did not finish in ${this.wait_for_pipeline?.timeout} (s)`);
}, this.wait_for_pipeline.timeout * 1000);
endGroup()
}
}

type CircleCIWaitRequest = {
timeout: number;
interval: number;
}

0 comments on commit fdb2fad

Please sign in to comment.