Skip to main content

One post tagged with "custom task"

View All Tags

azure-pipelines-task-lib and isOutput setVariable

ยท 2 min read

Some blog posts are insightful treatises on the future of web development, some are "here's how I solved my problem". This is most assuredly the latter.

I'm writing an custom pipelines task extension for Azure Pipelines. It's written with TypeScript and the azure-pipelines-task-lib.

The pipeline needs to output a variable. Azure Pipelines does that using the setvariable command combined with isOutput=true. This looks something like this: ##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the value".

The bad news is that the lib doesn't presently support isOutput=true. Gosh it makes me sad. Hopefully in future it will be resolved. But what now?

For now we can hack ourselves a workaround:

import * as tl from 'azure-pipelines-task-lib/task';import * as tcm from 'azure-pipelines-task-lib/taskcommand';import * as os from 'os';
/** * Sets a variable which will be output as well. * * @param     name    name of the variable to set * @param     val     value to set * @param     secret  whether variable is secret.  Multi-line secrets are not allowed.  Optional, defaults to false * @returns   void */export function setOutputVariable(name: string, val: string, secret = false): void {    // use the implementation of setVariable to set all the internals,    // then subsequently set the output variable manually    tl.setVariable(name, val, secret);
    const varValue = val || '';
    // write the command    // see https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#set-a-multi-job-output-variable    _command(        'task.setvariable',        { variable: name || '', isOutput: 'true', issecret: (secret || false).toString() },        varValue    );}
const _outStream = process.stdout;
function _writeLine(str: string): void {    _outStream.write(str + os.EOL);}
function _command(command: string, properties: any, message: string) {    const taskCmd = new tcm.TaskCommand(command, properties, message);    _writeLine(taskCmd.toString());}

The above is effectively a wrapper for the existing setVariable. However, once it's called into the initial implementation, setOutputVariable then writes out the same variable once more, but this time bolting on isOutput=true.

Finally, I've raised a PR to see if isOutput can be added directly to the library. You can track progress on that here.