Skip to content

Commit bd08fb7

Browse files
authored
feat: Task summary for deployments (#313)
1 parent ef76948 commit bd08fb7

File tree

6 files changed

+105
-34
lines changed

6 files changed

+105
-34
lines changed

package-lock.json

+13-13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"yargs": "^17.5.1"
3939
},
4040
"dependencies": {
41-
"@octopusdeploy/api-client": "^3.0.7",
41+
"@octopusdeploy/api-client": "^3.0.8",
4242
"azure-devops-node-api": "11.2.0",
4343
"azure-pipelines-task-lib": "3.3.1",
4444
"azure-pipelines-tool-lib": "1.3.2",

source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/release.ts

+18-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { Client, CreateReleaseCommandV1, Logger, Project, ProjectRepository, Space, SpaceRepository } from "@octopusdeploy/api-client";
1+
import {
2+
Client,
3+
CreateReleaseCommandV1,
4+
Logger,
5+
Project,
6+
ProjectRepository,
7+
resolveSpaceId,
8+
} from "@octopusdeploy/api-client";
29
import { OctoServerConnectionDetails } from "../../Utils/connection";
310
import { createReleaseFromInputs } from "./createRelease";
411
import { createCommandFromInputs } from "./inputCommandBuilder";
@@ -33,20 +40,16 @@ export class Release {
3340
}
3441

3542
private async tryCreateSummary(client: Client, command: CreateReleaseCommandV1, version: string) {
36-
const spaceRepo = new SpaceRepository(client);
37-
const spaces = await spaceRepo.list({ partialName: command.spaceName });
38-
const matchedSpaces = spaces.Items.filter((s: Space) => s.Name.localeCompare(command.spaceName) === 0);
39-
if (matchedSpaces.length === 1) {
40-
const projectRepo = new ProjectRepository(client, command.spaceName);
41-
const projects = await projectRepo.list({ partialName: command.ProjectName });
42-
const matchedProjects = projects.Items.filter((p: Project) => p.Name.localeCompare(command.ProjectName) === 0);
43-
if (matchedProjects.length === 1) {
44-
const link = `${this.connection.url}app#/${matchedSpaces[0].Id}/projects/${matchedProjects[0].Id}/deployments/releases/${version}`;
45-
const markdown = `[Release ${version} created for '${matchedProjects[0].Name}'](${link})`;
46-
const markdownFile = path.join(getVstsEnvironmentVariables().defaultWorkingDirectory, `${uuidv4()}.md`);
47-
tasks.writeFile(markdownFile, markdown);
48-
tasks.addAttachment("Distributedtask.Core.Summary", "Octopus Deploy", markdownFile);
49-
}
43+
const spaceId = await resolveSpaceId(client, command.spaceName);
44+
const projectRepo = new ProjectRepository(client, command.spaceName);
45+
const projects = await projectRepo.list({ partialName: command.ProjectName });
46+
const matchedProjects = projects.Items.filter((p: Project) => p.Name.localeCompare(command.ProjectName) === 0);
47+
if (matchedProjects.length === 1) {
48+
const link = `${this.connection.url}app#/${spaceId}/projects/${matchedProjects[0].Id}/deployments/releases/${version}`;
49+
const markdown = `[Release ${version} created for '${matchedProjects[0].Name}'](${link})`;
50+
const markdownFile = path.join(getVstsEnvironmentVariables().defaultWorkingDirectory, `${uuidv4()}.md`);
51+
tasks.writeFile(markdownFile, markdown);
52+
tasks.addAttachment("Distributedtask.Core.Summary", "Octopus Create Release", markdownFile);
5053
}
5154
}
5255
}

source/tasks/Deploy/DeployV6/createDeployment.ts

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { TaskWrapper } from "../../Utils/taskInput";
44
import { ExecutionResult } from "../../Utils/executionResult";
55

66
export async function createDeploymentFromInputs(client: Client, command: CreateDeploymentUntenantedCommandV1, task: TaskWrapper, logger: Logger): Promise<ExecutionResult[]> {
7-
87
logger.info?.("🐙 Deploying a release in Octopus Deploy...");
98

109
try {

source/tasks/Deploy/DeployV6/deploy.ts

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { Logger } from "@octopusdeploy/api-client";
1+
import { Client, CreateDeploymentUntenantedCommandV1, Logger, resolveSpaceId, ServerTask, SpaceServerTaskRepository } from "@octopusdeploy/api-client";
22
import { OctoServerConnectionDetails } from "../../Utils/connection";
33
import { createDeploymentFromInputs } from "./createDeployment";
44
import { createCommandFromInputs } from "./inputCommandBuilder";
55
import os from "os";
66
import { TaskWrapper } from "tasks/Utils/taskInput";
77
import { getClient } from "../../Utils/client";
8+
import path from "path";
9+
import { getVstsEnvironmentVariables } from "../../../tasksLegacy/Utils/environment";
10+
import { v4 as uuidv4 } from "uuid";
11+
import { ExecutionResult } from "../../Utils/executionResult";
12+
import * as tasks from "azure-pipelines-task-lib";
813

914
export class Deploy {
1015
constructor(readonly connection: OctoServerConnectionDetails, readonly task: TaskWrapper, readonly logger: Logger) {}
@@ -14,7 +19,8 @@ export class Deploy {
1419
const command = createCommandFromInputs(this.logger, this.task);
1520
const client = await getClient(this.connection, this.logger, "release", "deploy", 6);
1621

17-
createDeploymentFromInputs(client, command, this.task, this.logger);
22+
const results = await createDeploymentFromInputs(client, command, this.task, this.logger);
23+
await this.tryCreateSummary(client, command, results);
1824

1925
this.task.setSuccess("Deployment succeeded.");
2026
} catch (error: unknown) {
@@ -26,4 +32,32 @@ export class Deploy {
2632
throw error;
2733
}
2834
}
35+
36+
private async tryCreateSummary(client: Client, command: CreateDeploymentUntenantedCommandV1, results: ExecutionResult[]) {
37+
if (results.length === 0) {
38+
return;
39+
}
40+
41+
const spaceId = await resolveSpaceId(client, command.spaceName);
42+
const taskRepo = new SpaceServerTaskRepository(client, command.spaceName);
43+
const allTasks = await taskRepo.getByIds<{ DeploymentId: string }>(results.map((t) => t.serverTaskId));
44+
const taskLookup = new Map<string, ServerTask<{ DeploymentId: string }>>();
45+
allTasks.forEach(function (t) {
46+
taskLookup.set(t.Id, t);
47+
});
48+
49+
const url = this.connection.url;
50+
let markdown = `${results[0].type} tasks\n\n`;
51+
results.forEach(function (result) {
52+
const task = taskLookup.get(result.serverTaskId);
53+
if (task != null) {
54+
const link = `${url}app#/${spaceId}/deployments/${task.Arguments.DeploymentId}`;
55+
markdown += `[${result.environmentName}](${link})\n`;
56+
}
57+
});
58+
59+
const markdownFile = path.join(getVstsEnvironmentVariables().defaultWorkingDirectory, `${uuidv4()}.md`);
60+
tasks.writeFile(markdownFile, markdown);
61+
tasks.addAttachment("Distributedtask.Core.Summary", "Octopus Deploy", markdownFile);
62+
}
2963
}

source/tasks/DeployTenant/TenantedDeployV6/deploy.ts

+37-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { Logger } from "@octopusdeploy/api-client";
1+
import { CreateDeploymentTenantedCommandV1, Logger, Client, resolveSpaceId, SpaceServerTaskRepository, ServerTask } from "@octopusdeploy/api-client";
22
import { OctoServerConnectionDetails } from "../../Utils/connection";
33
import { createDeploymentFromInputs } from "./createDeployment";
44
import { createCommandFromInputs } from "./inputCommandBuilder";
55
import os from "os";
66
import { TaskWrapper } from "tasks/Utils/taskInput";
77
import { getClient } from "../../Utils/client";
8+
import { ExecutionResult } from "../../Utils/executionResult";
9+
import path from "path";
10+
import { getVstsEnvironmentVariables } from "../../../tasksLegacy/Utils/environment";
11+
import { v4 as uuidv4 } from "uuid";
12+
import * as tasks from "azure-pipelines-task-lib";
813

914
export class Deploy {
1015
constructor(readonly connection: OctoServerConnectionDetails, readonly task: TaskWrapper, readonly logger: Logger) {}
@@ -14,7 +19,9 @@ export class Deploy {
1419
const command = createCommandFromInputs(this.logger, this.task);
1520
const client = await getClient(this.connection, this.logger, "release", "deploy-tenanted", 6);
1621

17-
createDeploymentFromInputs(client, command, this.task, this.logger);
22+
const results = await createDeploymentFromInputs(client, command, this.task, this.logger);
23+
24+
await this.tryCreateSummary(client, command, results);
1825

1926
this.task.setSuccess("Deployment succeeded.");
2027
} catch (error: unknown) {
@@ -26,4 +33,32 @@ export class Deploy {
2633
throw error;
2734
}
2835
}
36+
37+
private async tryCreateSummary(client: Client, command: CreateDeploymentTenantedCommandV1, results: ExecutionResult[]) {
38+
if (results.length === 0) {
39+
return;
40+
}
41+
42+
const spaceId = await resolveSpaceId(client, command.spaceName);
43+
const taskRepo = new SpaceServerTaskRepository(client, command.spaceName);
44+
const allTasks = await taskRepo.getByIds<{ DeploymentId: string }>(results.map((t) => t.serverTaskId));
45+
const taskLookup = new Map<string, ServerTask<{ DeploymentId: string }>>();
46+
allTasks.forEach(function (t) {
47+
taskLookup.set(t.Id, t);
48+
});
49+
50+
const url = this.connection.url;
51+
let markdown = `${results[0].type} tasks for '${results[0].environmentName}' environment\n\n`;
52+
results.forEach(function (result) {
53+
const task = taskLookup.get(result.serverTaskId);
54+
if (task != null) {
55+
const link = `${url}app#/${spaceId}/deployments/${task.Arguments.DeploymentId}`;
56+
markdown += `[${result.tenantName}](${link})\n`;
57+
}
58+
});
59+
60+
const markdownFile = path.join(getVstsEnvironmentVariables().defaultWorkingDirectory, `${uuidv4()}.md`);
61+
tasks.writeFile(markdownFile, markdown);
62+
tasks.addAttachment("Distributedtask.Core.Summary", "Octopus Deploy Tenants", markdownFile);
63+
}
2964
}

0 commit comments

Comments
 (0)