YAML anchors for PowerShell scripts - powershell

I have YAML file for GitLab CI/CD Pipeline
.myanchor: &myanchor
- 'echo "Some Test"'
My Job:
script:
- 'echo "Some Text"'
- '*myanchor'
When I run pipeline, I get an error "myanchor : The term '*myanchor' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."
I tried removing quotes in a string - '*myanchor' but then CLint says that YAML is incorrect.
What am I doing wrong?

'*myanchor' is a YAML scalar and will be loaded as string. If you want to refer to the node with the anchor &myanchor, you must not use quotes.
If you drop the quotes, the structure in My Job will be
My Job:
script:
- 'echo "Some Text"'
- - 'echo "Some Text"'
It is likely that nested sequences are not supported for the content of script: (this is not a limitation of YAML per se, but a limitation of the tool that processes this structure).
To fix it, you need to put the anchor on the sequence item instead of the list:
.myanchor:
- &myanchor 'echo "Some Test"'
My Job:
script:
- 'echo "Some Text"'
- *myanchor
Now the problem is probably that you want to reference multiple items with *myanchor and put each of them as item directly into the script: sequence. That is simply not possible with YAML so you need to find another solution – perhaps preprocessing your YAML with a templating engine (lots of YAML's heavy users like e.g. Ansible and SaltStack do this).

Related

How to use a GitLab variable to represent the directory to a command in PowerShell

I am writing a PowerShell script for a GitLab CICD pipeline that will deploy a file to our TEST box via FTP. This works by using a command to execute an FTP client (winSCP.exe) with a text file as input.
The basic code works, however I decided to replace the hardcoded values and paths with GitLab variables for greater security and to simplify changes. Most of the variable additions worked, but using a variable to replace the path to the FTP client failed - see below:
./$FTPCLIENTDIRECTORY : The term './$FTPCLIENTDIRECTORY' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path
was included, verify that the path is correct and try again.
Right now this section of code works:
'./Resources/WinSCP.exe /log="$LOGFILEDIRECTORY" /ini=nul /script="$SCRIPTDIRECTORY" /parameter $FTPUSERNAME $FTPPASSWORD $FTPCERTIFICATE $FTPFILE'
I am trying to get something more like:
'./$FTPCLIENTDIRECTORY /log="$LOGFILEDIRECTORY" /ini=nul /script="$SCRIPTDIRECTORY" /parameter $FTPUSERNAME $FTPPASSWORD $FTPCERTIFICATE $FTPFILE'
I'm guessing that the ./ here operates as some kind of escape sequence that prevents YAML from recognizing the variable, however nothing none of the YAML or PowerShell escape characters I've used to escape-the-escape characters have worked.
Do you have any insight into why this is happening and or what a solution might be?

Powershell Variable replacement not working from command line

I have the following command I want to run from PowerShell:
docker run -v C:\src\docker_certs:/root/.dotnet/https -it MyContainer:MyTag /bin/bash
When I run that it works perfectly. (It mounts a volume using the source folder at the destination folder.)
But when I run this:
docker run -v $env:DOCKER_CERTS_PATH:/root/.dotnet/https -it MyContainer:MyTag /bin/bash
The volume does not get mounted.
I run this to check the value:
echo $env:DOCKER_CERTS_PATH
And it returns:
C:\src\docker_certs
As I understood things, it should have replaced the value of $env:DOCKER_CERTS_PATH with C:\src\docker_certs in the second command.
How can I get the PowerShell reference to an environment variable to replace when I run a command?
Enclose the environment-variable reference in {...}:
docker run -v ${env:DOCKER_CERTS_PATH}:/root/.dotnet/https ...
Alternatively, `-escape the : char. following the env.-var. reference:
docker run -v $env:DOCKER_CERTS_PATH`:/root/.dotnet/https ...
As for what you tried:
docker run -v $env:DOCKER_CERTS_PATH:/root/.dotnet/https ...
If you don't use {...} to explicitly delineate a variable name, PowerShell may have a different idea of where the variable name ends than you do.
As an alternative to using {...}, you can `-escape the first character you don't want to be considered part of the variable name.
Note that your command argument is in this case implicitly treated as if it were enclosed in "...", so the above applies to expandable strings ("...") too.
For an comprehensive discussion of how unquoted tokens are parsed as command arguments, see this answer.
In the case at hand, the : that follows $env:DOCKER_CERTS_PATH is not considered the end of the variable reference; instead, it is considered part of the variable name, so that PowerShell looks for an environment variable (env:) literally named DOCKER_CERTS_PATH: (sic).
Since no such environment variable (presumably) exists, $env:DOCKER_CERTS_PATH: expands to the empty string and all that is passed to docker is /root/.dotnet/https.
You can verify that DOCKER_CERTS_PATH: is a valid environment variable name as follows:
PS> $env:DOCKER_CERTS_PATH: = 'hi'; $env:DOCKER_CERTS_PATH:
hi
By contrast, a regular (shell) variable is not permitted to contain :, because that : - in the absence of a namespace prefix such as env: - is itself considered a namespace prefix, which fails, because then the variable-name part is missing:
PS> $DOCKER_CERTS_PATH: = 'hi' # BREAKS, even with {...}
Variable reference is not valid. ':' was not followed by a valid variable name character. Consider using ${} to delimit the name.
The first : in a variable identifier is invariably considered the end of the namespace identifier, which must refer to an existing PowerShell drive name, as reported by Get-PSDrive.
This notation is called namespace variable notation, as explained in this answer.

Can't access build variables from powershell script

I'm trying to use the Build variables in a script. According to this documentation I should be able to use the following:
Write-Host "BUILD_DATE: $Env:BUILD_DATE"
Write-Host "BUILD_REV: $Env:BUILD_REV"
However, I only get the following output
BUILD_DATE:
BUILD_REV:
I've also tried this syntax:
Write-Host "BUILD_DATE: $(Env:BUILD_DATE)"
Write-Host "BUILD_REV: $(Env:BUILD_REV)"
Write-Host "BUILD_DATE: $(Build.Date)"
Write-Host "BUILD_REV: $(Build.Rev)"
But the first segment gives The term 'Env:BUILD_DATE' is not recognized and the second segment gives The term 'Build.Date' is not recognized
How can I use the build variables in my script?
Disclaimer: I know virtually nothing about Azure pipelines, so my answer is based on reading the docs. Do let us know if I got things wrong.
Your first command uses the correct syntax for referencing environment variables in PowerShell (also inside an expandable (double-quoted) string).
(The other commands, based on subexpression operator $(...), mistakenly try to execute commands named Env:BUILD_DAT, ... rather than referencing variables.)
Your problem seems to be that the targeted environment variables do not exist.
The list of predefined variables that are exposed as environment variables does not contain variables named Build.Date / $env:BUILD_DATE and Build.Rev / $env:BUILD_REV.
By contrast, variables named Date and Rev seemingly do exist - as you state, they are used in the default format definition for the Build.BuildNumber / $Env:BUILD_BUILDNUMBER build variable, $(Date:yyyyMMdd)$(Rev:.r) - but are seemingly of a different kind not exposed as env. vars. (unlike Build.BuildNumber / $Env:BUILD_BUILDNUMBER itself, which is exposed).
(I don't know where these variables are defined or how they are classified, and where this is documented - do tell us if you know.)
A quick workaround would be to split the value of $Env:BUILD_BUILDNUMBER into its constituent parts:
# Split the build number into date and revision, by "."
$date, $rev = $Env:BUILD_BUILDNUMBER -split '\.'
"BUILD_DATE: $date"
"BUILD_REV: $rev"

Concourse CI shell commands being quoted

We are trying to copy multiple jar files in a Concourse CI package.yml file as part of a run step:
run:
path:
args:
- -exc
- |
...
cp project/target/*.jar build-output/.
But Concourse is adding single quotes to the source file, so that it's looking for a file named 'project/target/*.jar', and of course it's not finding it.
+ cp 'project/target/*.jar' build-output/.
cp: can't stat 'project/target/*.jar'; no such file or directory
I even tried putting double quotes around the jar file name, hoping that it might keep Concourse from changing it, but it made no difference.
We want to use file globbing so that we can use this generically, so that we don't need to know the file names ahead of time. Is there any way we can get this to work?
Bizarre. Try specifying the shell:
run:
path: sh <== missing `sh` or the shell you have available in the image
args:
- -exc
- |
...
cp project/target/*.jar build-output/ <== no `.`
Mhhh, actually maybe the quotes are misleading, there is nothing below project/target :-) Try with
run:
path: sh <== missing `sh` or the shell you have available in the image
args:
- -exc
- |
...
# is anything here ?
ls -1 project/target
cp project/target/*.jar build-output/ <== no `.`
set -x mode quotes all arguments; it doesn't mean that it actually quoted the argument. I think you had a red herring, but I'm glad you got it working.

How to pass powershell script variable values to downstream task in Release pipeline

Created a CD with few steps starting from "Azure PowerShell Task".
In Azure PowerShell tasks, executing a PowerShell script file and set a value in a variable.
At the end of the script I have set the variable with a value –
echo "##vso[task.setvariable variable=myvariable;isSecret=false;isOutput=true;]myvalue"
myvariable is the variable
myvalue is the value.
Based on the value of “myvariable”; downstream task will be executed or skipped. Mentioned "Custom Condition" in downstream task (Task - Azure Create or Update Resource) –
and(succeeded(), eq(variables[‘myvariable’], ‘myvalue’))
But, it’s always skipping the step; despite the correct value is passing. Here is my release tasks snippet -
How do I overcome?
try
Write-Host "##vso[task.setvariable variable=myvariable;isSecret=false;isOutput=true;]myvalue"
And then
and(succeeded(), eq(variables['myvariable'], 'myvalue'))
In the second part, the code you pasted in has the incorrect quote types, you had curly quotes ‘ ’ rather than the normal straight quotes ' '
You often end up with the wrong quotes if copying / pasting from Word or Outlook. I'm sure there's a proper a typography term for them.
Thanks everyone for your valuable input. Resolution -
PowerShell Script -
$myvalue="hello"
Write-Host "##vso[task.setvariable variable=myvariable]$myvalue"
Assign value ("hello") in a variable ($myvalue), then set it in "Write-Host". Direct value did not work for me.
Now we can use/verify "myvariable" value in downstream tasks in Custom Condition as mentioned by #Alex KeySmith.
and(succeeded(), eq(variables['myvariable'], 'hello'))
task -
Works in Build and Release pipeline.