Skip to content

Commit

Permalink
CmdLine script (#4601)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsciple authored Jun 21, 2017
1 parent 9123f17 commit 30bb9a1
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 63 deletions.
20 changes: 10 additions & 10 deletions Tasks/CmdLine/Strings/resources.resjson/en-US/resources.resjson
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"loc.friendlyName": "Command Line",
"loc.helpMarkDown": "[More Information](https://go.microsoft.com/fwlink/?LinkID=613735)",
"loc.description": "Run a command line with arguments",
"loc.instanceNameFormat": "Run $(filename)",
"loc.description": "Run a command line script using cmd.exe on Windows and bash on Mac and Linux.",
"loc.instanceNameFormat": "Command Line Script",
"loc.releaseNotes": "Script task consistency. Added support for multiple lines.",
"loc.group.displayName.advanced": "Advanced",
"loc.input.label.filename": "Tool",
"loc.input.help.filename": "Tool name to run. Tool should be found in your path. Optionally, a fully qualified path can be supplied but that relies on that being present on the agent.<br/> Note: You can use **$(Build.SourcesDirectory)**\\\\ if you want the path relative to repo.",
"loc.input.label.arguments": "Arguments",
"loc.input.help.arguments": "Arguments passed to the tool. Use double quotes to escape spaces.",
"loc.input.label.workingFolder": "Working folder",
"loc.input.label.failOnStandardError": "Fail on Standard Error",
"loc.input.help.failOnStandardError": "If this is true, this task will fail if any errors are written to the StandardError stream.",
"loc.input.label.script": "Script",
"loc.input.label.workingDirectory": "Working Directory",
"loc.input.label.failOnStderr": "Fail on Standard Error",
"loc.input.help.failOnStderr": "If this is true, this task will fail if any errors are written to the StandardError stream.",
"loc.messages.CmdLineReturnCode": "%s exited with return code: %d",
"loc.messages.CmdLineFailed": "%s failed with error: %s"
"loc.messages.CmdLineFailed": "%s failed with error: %s",
"loc.messages.PS_ExitCode": "powershell exited with code '{0}'.",
"loc.messages.PS_UnableToDetermineExitCode": "Unexpected exception. Unable to determine the exit code from powershell."
}
130 changes: 130 additions & 0 deletions Tasks/CmdLine/cmdline.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
[CmdletBinding()]
param()

Trace-VstsEnteringInvocation $MyInvocation
try {
Import-VstsLocStrings "$PSScriptRoot\task.json"

# TODO MOVE ASSERT-VSTSAGENT TO THE TASK LIB AND LOC
function Assert-VstsAgent {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[version]$Minimum)

if ($Minimum -lt ([version]'2.104.1')) {
Write-Error "Assert-Agent requires the parameter to be 2.104.1 or higher"
return
}

$agent = Get-VstsTaskVariable -Name 'agent.version'
if (!$agent -or (([version]$agent) -lt $Minimum)) {
Write-Error "Agent version $Minimum or higher is required."
}
}

# Get inputs.
$input_failOnStderr = Get-VstsInput -Name 'failOnStderr' -AsBool
$input_script = Get-VstsInput -Name 'script'
$input_workingDirectory = Get-VstsInput -Name 'workingDirectory' -Require
Assert-VstsPath -LiteralPath $input_workingDirectory -PathType 'Container'

# Generate the script contents.
#TODO: CONVERT NEWLINES?
$contents = "$input_script"

# Write the script to disk.
Assert-VstsAgent -Minimum '2.115.0'
$tempDirectory = Get-VstsTaskVariable -Name 'agent.tempDirectory' -Require
Assert-VstsPath -LiteralPath $tempDirectory -PathType 'Container'
$filePath = [System.IO.Path]::Combine($tempDirectory, "$([System.Guid]::NewGuid()).cmd")
$null = [System.IO.File]::WriteAllText(
$filePath,
$contents.ToString(),
([System.Console]::OutputEncoding))

# Prepare the external command values.
$cmdPath = $env:ComSpec
Assert-VstsPath -LiteralPath $cmdPath -PathType Leaf
# Command line switches:
# /Q Turns echo off.
# /D Disable execution of AutoRun commands from registry.
# /E:ON Enable command extensions. Note, command extensions are enabled
# by default, unless disabled via registry.
# /V:OFF Disable delayed environment expansion. Note, delayed environment
# expansion is disabled by default, unless enabled via registry.
# /S Will cause first and last quote after /C to be stripped.
#
# TODO: ADD EXPLANATION WHY "CALL" IS REQUIRED
$arguments = "/Q /D /E:ON /V:OFF /S /C `"CALL `"$filePath`"`""
$splat = @{
'FileName' = $cmdPath
'Arguments' = $arguments
'WorkingDirectory' = $input_workingDirectory
}

# Switch to "Continue".
$global:ErrorActionPreference = 'Continue'
$failed = $false

# Run the script.
if (!$input_failOnStderr) {
Invoke-VstsTool @splat
} else {
$inError = $false
$errorLines = New-Object System.Text.StringBuilder
Invoke-VstsTool @splat 2>&1 |
ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
# Buffer the error lines.
$failed = $true
$inError = $true
$null = $errorLines.AppendLine("$($_.Exception.Message)")

# Write to verbose to mitigate if the process hangs.
Write-Verbose "STDERR: $($_.Exception.Message)"
} else {
# Flush the error buffer.
if ($inError) {
$inError = $false
$message = $errorLines.ToString().Trim()
$null = $errorLines.Clear()
if ($message) {
Write-VstsTaskError -Message $message
}
}

Write-Host "$_"
}
}

# Flush the error buffer one last time.
if ($inError) {
$inError = $false
$message = $errorLines.ToString().Trim()
$null = $errorLines.Clear()
if ($message) {
Write-VstsTaskError -Message $message
}
}
}

# Fail on $LASTEXITCODE
if (!(Test-Path -LiteralPath 'variable:\LASTEXITCODE')) {
$failed = $true
Write-Verbose "Unable to determine exit code"
Write-VstsTaskError -Message (Get-VstsLocString -Key 'PS_UnableToDetermineExitCode')
} else {
if ($LASTEXITCODE -ne 0) {
$failed = $true
Write-VstsTaskError -Message (Get-VstsLocString -Key 'PS_ExitCode' -ArgumentList $LASTEXITCODE)
}
}

# Fail if any errors.
if ($failed) {
Write-VstsSetResult -Result 'Failed' -Message "Error detected" -DoNotThrow
}
} finally {
Trace-VstsLeavingInvocation $MyInvocation
}
24 changes: 24 additions & 0 deletions Tasks/CmdLine/make.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"externals": {
"nugetv2": [
{
"name": "VstsTaskSdk",
"version": "0.8.1",
"repository": "https://www.powershellgallery.com/api/v2/",
"cp": [
{
"source": [
"*.ps1",
"*.psd1",
"*.psm1",
"lib.json",
"Strings"
],
"dest": "ps_modules/VstsTaskSdk/",
"options": "-R"
}
]
}
]
}
}
51 changes: 25 additions & 26 deletions Tasks/CmdLine/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "D9BAFED4-0B18-4F58-968D-86655B4D2CE9",
"name": "CmdLine",
"friendlyName": "Command Line",
"description": "Run a command line with arguments",
"description": "Run a command line script using cmd.exe on Windows and bash on Mac and Linux.",
"helpMarkDown": "[More Information](https://go.microsoft.com/fwlink/?LinkID=613735)",
"category": "Utility",
"visibility": [
Expand All @@ -15,10 +15,12 @@
],
"author": "Microsoft Corporation",
"version": {
"Major": 1,
"Minor": 1,
"Patch": 3
"Major": 2,
"Minor": 120,
"Patch": 0
},
"releaseNotes": "Script task consistency. Added support for multiple lines.",
"preview": true,
"groups": [
{
"name": "advanced",
Expand All @@ -28,31 +30,28 @@
],
"inputs": [
{
"name": "filename",
"type": "string",
"label": "Tool",
"defaultValue": "",
"name": "script",
"type": "multiLine",
"label": "Script",
"required": true,
"helpMarkDown": "Tool name to run. Tool should be found in your path. Optionally, a fully qualified path can be supplied but that relies on that being present on the agent.<br/> Note: You can use **$(Build.SourcesDirectory)**\\\\ if you want the path relative to repo."
},
{
"name": "arguments",
"type": "string",
"label": "Arguments",
"defaultValue": "",
"helpMarkDown": "Arguments passed to the tool. Use double quotes to escape spaces.",
"required": false
"defaultValue": "echo Write your commands here\necho Use the Environment input below to map secret variables into environment variables",
"properties": {
"resizable": "true",
"rows": "10",
"maxLength": "5000"
},
"helpMarkDown": ""
},
{
"name": "workingFolder",
"name": "workingDirectory",
"type": "filePath",
"label": "Working folder",
"label": "Working Directory",
"defaultValue": "",
"required": false,
"groupName": "advanced"
},
{
"name": "failOnStandardError",
"name": "failOnStderr",
"type": "boolean",
"label": "Fail on Standard Error",
"defaultValue": "false",
Expand All @@ -61,12 +60,10 @@
"groupName": "advanced"
}
],
"instanceNameFormat": "Run $(filename)",
"instanceNameFormat": "Command Line Script",
"execution": {
"Process": {
"target": "$(filename)",
"argumentFormat": "$(arguments)",
"workingDirectory": "$(workingFolder)",
"PowerShell3": {
"target": "cmdline.ps1",
"platforms": [
"windows"
]
Expand All @@ -78,6 +75,8 @@
},
"messages": {
"CmdLineReturnCode": "%s exited with return code: %d",
"CmdLineFailed": "%s failed with error: %s"
"CmdLineFailed": "%s failed with error: %s",
"PS_ExitCode": "powershell exited with code '{0}'.",
"PS_UnableToDetermineExitCode": "Unexpected exception. Unable to determine the exit code from powershell."
}
}
51 changes: 25 additions & 26 deletions Tasks/CmdLine/task.loc.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
],
"author": "Microsoft Corporation",
"version": {
"Major": 1,
"Minor": 1,
"Patch": 3
"Major": 2,
"Minor": 120,
"Patch": 0
},
"releaseNotes": "ms-resource:loc.releaseNotes",
"preview": true,
"groups": [
{
"name": "advanced",
Expand All @@ -28,45 +30,40 @@
],
"inputs": [
{
"name": "filename",
"type": "string",
"label": "ms-resource:loc.input.label.filename",
"defaultValue": "",
"name": "script",
"type": "multiLine",
"label": "ms-resource:loc.input.label.script",
"required": true,
"helpMarkDown": "ms-resource:loc.input.help.filename"
},
{
"name": "arguments",
"type": "string",
"label": "ms-resource:loc.input.label.arguments",
"defaultValue": "",
"helpMarkDown": "ms-resource:loc.input.help.arguments",
"required": false
"defaultValue": "echo Write your commands here\necho Use the Environment input below to map secret variables into environment variables",
"properties": {
"resizable": "true",
"rows": "10",
"maxLength": "5000"
},
"helpMarkDown": ""
},
{
"name": "workingFolder",
"name": "workingDirectory",
"type": "filePath",
"label": "ms-resource:loc.input.label.workingFolder",
"label": "ms-resource:loc.input.label.workingDirectory",
"defaultValue": "",
"required": false,
"groupName": "advanced"
},
{
"name": "failOnStandardError",
"name": "failOnStderr",
"type": "boolean",
"label": "ms-resource:loc.input.label.failOnStandardError",
"label": "ms-resource:loc.input.label.failOnStderr",
"defaultValue": "false",
"required": false,
"helpMarkDown": "ms-resource:loc.input.help.failOnStandardError",
"helpMarkDown": "ms-resource:loc.input.help.failOnStderr",
"groupName": "advanced"
}
],
"instanceNameFormat": "ms-resource:loc.instanceNameFormat",
"execution": {
"Process": {
"target": "$(filename)",
"argumentFormat": "$(arguments)",
"workingDirectory": "$(workingFolder)",
"PowerShell3": {
"target": "cmdline.ps1",
"platforms": [
"windows"
]
Expand All @@ -78,6 +75,8 @@
},
"messages": {
"CmdLineReturnCode": "ms-resource:loc.messages.CmdLineReturnCode",
"CmdLineFailed": "ms-resource:loc.messages.CmdLineFailed"
"CmdLineFailed": "ms-resource:loc.messages.CmdLineFailed",
"PS_ExitCode": "ms-resource:loc.messages.PS_ExitCode",
"PS_UnableToDetermineExitCode": "ms-resource:loc.messages.PS_UnableToDetermineExitCode"
}
}
1 change: 0 additions & 1 deletion make-options.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"Chef",
"ChefKnife",
"CMake",
"CmdLine",
"CocoaPods",
"CopyFiles",
"CopyFilesOverSSH",
Expand Down

0 comments on commit 30bb9a1

Please sign in to comment.