1
votes

I'm working on an Azure DevOps extension that includes a custom task that adds an attachment. It can be used in both Build or Release pipeline.

Using the npm package vss-web-extension-sdk and TypeScript, how can I retrieve the content of this attachment for a specific Release Pipeline deployment, a specific environment and a specific deployment attempt ?

The final goal is to inject the attachment content (which is HTML) into an iframe, inside a tab contribution of a release.

This is where I'm stuck:

import Controls = require("VSS/Controls");
import TFS_Build_Contracts = require("TFS/Build/Contracts");
import TFS_Build_Extension_Contracts = require("TFS/Build/ExtensionContracts");
import TFS_DistributedTask_Contracts = require("TFS/DistributedTask/Contracts");
import TFS_Release_Extension_Contracts = require("ReleaseManagement/Core/ExtensionContracts");
import TFS_Release_Contracts = require("ReleaseManagement/Core/Contracts");
import DT_Client = require("TFS/DistributedTask/TaskRestClient");
import RM_Client = require("ReleaseManagement/Core/RestClient");

// [...]

private async searchForAttachment(release: TFS_Release_Contracts.Release) {
    let vsoContext: WebContext = VSS.getWebContext();
    let rmClient = <RM_Client.ReleaseHttpClient5>RM_Client.getClient();
    let projectId = vsoContext.project.id;

    // For test purpose, target the last environment and last deployment attempt
    let env = release.environments[release.environments.length - 1];
    let attempt = env.deploySteps[env.deploySteps.length - 1];

    // Where I am supposed to retrieve "timelineId" ?
    let attachments = rmClient.getTaskAttachments(
        projectId, release.id, env.id, attempt.id, timelineId, 'my_attachment_type'
    );

    // The documentation says that the call above is deprecated, and I should use getReleaseTaskAttachments
    // But, where I am supposed to retrieve "planId" ?
    // Also, getReleaseTaskAttachments is undefined in the latest version of the npm package...
    attachments = rmClient.getReleaseTaskAttachments(
        projectId, release.id, env.id, attempt.id, planId, 'my_attachment_type'
    );
}

FYI, I'm already able to retrieve the attachment from a Build Pipeline, but it does not apply to a Release deployment. It is simpler and I found enough documentation online.

Also, I'm adding the attachment in the custom task using the task.addattachment command:

##vso[task.addattachment type=myattachmenttype;name=myattachmentname;]c:\myattachment.txt
1

1 Answers

0
votes

While configuring the release definition, each job that you add to the workflow maps to a plan/planId when the release triggers. Eg. When I queue a release on a definition where the workflow looks like the one below, the deploy step object (env.deploySteps[env.deploySteps.length - 1]) will contain two release deploy phases.

enter image description here

The plan Id for the two jobs can be retrieved as -

env.deploySteps[env.deploySteps.length - 1].releaseDeployPhases[0].runPlanId
env.deploySteps[env.deploySteps.length - 1].releaseDeployPhases[1].runPlanId

Each task that runs within the job (Bash Script in this case) will create a timeline that is used to retrieve the logs and attachments. I'll do this to get the timeline Id for BashScript,

env.deploySteps[env.deploySteps.length - 1].releaseDeployPhases[0].deploymentJobs[0].tasks[0].timelineRecordId

The hierarchy is a bit complex for the fact that a deployStep can contain N(>1) phases. Each phase can contain multiple jobs (usually the case with deployment groups and multipliers, if you don't use those just fall back to deploymentJobs[0]). Within each job there are multiple tasks that you configured in the workflow, each creating a timeline of its own.