From 9b69232d124cb6fbf8136320b8498f0671912e80 Mon Sep 17 00:00:00 2001 From: hnrkndrssn Date: Fri, 16 May 2025 11:41:22 +1000 Subject: [PATCH 1/3] fix: add function to build deeplinks that ensures that url is correctly generated --- source/tasks/AwaitTask/AwaitTaskV6/waiter.ts | 11 ++++++----- .../CreateOctopusReleaseV6/release.ts | 13 +++---------- source/tasks/Deploy/DeployV6/deploy.ts | 4 ++-- .../tasks/DeployTenant/TenantedDeployV6/deploy.ts | 4 ++-- source/tasks/Utils/connection.ts | 7 +++++++ 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/source/tasks/AwaitTask/AwaitTaskV6/waiter.ts b/source/tasks/AwaitTask/AwaitTaskV6/waiter.ts index 2cdcc123..c86c5902 100644 --- a/source/tasks/AwaitTask/AwaitTaskV6/waiter.ts +++ b/source/tasks/AwaitTask/AwaitTaskV6/waiter.ts @@ -1,5 +1,5 @@ import { ActivityElement, ActivityLogEntryCategory, ActivityStatus, Client, Logger, ServerTaskWaiter, SpaceRepository, SpaceServerTaskRepository, TaskState } from "@octopusdeploy/api-client"; -import { OctoServerConnectionDetails } from "tasks/Utils/connection"; +import { getDeepLink, OctoServerConnectionDetails } from "tasks/Utils/connection"; import { TaskWrapper } from "tasks/Utils/taskInput"; import { getInputParameters, InputParameters } from "./input-parameters"; import { ExecutionResult } from "../../Utils/executionResult"; @@ -10,7 +10,7 @@ export interface WaitExecutionResult extends ExecutionResult { } export class Waiter { - constructor(readonly connection: OctoServerConnectionDetails, readonly task: TaskWrapper, readonly logger: Logger) { } + constructor(readonly connection: OctoServerConnectionDetails, readonly task: TaskWrapper, readonly logger: Logger) {} public async run() { const inputParameters = getInputParameters(this.logger, this.task); @@ -19,15 +19,16 @@ export class Waiter { const waitExecutionResults = inputParameters.showProgress ? await this.waitWithProgress(client, inputParameters) : await this.waitWithoutProgress(client, inputParameters); + const url = this.connection.url; const spaceId = await this.getSpaceId(client, inputParameters.space); let failedDeploymentsCount = 0; waitExecutionResults.map((r) => { - const url = `${this.connection.url}app#/${spaceId}/tasks/${r.serverTaskId}`; + const link = getDeepLink(url, `${spaceId}/tasks/${r.serverTaskId}`); const context = this.getContext(r); if (r.successful) { - this.logger.info?.(`Succeeded: ${url}`); + this.logger.info?.(`Succeeded: ${link}`); } else { - this.logger.warn?.(`Failed: ${url}`); + this.logger.warn?.(`Failed: ${link}`); failedDeploymentsCount++; } this.task.setOutputVariable(`${context}.completed_successfully`, r.successful.toString()); diff --git a/source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/release.ts b/source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/release.ts index e7301441..6b5bd80a 100644 --- a/source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/release.ts +++ b/source/tasks/CreateOctopusRelease/CreateOctopusReleaseV6/release.ts @@ -1,12 +1,5 @@ -import { - Client, - CreateReleaseCommandV1, - Logger, - Project, - ProjectRepository, - resolveSpaceId, -} from "@octopusdeploy/api-client"; -import { OctoServerConnectionDetails } from "../../Utils/connection"; +import { Client, CreateReleaseCommandV1, Logger, Project, ProjectRepository, resolveSpaceId } from "@octopusdeploy/api-client"; +import { getDeepLink, OctoServerConnectionDetails } from "../../Utils/connection"; import { createReleaseFromInputs } from "./createRelease"; import { createCommandFromInputs } from "./inputCommandBuilder"; import os from "os"; @@ -45,7 +38,7 @@ export class Release { const projects = await projectRepo.list({ partialName: command.ProjectName }); const matchedProjects = projects.Items.filter((p: Project) => p.Name.localeCompare(command.ProjectName) === 0); if (matchedProjects.length === 1) { - const link = `${this.connection.url}app#/${spaceId}/projects/${matchedProjects[0].Id}/deployments/releases/${version}`; + const link = getDeepLink(this.connection.url, `${spaceId}/projects/${matchedProjects[0].Id}/deployments/releases/${version}`); const markdown = `[Release ${version} created for '${matchedProjects[0].Name}'](${link})`; const markdownFile = path.join(getVstsEnvironmentVariables().defaultWorkingDirectory, `${uuidv4()}.md`); tasks.writeFile(markdownFile, markdown); diff --git a/source/tasks/Deploy/DeployV6/deploy.ts b/source/tasks/Deploy/DeployV6/deploy.ts index c731732f..314c267d 100644 --- a/source/tasks/Deploy/DeployV6/deploy.ts +++ b/source/tasks/Deploy/DeployV6/deploy.ts @@ -1,5 +1,5 @@ import { Client, CreateDeploymentUntenantedCommandV1, Logger, resolveSpaceId, ServerTask, SpaceServerTaskRepository } from "@octopusdeploy/api-client"; -import { OctoServerConnectionDetails } from "../../Utils/connection"; +import { getDeepLink, OctoServerConnectionDetails } from "../../Utils/connection"; import { createDeploymentFromInputs } from "./createDeployment"; import { createCommandFromInputs } from "./inputCommandBuilder"; import os from "os"; @@ -51,7 +51,7 @@ export class Deploy { results.forEach(function (result) { const task = taskLookup.get(result.serverTaskId); if (task != null) { - const link = `${url}app#/${spaceId}/deployments/${task.Arguments.DeploymentId}`; + const link = getDeepLink(url, `${spaceId}/deployments/${task.Arguments.DeploymentId}`); markdown += `[${result.environmentName}](${link})\n`; } }); diff --git a/source/tasks/DeployTenant/TenantedDeployV6/deploy.ts b/source/tasks/DeployTenant/TenantedDeployV6/deploy.ts index 490fe929..ab9fa919 100644 --- a/source/tasks/DeployTenant/TenantedDeployV6/deploy.ts +++ b/source/tasks/DeployTenant/TenantedDeployV6/deploy.ts @@ -1,5 +1,5 @@ import { CreateDeploymentTenantedCommandV1, Logger, Client, resolveSpaceId, SpaceServerTaskRepository, ServerTask } from "@octopusdeploy/api-client"; -import { OctoServerConnectionDetails } from "../../Utils/connection"; +import { getDeepLink, OctoServerConnectionDetails } from "../../Utils/connection"; import { createDeploymentFromInputs } from "./createDeployment"; import { createCommandFromInputs } from "./inputCommandBuilder"; import os from "os"; @@ -52,7 +52,7 @@ export class Deploy { results.forEach(function (result) { const task = taskLookup.get(result.serverTaskId); if (task != null) { - const link = `${url}app#/${spaceId}/deployments/${task.Arguments.DeploymentId}`; + const link = getDeepLink(url, `${spaceId}/deployments/${task.Arguments.DeploymentId}`); markdown += `[${result.tenantName}](${link})\n`; } }); diff --git a/source/tasks/Utils/connection.ts b/source/tasks/Utils/connection.ts index a2ccc6ac..17f02fc2 100644 --- a/source/tasks/Utils/connection.ts +++ b/source/tasks/Utils/connection.ts @@ -30,3 +30,10 @@ function getOctopusConnectionDetails(name: string): OctoServerConnectionDetails ignoreSslErrors: !!ignoreSSL && ignoreSSL.toLowerCase() === "true", }; } + +export function getDeepLink(baseUrl: string, path: string): string { + if (baseUrl.endsWith("/")) { + baseUrl = baseUrl.substring(0, baseUrl.length - 1); + } + return `${baseUrl}/app#/${path}`; +} From 8641ce39f3269d1a6174793ffd00589364d663c2 Mon Sep 17 00:00:00 2001 From: hnrkndrssn Date: Fri, 16 May 2025 11:56:15 +1000 Subject: [PATCH 2/3] chore(tests): add a couple of tests --- source/tasks/Utils/connection.test.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 source/tasks/Utils/connection.test.ts diff --git a/source/tasks/Utils/connection.test.ts b/source/tasks/Utils/connection.test.ts new file mode 100644 index 00000000..a825ad53 --- /dev/null +++ b/source/tasks/Utils/connection.test.ts @@ -0,0 +1,15 @@ +import { getDeepLink } from "./connection"; + +describe("DeepLinks", () => { + test("URL ends with / returns correctly formatted deep link", async () => { + const url = "https://octopus.com/vdir/"; + const expectedDeepLink = "https://octopus.com/vdir/app#/Spaces-1/deployments/Deployments-1"; + expect(getDeepLink(url, "Spaces-1/deployments/Deployments-1")).toBe(expectedDeepLink); + }); + + test("URL does not end with / return correctly formatted deep link", async () => { + const url = "https://octopus.com/vdir"; + const expectedDeepLink = "https://octopus.com/vdir/app#/Spaces-1/deployments/Deployments-1"; + expect(getDeepLink(url, "Spaces-1/deployments/Deployments-1")).toBe(expectedDeepLink); + }); +}); From 986f7914fdc493787288194c806fcc43ea084fdb Mon Sep 17 00:00:00 2001 From: hnrkndrssn Date: Fri, 16 May 2025 12:04:54 +1000 Subject: [PATCH 3/3] chore: update ubuntu runner --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index de689d06..0b2b8ad3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -60,7 +60,7 @@ jobs: checks: write strategy: matrix: - os: [windows-2022, ubuntu-20.04, macos-14] + os: [windows-2022, ubuntu-22.04, macos-14] steps: - uses: actions/checkout@v3 - name: Use Node.js