-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
399 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
**/task.json |
38 changes: 38 additions & 0 deletions
38
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/createRelease.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import os from "os"; | ||
import { Client, CreateReleaseCommandV1, Logger, ReleaseRepository } from "@octopusdeploy/api-client"; | ||
import { InputParameters } from "./input-parameters"; | ||
import { TaskWrapper } from "tasks/Utils/taskInput"; | ||
|
||
// Returns the release number that was actually created in Octopus | ||
export async function createReleaseFromInputs(client: Client, parameters: InputParameters, task: TaskWrapper, logger: Logger): Promise<string> { | ||
logger.info?.("🐙 Creating a release in Octopus Deploy..."); | ||
const command: CreateReleaseCommandV1 = { | ||
spaceName: parameters.space, | ||
ProjectName: parameters.project, | ||
ReleaseVersion: parameters.releaseNumber, | ||
ChannelName: parameters.channel, | ||
PackageVersion: parameters.defaultPackageVersion, | ||
Packages: parameters.packages, | ||
ReleaseNotes: parameters.releaseNotes, | ||
GitRef: parameters.gitRef, | ||
GitCommit: parameters.gitCommit, | ||
}; | ||
|
||
try { | ||
const repository = new ReleaseRepository(client, parameters.space); | ||
const response = await repository.create(command); | ||
|
||
client.info(`🎉 Release ${response.ReleaseVersion} created successfully!`); | ||
|
||
task.setOutputVariable("release_number", response.ReleaseVersion); | ||
|
||
return response.ReleaseVersion; | ||
} catch (error: unknown) { | ||
if (error instanceof Error) { | ||
task.setFailure(`"Failed to execute command. ${error.message}${os.EOL}${error.stack}`, true); | ||
} else { | ||
task.setFailure(`"Failed to execute command. ${error}`, true); | ||
} | ||
throw error; | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions
1
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions
26
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { getDefaultOctopusConnectionDetailsOrThrow } from "../../Utils/connection"; | ||
import { ConcreteTaskWrapper, TaskWrapper } from "tasks/Utils/taskInput"; | ||
import { Logger } from "@octopusdeploy/api-client"; | ||
import * as tasks from "azure-pipelines-task-lib/task"; | ||
import { Release } from "./release"; | ||
|
||
const connection = getDefaultOctopusConnectionDetailsOrThrow(); | ||
|
||
const logger: Logger = { | ||
debug: (message) => { | ||
tasks.debug(message); | ||
}, | ||
info: (message) => console.log(message), | ||
warn: (message) => tasks.warning(message), | ||
error: (message, err) => { | ||
if (err !== undefined) { | ||
tasks.error(err.message); | ||
} else { | ||
tasks.error(message); | ||
} | ||
}, | ||
}; | ||
|
||
const task: TaskWrapper = new ConcreteTaskWrapper(); | ||
|
||
new Release(connection, task, logger).run(); |
55 changes: 55 additions & 0 deletions
55
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/input-parameters.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { Logger } from "@octopusdeploy/api-client"; | ||
import { getInputParameters } from "./input-parameters"; | ||
import { MockTaskWrapper } from "../../Utils/MockTaskWrapper"; | ||
|
||
describe("getInputParameters", () => { | ||
let logger: Logger; | ||
let task: MockTaskWrapper; | ||
beforeEach(() => { | ||
logger = {}; | ||
task = new MockTaskWrapper(); | ||
}); | ||
|
||
test("all regular fields supplied", () => { | ||
task.addVariableString("Space", "Default"); | ||
task.addVariableString("Project", "Awesome project"); | ||
task.addVariableString("Channel", "Beta"); | ||
task.addVariableString("ReleaseNumber", "1.0.0"); | ||
task.addVariableString("DefaultPackageVersion", "1.0.1"); | ||
task.addVariableString("Packages", "Step1:Foo:1.0.0\nBar:2.0.0"); | ||
task.addVariableString("GitRef", "main"); | ||
|
||
const inputParameters = getInputParameters(logger, task); | ||
expect(inputParameters.space).toBe("Default"); | ||
expect(inputParameters.project).toBe("Awesome project"); | ||
expect(inputParameters.channel).toBe("Beta"); | ||
expect(inputParameters.releaseNumber).toBe("1.0.0"); | ||
expect(inputParameters.defaultPackageVersion).toBe("1.0.1"); | ||
expect(inputParameters.packages).toStrictEqual(["Step1:Foo:1.0.0", "Bar:2.0.0"]); | ||
expect(inputParameters.gitRef).toBe("main"); | ||
|
||
expect(task.lastResult).toBeUndefined(); | ||
expect(task.lastResultMessage).toBeUndefined(); | ||
expect(task.lastResultDone).toBeUndefined(); | ||
}); | ||
|
||
test("packages in additional fields", () => { | ||
task.addVariableString("Space", "Default"); | ||
task.addVariableString("Project", "Awesome project"); | ||
task.addVariableString("Packages", "Step1:Foo:1.0.0\nBar:2.0.0"); | ||
task.addVariableString("AdditionalArguments", "--package Baz:2.5.0"); | ||
|
||
const inputParameters = getInputParameters(logger, task); | ||
expect(inputParameters.packages).toStrictEqual(["Baz:2.5.0", "Step1:Foo:1.0.0", "Bar:2.0.0"]); | ||
}); | ||
|
||
test("duplicate variable name, variables field takes precedence", () => { | ||
task.addVariableString("Space", "Default"); | ||
task.addVariableString("Project", "Awesome project"); | ||
task.addVariableString("Packages", "Step1:Foo:1.0.0\nBar:2.0.0"); | ||
task.addVariableString("AdditionalArguments", "--package Bar:2.0.0"); | ||
|
||
const inputParameters = getInputParameters(logger, task); | ||
expect(inputParameters.packages).toStrictEqual(["Bar:2.0.0", "Step1:Foo:1.0.0"]); | ||
}); | ||
}); |
81 changes: 81 additions & 0 deletions
81
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/input-parameters.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import commandLineArgs from "command-line-args"; | ||
import shlex from "shlex"; | ||
import { getLineSeparatedItems } from "../../Utils/inputs"; | ||
import { Logger } from "@octopusdeploy/api-client"; | ||
import { TaskWrapper } from "tasks/Utils/taskInput"; | ||
|
||
export interface InputParameters { | ||
space: string; | ||
project: string; | ||
releaseNumber: string | undefined; | ||
channel: string | undefined; | ||
defaultPackageVersion: string | undefined; | ||
packages: string[] | undefined; | ||
releaseNotes: string | undefined; | ||
gitRef: string | undefined; | ||
gitCommit: string | undefined; | ||
} | ||
|
||
export function getInputParameters(logger: Logger, task: TaskWrapper): InputParameters { | ||
const packages: string[] = []; | ||
let defaultPackageVersion: string | undefined = undefined; | ||
|
||
const additionalArguments = task.getInput("AdditionalArguments"); | ||
logger.debug?.("AdditionalArguments:" + additionalArguments); | ||
if (additionalArguments) { | ||
const optionDefs = [ | ||
{ name: "package", type: String, multiple: true }, | ||
{ name: "defaultPackageVersion", type: String }, | ||
{ name: "packageVersion", type: String }, | ||
]; | ||
const splitArgs = shlex.split(additionalArguments); | ||
const options = commandLineArgs(optionDefs, { argv: splitArgs }); | ||
logger.debug?.(JSON.stringify(options)); | ||
for (const pkg of options.package) { | ||
packages.push(pkg.trim()); | ||
} | ||
|
||
// defaultPackageVersion and packageVersion both represent the default package version | ||
if (options.defaultPackageVersion) { | ||
defaultPackageVersion = options.defaultPackageVersion; | ||
} | ||
if (options.packageVersion) { | ||
defaultPackageVersion = options.packageVersion; | ||
} | ||
} | ||
|
||
const packagesField = task.getInput("Packages"); | ||
logger.debug?.("Packages:" + packagesField); | ||
if (packagesField) { | ||
const packagesFieldData = getLineSeparatedItems(packagesField).map((p) => p.trim()) || undefined; | ||
if (packagesFieldData) { | ||
for (const packageLine of packagesFieldData) { | ||
const trimmedPackageLine = packageLine.trim(); | ||
if (packages.indexOf(trimmedPackageLine) < 0) { | ||
packages.push(trimmedPackageLine); | ||
} | ||
} | ||
} | ||
} | ||
|
||
const defaultPackageVersionField = task.getInput("DefaultPackageVersion"); | ||
if (defaultPackageVersionField) { | ||
defaultPackageVersion = defaultPackageVersionField; | ||
} | ||
|
||
const parameters: InputParameters = { | ||
space: task.getInput("Space", true) || "", | ||
project: task.getInput("Project", true) || "", | ||
releaseNumber: task.getInput("ReleaseNumber"), | ||
channel: task.getInput("Channel"), | ||
defaultPackageVersion: defaultPackageVersion, | ||
packages: packages.length > 0 ? packages : undefined, | ||
releaseNotes: task.getInput("ReleaseNotes"), | ||
gitRef: task.getInput("GitRef"), | ||
gitCommit: task.getInput("GitCommit"), | ||
}; | ||
|
||
logger.debug?.(JSON.stringify(parameters)); | ||
|
||
return parameters; | ||
} |
35 changes: 35 additions & 0 deletions
35
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/release.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { Client, ClientConfiguration, Logger } from "@octopusdeploy/api-client"; | ||
import { OctoServerConnectionDetails } from "../../Utils/connection"; | ||
import { createReleaseFromInputs } from "./createRelease"; | ||
import { getInputParameters } from "./input-parameters"; | ||
import os from "os"; | ||
import { TaskWrapper } from "tasks/Utils/taskInput"; | ||
|
||
export class Release { | ||
constructor(readonly connection: OctoServerConnectionDetails, readonly task: TaskWrapper, readonly logger: Logger) {} | ||
|
||
public async run() { | ||
try { | ||
const inputParameters = getInputParameters(this.logger, this.task); | ||
|
||
const config: ClientConfiguration = { | ||
userAgentApp: "AzureDevOps (release;create;v6)", | ||
instanceURL: this.connection.url, | ||
apiKey: this.connection.apiKey, | ||
logging: this.logger, | ||
}; | ||
const client = await Client.create(config); | ||
|
||
await createReleaseFromInputs(client, inputParameters, this.task, this.logger); | ||
|
||
this.task.setSuccess("Release creation succeeded."); | ||
} catch (error: unknown) { | ||
if (error instanceof Error) { | ||
this.task.setFailure(`"Failed to successfully create release. ${error.message}${os.EOL}${error.stack}`, true); | ||
} else { | ||
this.task.setFailure(`"Failed to successfully create release. ${error}`, true); | ||
} | ||
throw error; | ||
} | ||
} | ||
} |
137 changes: 137 additions & 0 deletions
137
source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/task.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
{ | ||
"id": "4E131B60-5532-4362-95B6-7C67D9841B4F", | ||
"name": "OctopusCreateRelease", | ||
"friendlyName": "Create Octopus Release", | ||
"description": "Create a Release in Octopus Deploy", | ||
"helpMarkDown": "set-by-pack.ps1", | ||
"category": "Deploy", | ||
"visibility": [ | ||
"Build", | ||
"Release" | ||
], | ||
"author": "Octopus Deploy", | ||
"version": { | ||
"Major": 6, | ||
"Minor": 0, | ||
"Patch": 0 | ||
}, | ||
"demands": [ ], | ||
"minimumAgentVersion": "2.144.0", | ||
"groups": [ | ||
{ | ||
"name": "versionControl", | ||
"displayName": "Version Control", | ||
"isExpanded": false | ||
}, | ||
{ | ||
"name": "additional", | ||
"displayName": "Additional Options", | ||
"isExpanded": false | ||
} | ||
], | ||
"inputs": [ | ||
{ | ||
"name": "OctoConnectedServiceName", | ||
"type": "connectedService:OctopusEndpoint", | ||
"label": "Octopus Deploy Server", | ||
"defaultValue": "", | ||
"required": true, | ||
"helpMarkDown": "Octopus Deploy server connection" | ||
}, | ||
{ | ||
"name": "Space", | ||
"type": "string", | ||
"label": "Space", | ||
"defaultValue": "", | ||
"required": true, | ||
"helpMarkDown": "The space within Octopus. This must be the name of the space, not the id." | ||
}, | ||
{ | ||
"name": "Project", | ||
"type": "string", | ||
"label": "Project", | ||
"defaultValue": "", | ||
"required": true, | ||
"helpMarkDown": "The project within Octopus. This must be the name of the project, not the id." | ||
}, | ||
{ | ||
"name": "ReleaseNumber", | ||
"type": "string", | ||
"label": "Release Number", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "The number to use for this release. You can leave this blank if the release number is calculated by Octopus." | ||
}, | ||
{ | ||
"name": "Channel", | ||
"type": "string", | ||
"label": "Channel", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "The [channel](https://g.octopushq.com/Channels) to use for the release. This must be the name of the channel, not the id." | ||
}, | ||
{ | ||
"name": "DefaultPackageVersion", | ||
"type": "string", | ||
"label": "Default Package Version", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "Set this to provide a default package version to use for all packages on all steps. Can be used in conjunction with the Packages field, which can be used to override versions for specific packages." | ||
}, | ||
{ | ||
"name": "Packages", | ||
"type": "multiLine", | ||
"label": "Packages", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "A multi-line list of version numbers to use for a package in the release. Format: StepName:Version or PackageID:Version or StepName:PackageName:Version. StepName, PackageID, and PackageName can be replaced with an asterisk ('*'). An asterisk will be assumed for StepName, PackageID, or PackageName if they are omitted." | ||
}, | ||
{ | ||
"name": "ReleaseNotes", | ||
"type": "string", | ||
"label": "Release Notes", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "Octopus Release notes. This field supports markdown. To include newlines, you can use HTML linebreaks." | ||
}, | ||
{ | ||
"name": "GitRef", | ||
"type": "string", | ||
"label": "Git Reference", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "Git branch reference to use when creating the release for version controlled Projects.", | ||
"groupName": "versionControl" | ||
}, | ||
{ | ||
"name": "GitCommit", | ||
"type": "string", | ||
"label": "Git Commit", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "Git commit to use when creating the release for version controlled Projects. Use in conjunction with the gitRef parameter to select any previous commit.", | ||
"groupName": "versionControl" | ||
}, | ||
{ | ||
"name": "AdditionalArguments", | ||
"type": "string", | ||
"label": "Additional Arguments", | ||
"defaultValue": "", | ||
"required": false, | ||
"helpMarkDown": "Additional arguments are no longer supported. This field has been retained to ease migration from earlier versions of the step but values should be moved to the appropriate fields.", | ||
"groupName": "additional" | ||
} | ||
], | ||
"OutputVariables": [ | ||
{ | ||
"name": "release_number", | ||
"description": "The Octopus Deploy release number assigned to the Release." | ||
} | ||
], | ||
"instanceNameFormat": "Create Octopus Release", | ||
"execution": { | ||
"Node16": { | ||
"target": "index.js" | ||
} | ||
} | ||
} |
Oops, something went wrong.