From 5d47e3d695793db309166fa556fa90b8f5d3c1da Mon Sep 17 00:00:00 2001
From: Steven Cleve <107827476+stevencl840@users.noreply.github.com>
Date: Wed, 18 Dec 2024 13:22:22 +1100
Subject: [PATCH] feat: Added Git Runbook support (#432)
* Added Git Runbook support
* Upgraded to latest API client
* Include built action file
---
README.md | 19 +--
action.yml | 2 +
dist/index.js | 341 +++++++++++++++++++++++++++++++++++-----
package-lock.json | 14 +-
package.json | 2 +-
src/api-wrapper.ts | 48 ++++++
src/input-parameters.ts | 4 +-
7 files changed, 372 insertions(+), 58 deletions(-)
diff --git a/README.md b/README.md
index 254a2a71..13641338 100644
--- a/README.md
+++ b/README.md
@@ -41,15 +41,16 @@ steps:
## 📥 Inputs
-| Name | Description |
-| :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `project` | **Required.** The name of the project associated with this runbook. |
-| `runbook` | **Required.** The name of the runbook. |
-| `environments` | **Required.** A list of environments in Octopus Deploy in which to run (i.e. Dev, Test, Prod). Each environment should be added on a new line. |
-| `variables` | A multi-line list of prompted variable values. Format: name:value. |
-| `server` | The instance URL hosting Octopus Deploy (i.e. ""). The instance URL is required, but you may also use the OCTOPUS_URL environment variable. |
-| `api_key` | The API key used to access Octopus Deploy. An API key is required, but you may also use the OCTOPUS_API_KEY environment variable. It is strongly recommended that this value retrieved from a GitHub secret. |
-| `space` | The name of a space within which this command will be executed. The space name is required, but you may also use the OCTOPUS_SPACE environment variable. |
+| Name | Description |
+| :------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `project` | **Required.** The name of the project associated with this runbook. |
+| `runbook` | **Required.** The name of the runbook. |
+| `environments` | **Required.** A list of environments in Octopus Deploy in which to run (i.e. Dev, Test, Prod). Each environment should be added on a new line. |
+| `variables` | A multi-line list of prompted variable values. Format: name:value. |
+| `server` | The instance URL hosting Octopus Deploy (i.e. ""). The instance URL is required, but you may also use the OCTOPUS_URL environment variable. |
+| `api_key` | The API key used to access Octopus Deploy. An API key is required, but you may also use the OCTOPUS_API_KEY environment variable. It is strongly recommended that this value retrieved from a GitHub secret. |
+| `space` | The name of a space within which this command will be executed. The space name is required, but you may also use the OCTOPUS_SPACE environment variable. |
+| `git_ref` | Git branch reference to the specific resources of a version controlled Octopus Project. This is required for version controlled projects. E.g. ${{ github.ref }} to use the branch or tag ref that triggered the workflow. |
## 📤 Outputs
diff --git a/action.yml b/action.yml
index d2509f54..9e9fe8ab 100644
--- a/action.yml
+++ b/action.yml
@@ -30,6 +30,8 @@ inputs:
description: 'The API key used to access Octopus Deploy. An API key is required, but you may also use the OCTOPUS_API_KEY environment variable. It is strongly recommended that this value retrieved from a GitHub secret.'
space:
description: 'The name of a space within which this command will be executed. The space name is required, but you may also use the OCTOPUS_SPACE environment variable.'
+ git_ref:
+ description: 'The Git Reference on which to run the Runbook. If not populate the action assumes you are running a DB Runbook. In most cases when running a Git Runbook this will be your default branch refs/heads/main'
outputs:
server_tasks:
diff --git a/dist/index.js b/dist/index.js
index 1005bc04..7ea97354 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -2748,10 +2748,10 @@ var BuildInformationRepository = /** @class */ (function () {
BuildInformationRepository.prototype.push = function (buildInformation, overwriteMode) {
if (overwriteMode === void 0) { overwriteMode = overwriteMode_1.OverwriteMode.FailIfExists; }
return __awaiter(this, void 0, void 0, function () {
- var tasks, _a, _b, pkg;
- var e_1, _c;
- return __generator(this, function (_d) {
- switch (_d.label) {
+ var tasks, _a, _b, pkg, rejectedTasks, completedTasks, completedTasks_1, completedTasks_1_1, t, errors, rejectedTasks_1, rejectedTasks_1_1, e, error;
+ var e_1, _c, e_2, _d, e_3, _e;
+ return __generator(this, function (_f) {
+ switch (_f.label) {
case 0:
tasks = [];
try {
@@ -2781,9 +2781,48 @@ var BuildInformationRepository = /** @class */ (function () {
}
finally { if (e_1) throw e_1.error; }
}
+ rejectedTasks = [];
return [4 /*yield*/, Promise.allSettled(tasks)];
case 1:
- _d.sent();
+ completedTasks = _f.sent();
+ try {
+ for (completedTasks_1 = __values(completedTasks), completedTasks_1_1 = completedTasks_1.next(); !completedTasks_1_1.done; completedTasks_1_1 = completedTasks_1.next()) {
+ t = completedTasks_1_1.value;
+ if (t.status === "rejected") {
+ rejectedTasks.push(t.reason);
+ }
+ }
+ }
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
+ finally {
+ try {
+ if (completedTasks_1_1 && !completedTasks_1_1.done && (_d = completedTasks_1.return)) _d.call(completedTasks_1);
+ }
+ finally { if (e_2) throw e_2.error; }
+ }
+ errors = [];
+ try {
+ for (rejectedTasks_1 = __values(rejectedTasks), rejectedTasks_1_1 = rejectedTasks_1.next(); !rejectedTasks_1_1.done; rejectedTasks_1_1 = rejectedTasks_1.next()) {
+ e = rejectedTasks_1_1.value;
+ if (e instanceof Error) {
+ errors.push(e);
+ }
+ else {
+ errors.push(new Error("unexpected error: ".concat(e)));
+ }
+ }
+ }
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
+ finally {
+ try {
+ if (rejectedTasks_1_1 && !rejectedTasks_1_1.done && (_e = rejectedTasks_1.return)) _e.call(rejectedTasks_1);
+ }
+ finally { if (e_3) throw e_3.error; }
+ }
+ if (errors.length > 0) {
+ error = errors.map(function (e) { return "".concat(e); });
+ throw new Error(error.join("\n"));
+ }
return [2 /*return*/];
}
});
@@ -3858,12 +3897,12 @@ var globp = (0, util_1.promisify)(glob_1.glob);
* @param {boolean} overwrite Whether to overwrite the Zip file if it already exists. Defaults to true if not specified.
*/
function doZip(basePath, inputFilePatterns, outputFolder, zipFilename, logger, compressionLevel, overwrite) {
- var _a, _b, _c;
+ var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function () {
var archivePath, initialWorkingDirectory, zip, files, files_1, files_1_1, file, dirName;
- var e_1, _d;
- return __generator(this, function (_e) {
- switch (_e.label) {
+ var e_1, _e;
+ return __generator(this, function (_f) {
+ switch (_f.label) {
case 0:
archivePath = path_1.default.resolve(outputFolder, zipFilename);
(_a = logger.info) === null || _a === void 0 ? void 0 : _a.call(logger, "Writing to package: ".concat(archivePath, "..."));
@@ -3872,7 +3911,7 @@ function doZip(basePath, inputFilePatterns, outputFolder, zipFilename, logger, c
zip = new adm_zip_1.default();
return [4 /*yield*/, expandGlobs(inputFilePatterns)];
case 1:
- files = _e.sent();
+ files = _f.sent();
try {
for (files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) {
file = files_1_1.value;
@@ -3889,7 +3928,7 @@ function doZip(basePath, inputFilePatterns, outputFolder, zipFilename, logger, c
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
- if (files_1_1 && !files_1_1.done && (_d = files_1.return)) _d.call(files_1);
+ if (files_1_1 && !files_1_1.done && (_e = files_1.return)) _e.call(files_1);
}
finally { if (e_1) throw e_1.error; }
}
@@ -3898,10 +3937,11 @@ function doZip(basePath, inputFilePatterns, outputFolder, zipFilename, logger, c
}
setCompressionLevel(zip, compressionLevel || 8);
process.chdir(initialWorkingDirectory);
- return [4 /*yield*/, zip.writeZipPromise(archivePath, { overwrite: overwrite || true })];
- case 2:
- _e.sent();
- return [2 /*return*/];
+ if (fs_1.default.existsSync(archivePath) && overwrite === false) {
+ (_d = logger.info) === null || _d === void 0 ? void 0 : _d.call(logger, "Found an existing archive at ".concat(archivePath, " and overwrite is disabled. The existing archive will not be overwritten."));
+ return [2 /*return*/];
+ }
+ return [2 /*return*/, zip.writeZip(archivePath, function () { })];
}
});
});
@@ -5633,6 +5673,24 @@ var RunbookProcessRepository = /** @class */ (function () {
});
});
};
+ RunbookProcessRepository.prototype.getWithGitRef = function (runbook, gitRef) {
+ return __awaiter(this, void 0, void 0, function () {
+ var response;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, this.client.request("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/{projectId}/{gitRef}/runbookProcesses{/id}"), {
+ spaceName: this.spaceName,
+ projectId: this.projectId,
+ id: runbook.RunbookProcessId,
+ gitRef: gitRef,
+ })];
+ case 1:
+ response = _a.sent();
+ return [2 /*return*/, response];
+ }
+ });
+ });
+ };
RunbookProcessRepository.prototype.update = function (runbookProcess) {
return __awaiter(this, void 0, void 0, function () {
var response;
@@ -5650,6 +5708,24 @@ var RunbookProcessRepository = /** @class */ (function () {
});
});
};
+ RunbookProcessRepository.prototype.updateWithGitRef = function (runbookProcess, gitRef) {
+ return __awaiter(this, void 0, void 0, function () {
+ var response;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, this.client.doUpdate("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/{projectId}/{gitRef}/runbookProcesses{/id}"), runbookProcess, {
+ spaceName: this.spaceName,
+ projectId: this.projectId,
+ id: runbookProcess.Id,
+ gitRef: gitRef,
+ })];
+ case 1:
+ response = _a.sent();
+ return [2 /*return*/, response];
+ }
+ });
+ });
+ };
return RunbookProcessRepository;
}());
exports.RunbookProcessRepository = RunbookProcessRepository;
@@ -5677,6 +5753,42 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+var __generator = (this && this.__generator) || function (thisArg, body) {
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
+ function verb(n) { return function (v) { return step([n, v]); }; }
+ function step(op) {
+ if (f) throw new TypeError("Generator is already executing.");
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
+ if (y = 0, t) op = [op[0] & 2, t.value];
+ switch (op[0]) {
+ case 0: case 1: t = op; break;
+ case 4: _.label++; return { value: op[1], done: false };
+ case 5: _.label++; y = op[1]; op = [0]; continue;
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
+ default:
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
+ if (t[2]) _.ops.pop();
+ _.trys.pop(); continue;
+ }
+ op = body.call(thisArg, _);
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
+ }
+};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.RunbookRepository = void 0;
var spaceScopedRoutePrefix_1 = __nccwpck_require__(7218);
@@ -5684,8 +5796,81 @@ var spaceScopedBasicRepository_1 = __nccwpck_require__(3496);
var RunbookRepository = /** @class */ (function (_super) {
__extends(RunbookRepository, _super);
function RunbookRepository(client, spaceName, project) {
- return _super.call(this, client, spaceName, "".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/").concat(project.Id, "/runbooks"), "skip,take,ids,partialName") || this;
+ var _this = _super.call(this, client, spaceName, "".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/").concat(project.Id, "/runbooks"), "skip,take,ids,partialName") || this;
+ _this.projectId = project.Id;
+ return _this;
}
+ RunbookRepository.prototype.getWithGitRef = function (slug, gitRef) {
+ return __awaiter(this, void 0, void 0, function () {
+ var response;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, this.client.request("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/{projectId}/{gitRef}/runbooks{/id}"), {
+ spaceName: this.spaceName,
+ projectId: this.projectId,
+ id: slug,
+ gitRef: gitRef,
+ })];
+ case 1:
+ response = _a.sent();
+ return [2 /*return*/, response];
+ }
+ });
+ });
+ };
+ RunbookRepository.prototype.createWithGitRef = function (runbook, gitRef) {
+ return __awaiter(this, void 0, void 0, function () {
+ var response;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, this.client.doCreate("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/{projectId}/{gitRef}/runbooks/v2"), runbook, {
+ spaceName: this.spaceName,
+ projectId: this.projectId,
+ gitRef: gitRef,
+ })];
+ case 1:
+ response = _a.sent();
+ return [2 /*return*/, response];
+ }
+ });
+ });
+ };
+ RunbookRepository.prototype.modifyWithGitRef = function (runbook, gitRef) {
+ return __awaiter(this, void 0, void 0, function () {
+ var response;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, this.client.doUpdate("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/{projectId}/{gitRef}/runbooks{/id}"), runbook, {
+ spaceName: this.spaceName,
+ projectId: this.projectId,
+ id: runbook.Id,
+ gitRef: gitRef,
+ })];
+ case 1:
+ response = _a.sent();
+ return [2 /*return*/, response];
+ }
+ });
+ });
+ };
+ RunbookRepository.prototype.deleteWithGitRef = function (runbook, gitRef) {
+ return __awaiter(this, void 0, void 0, function () {
+ var response;
+ return __generator(this, function (_a) {
+ switch (_a.label) {
+ case 0: return [4 /*yield*/, this.client.del("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/projects/{projectId}/{gitRef}/runbooks{/id}"), {
+ spaceName: this.spaceName,
+ projectId: this.projectId,
+ id: runbook.Id,
+ gitRef: gitRef,
+ })];
+ case 1:
+ response = _a.sent();
+ return [2 /*return*/, response];
+ }
+ });
+ });
+ };
return RunbookRepository;
}(spaceScopedBasicRepository_1.SpaceScopedBasicRepository));
exports.RunbookRepository = RunbookRepository;
@@ -5699,6 +5884,12 @@ exports.RunbookRepository = RunbookRepository;
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
+exports.RunbookRetentionUnit = void 0;
+var RunbookRetentionUnit;
+(function (RunbookRetentionUnit) {
+ RunbookRetentionUnit["Days"] = "Days";
+ RunbookRetentionUnit["Items"] = "Items";
+})(RunbookRetentionUnit = exports.RunbookRetentionUnit || (exports.RunbookRetentionUnit = {}));
/***/ }),
@@ -5944,6 +6135,40 @@ var RunbookRunRepository = /** @class */ (function () {
});
});
};
+ RunbookRunRepository.prototype.createGit = function (command, gitRef) {
+ var _a, _b;
+ return __awaiter(this, void 0, void 0, function () {
+ var serverInformation, response, mappedTasks;
+ return __generator(this, function (_c) {
+ switch (_c.label) {
+ case 0: return [4 /*yield*/, this.client.getServerInformation()];
+ case 1:
+ serverInformation = _c.sent();
+ if ((0, semver_1.lt)(serverInformation.version, "2022.3.5512")) {
+ (_b = (_a = this.client).error) === null || _b === void 0 ? void 0 : _b.call(_a, "The Octopus instance doesn't support running runbooks using the Executions API, it will need to be upgraded to at least 2022.3.5512 in order to access this API.");
+ throw new Error("The Octopus instance doesn't support running runbooks using the Executions API, it will need to be upgraded to at least 2022.3.5512 in order to access this API.");
+ }
+ this.client.debug("Running a runbook...");
+ return [4 /*yield*/, this.client.doCreate("".concat(spaceScopedRoutePrefix_1.spaceScopedRoutePrefix, "/runbook-runs/git/create/v1"), __assign({ spaceIdOrName: command.spaceName, gitRef: gitRef }, command))];
+ case 2:
+ response = _c.sent();
+ if (response.RunbookRunServerTasks.length == 0) {
+ throw new Error("No server task details returned");
+ }
+ mappedTasks = response.RunbookRunServerTasks.map(function (x) {
+ return {
+ RunbookRunId: x.RunbookRunId || x.runbookRunId,
+ ServerTaskId: x.ServerTaskId || x.serverTaskId,
+ };
+ });
+ this.client.debug("Runbook executed successfully. [".concat(mappedTasks.map(function (t) { return t.ServerTaskId; }).join(", "), "]"));
+ return [2 /*return*/, {
+ RunbookRunServerTasks: mappedTasks,
+ }];
+ }
+ });
+ });
+ };
return RunbookRunRepository;
}());
exports.RunbookRunRepository = RunbookRunRepository;
@@ -6160,30 +6385,31 @@ var ServerTaskWaiter = /** @class */ (function () {
stop = true;
}, timeout);
completedTasks = [];
+ _a.label = 1;
+ case 1:
+ _a.trys.push([1, , 5, 6]);
_loop_1 = function () {
- var tasks_2, unknownTaskIds, nowCompletedTaskIds_1, tasks_1, tasks_1_1, task;
+ var tasks, unknownTaskIds, nowCompletedTaskIds, tasks_1, tasks_1_1, task;
var e_1, _b;
return __generator(this, function (_c) {
switch (_c.label) {
- case 0:
- _c.trys.push([0, , 2, 3]);
- return [4 /*yield*/, spaceServerTaskRepository.getByIds(serverTaskIds)];
+ case 0: return [4 /*yield*/, spaceServerTaskRepository.getByIds(serverTaskIds)];
case 1:
- tasks_2 = _c.sent();
- unknownTaskIds = serverTaskIds.filter(function (id) { return tasks_2.filter(function (t) { return t.Id === id; }).length == 0; });
+ tasks = _c.sent();
+ unknownTaskIds = serverTaskIds.filter(function (id) { return tasks.filter(function (t) { return t.Id === id; }).length == 0; });
if (unknownTaskIds.length) {
throw new Error("Unknown task Id(s) ".concat(unknownTaskIds.join(", ")));
}
- nowCompletedTaskIds_1 = [];
+ nowCompletedTaskIds = [];
try {
- for (tasks_1 = (e_1 = void 0, __values(tasks_2)), tasks_1_1 = tasks_1.next(); !tasks_1_1.done; tasks_1_1 = tasks_1.next()) {
+ for (tasks_1 = (e_1 = void 0, __values(tasks)), tasks_1_1 = tasks_1.next(); !tasks_1_1.done; tasks_1_1 = tasks_1.next()) {
task = tasks_1_1.value;
if (pollingCallback) {
pollingCallback(task);
}
// once the task is complete
if (task.IsCompleted) {
- nowCompletedTaskIds_1.push(task.Id);
+ nowCompletedTaskIds.push(task.Id);
completedTasks.push(task);
}
}
@@ -6196,30 +6422,31 @@ var ServerTaskWaiter = /** @class */ (function () {
finally { if (e_1) throw e_1.error; }
}
// filter down the ids to only those that haven't completed for the next time around the loop
- serverTaskIds = serverTaskIds.filter(function (id) { return nowCompletedTaskIds_1.indexOf(id) < 0; });
+ serverTaskIds = serverTaskIds.filter(function (id) { return nowCompletedTaskIds.indexOf(id) < 0; });
// once all tasks have completed we can stop the loop
- if (serverTaskIds.length === 0 || tasks_2.length === 0) {
+ if (serverTaskIds.length === 0 || tasks.length === 0) {
stop = true;
+ clearTimeout(t);
}
- return [3 /*break*/, 3];
+ return [4 /*yield*/, sleep(statusCheckSleepCycle)];
case 2:
- clearTimeout(t);
- return [7 /*endfinally*/];
- case 3: return [4 /*yield*/, sleep(statusCheckSleepCycle)];
- case 4:
_c.sent();
return [2 /*return*/];
}
});
};
- _a.label = 1;
- case 1:
- if (!!stop) return [3 /*break*/, 3];
- return [5 /*yield**/, _loop_1()];
+ _a.label = 2;
case 2:
+ if (!!stop) return [3 /*break*/, 4];
+ return [5 /*yield**/, _loop_1()];
+ case 3:
_a.sent();
- return [3 /*break*/, 1];
- case 3: return [2 /*return*/, completedTasks];
+ return [3 /*break*/, 2];
+ case 4: return [3 /*break*/, 6];
+ case 5:
+ clearTimeout(t);
+ return [7 /*endfinally*/];
+ case 6: return [2 /*return*/, completedTasks];
}
});
});
@@ -41744,6 +41971,35 @@ const api_client_1 = __nccwpck_require__(586);
function runRunbookFromInputs(client, parameters) {
return __awaiter(this, void 0, void 0, function* () {
client.info('🐙 Running runbooks in Octopus Deploy...');
+ if (parameters.gitRef) {
+ return yield runGitRunbookFromInputs(client, parameters);
+ }
+ return yield runDbRunbookFromInputs(client, parameters);
+ });
+}
+exports.runRunbookFromInputs = runRunbookFromInputs;
+function runGitRunbookFromInputs(client, parameters) {
+ return __awaiter(this, void 0, void 0, function* () {
+ const command = {
+ spaceName: parameters.space,
+ ProjectName: parameters.project,
+ RunbookName: parameters.runbook,
+ EnvironmentNames: parameters.environments,
+ Tenants: parameters.tenants,
+ TenantTags: parameters.tenantTags,
+ UseGuidedFailure: parameters.useGuidedFailure,
+ Variables: parameters.variables
+ };
+ if (!parameters.gitRef) {
+ throw new Error('gitRef is required for running a Git runbook.');
+ }
+ const runbookRunRepository = new api_client_1.RunbookRunRepository(client, parameters.space);
+ const response = yield runbookRunRepository.createGit(command, parameters.gitRef);
+ return yield parseResult(client, response, runbookRunRepository, parameters);
+ });
+}
+function runDbRunbookFromInputs(client, parameters) {
+ return __awaiter(this, void 0, void 0, function* () {
const command = {
spaceName: parameters.space,
ProjectName: parameters.project,
@@ -41756,6 +42012,11 @@ function runRunbookFromInputs(client, parameters) {
};
const runbookRunRepository = new api_client_1.RunbookRunRepository(client, parameters.space);
const response = yield runbookRunRepository.create(command);
+ return yield parseResult(client, response, runbookRunRepository, parameters);
+ });
+}
+function parseResult(client, response, runbookRunRepository, parameters) {
+ return __awaiter(this, void 0, void 0, function* () {
client.info(`🎉 ${response.RunbookRunServerTasks.length} Runbook run${response.RunbookRunServerTasks.length > 1 ? 's' : ''} queued successfully!`);
if (response.RunbookRunServerTasks.length === 0) {
throw new Error('Expected at least one deployment to be queued.');
@@ -41788,7 +42049,6 @@ function runRunbookFromInputs(client, parameters) {
return results;
});
}
-exports.runRunbookFromInputs = runRunbookFromInputs;
/***/ }),
@@ -41828,7 +42088,8 @@ function getInputParameters() {
tenants: (0, core_1.getMultilineInput)('tenants').map(p => p.trim()) || undefined,
tenantTags: (0, core_1.getMultilineInput)('tenant_tags').map(p => p.trim()) || undefined,
useGuidedFailure: (0, core_1.getBooleanInput)('use_guided_failure') || undefined,
- variables: variablesMap
+ variables: variablesMap,
+ gitRef: (0, core_1.getInput)('git_ref') || undefined
};
const errors = [];
if (!parameters.server) {
diff --git a/package-lock.json b/package-lock.json
index 6a002e59..39e33f2e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,7 @@
"license": "Apache-2.0",
"dependencies": {
"@actions/core": "1.10.1",
- "@octopusdeploy/api-client": "3.2.0"
+ "@octopusdeploy/api-client": "3.5.1"
},
"devDependencies": {
"@types/jest": "29.5.14",
@@ -1358,9 +1358,9 @@
}
},
"node_modules/@octopusdeploy/api-client": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@octopusdeploy/api-client/-/api-client-3.2.0.tgz",
- "integrity": "sha512-0TrbsXaFc/Xi3yfsEEAvf5mOveZx4K347LmBRwCuLd2pLl8tj3NJYJn7nRzz3kr4j6o46oUv1RukemEXqu91Dg==",
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/@octopusdeploy/api-client/-/api-client-3.5.1.tgz",
+ "integrity": "sha512-JKPx+L1QNjtX1txpj+0+JJR3Q5D/IwKdocih8WTGXGYNYC8jdEDgaTkPb701gD/Jzu14foNn67W4CDDBvyPZeA==",
"dependencies": {
"adm-zip": "^0.5.9",
"axios": "^1.2.1",
@@ -7690,9 +7690,9 @@
}
},
"@octopusdeploy/api-client": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@octopusdeploy/api-client/-/api-client-3.2.0.tgz",
- "integrity": "sha512-0TrbsXaFc/Xi3yfsEEAvf5mOveZx4K347LmBRwCuLd2pLl8tj3NJYJn7nRzz3kr4j6o46oUv1RukemEXqu91Dg==",
+ "version": "3.5.1",
+ "resolved": "https://registry.npmjs.org/@octopusdeploy/api-client/-/api-client-3.5.1.tgz",
+ "integrity": "sha512-JKPx+L1QNjtX1txpj+0+JJR3Q5D/IwKdocih8WTGXGYNYC8jdEDgaTkPb701gD/Jzu14foNn67W4CDDBvyPZeA==",
"requires": {
"adm-zip": "^0.5.9",
"axios": "^1.2.1",
diff --git a/package.json b/package.json
index bdf04bb2..f203cf7c 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
},
"dependencies": {
"@actions/core": "1.10.1",
- "@octopusdeploy/api-client": "3.2.0"
+ "@octopusdeploy/api-client": "3.5.1"
},
"description": "GitHub Action to Run a Runbook in Octopus Deploy",
"devDependencies": {
diff --git a/src/api-wrapper.ts b/src/api-wrapper.ts
index 7cf7e357..50706141 100644
--- a/src/api-wrapper.ts
+++ b/src/api-wrapper.ts
@@ -1,3 +1,4 @@
+import { RunGitRunbookCommand } from '@octopusdeploy/api-client/dist/features/projects/runbooks/runs/RunGitRunbookCommand'
import { InputParameters } from './input-parameters'
import {
Client,
@@ -18,6 +19,37 @@ export interface RunbookRunResult {
export async function runRunbookFromInputs(client: Client, parameters: InputParameters): Promise {
client.info('🐙 Running runbooks in Octopus Deploy...')
+ if (parameters.gitRef) {
+ return await runGitRunbookFromInputs(client, parameters)
+ }
+
+ return await runDbRunbookFromInputs(client, parameters)
+}
+
+async function runGitRunbookFromInputs(client: Client, parameters: InputParameters): Promise {
+ const command: RunGitRunbookCommand = {
+ spaceName: parameters.space,
+ ProjectName: parameters.project,
+ RunbookName: parameters.runbook,
+ EnvironmentNames: parameters.environments,
+ Tenants: parameters.tenants,
+ TenantTags: parameters.tenantTags,
+ UseGuidedFailure: parameters.useGuidedFailure,
+ Variables: parameters.variables
+ }
+
+ if (!parameters.gitRef) {
+ throw new Error('gitRef is required for running a Git runbook.')
+ }
+
+ const runbookRunRepository = new RunbookRunRepository(client, parameters.space)
+
+ const response = await runbookRunRepository.createGit(command, parameters.gitRef)
+
+ return await parseResult(client, response, runbookRunRepository, parameters)
+}
+
+async function runDbRunbookFromInputs(client: Client, parameters: InputParameters): Promise {
const command: CreateRunbookRunCommandV1 = {
spaceName: parameters.space,
ProjectName: parameters.project,
@@ -32,6 +64,22 @@ export async function runRunbookFromInputs(client: Client, parameters: InputPara
const runbookRunRepository = new RunbookRunRepository(client, parameters.space)
const response = await runbookRunRepository.create(command)
+ return await parseResult(client, response, runbookRunRepository, parameters)
+}
+
+interface CreateRunbookRunResponse {
+ RunbookRunServerTasks: {
+ RunbookRunId: string
+ ServerTaskId: string
+ }[]
+}
+
+async function parseResult(
+ client: Client,
+ response: CreateRunbookRunResponse,
+ runbookRunRepository: RunbookRunRepository,
+ parameters: InputParameters
+): Promise {
client.info(
`🎉 ${response.RunbookRunServerTasks.length} Runbook run${
response.RunbookRunServerTasks.length > 1 ? 's' : ''
diff --git a/src/input-parameters.ts b/src/input-parameters.ts
index cb6155aa..f2bcdd0c 100644
--- a/src/input-parameters.ts
+++ b/src/input-parameters.ts
@@ -20,6 +20,7 @@ export interface InputParameters {
apiKey?: string
accessToken?: string
space: string
+ gitRef?: string
}
export function getInputParameters(): InputParameters {
@@ -44,7 +45,8 @@ export function getInputParameters(): InputParameters {
tenants: getMultilineInput('tenants').map(p => p.trim()) || undefined,
tenantTags: getMultilineInput('tenant_tags').map(p => p.trim()) || undefined,
useGuidedFailure: getBooleanInput('use_guided_failure') || undefined,
- variables: variablesMap
+ variables: variablesMap,
+ gitRef: getInput('git_ref') || undefined
}
const errors: string[] = []