azure-pipelines-task-lib and isOutput setVariable
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.