Assigning a variable to a variable in Github action variables - yaml

I'm new to yaml & Github & actions and trying to figure out how to assign x=y vs. x=value. Is this possible? In the example below, I'm trying to assign CertificatePath as a global variable to a concatenation of several directories.
env:
Solution_Name: WpfApp3.sln
Test_Project_Path: TestProject1\TestProject1.csproj
Wap_Project_Directory: WapProjTemplate1
Wap_Project_Path: WapProjTemplate1\WapProjTemplate1.wapproj
SigningCertificate: GitHubActionsDemo.pfx
- name: SetCertPath
run:
$currentDirectory = Get-Location
tempcertificatePath= Join-Path -Path $currentDirectory -ChildPath $env:Wap_Project_Directory -AdditionalChildPath $env:SigningCertificate
echo "CertificatePath=${{ tempcertificatePath }}" >> $GITHUB_ENV
Thanks!

If you want to run multiple lines as part of a run step, you need to use a |. Furthermore, when assigning a variable, you don't need to use the $ on the left hand side.
Example:
- run: |
myVar="foo"
mySecondVar="${myVar}bar"
echo $mySecondVar

Related

How can I source Terraform HCL variables in bash?

I have Terraform variables defined like
variable "location" {
type = string
default = "eastus"
description = "Desired Azure Region"
}
variable "resource_group" {
type = string
default = "my-rg"
description = "Desired Azure Resource Group Name"
}
and potentially / partially overwritten in terraform.tfvars file
location = "westeurope"
and then defined variables as outputs e.g. a file outputs.tf:
output "resource_group" {
value = var.resource_group
}
output "location" {
value = var.location
}
How can I "source" the effective variable values in a bash script to work with these values?
One way is to use Terraform output values as JSON and then an utility like jq to convert and source as variables:
source <(terraform output --json | jq -r 'keys[] as $k | "\($k|ascii_upcase)=\(.[$k] | .value)"')
note that output is only available after executing terraform plan, terraform apply or even a terraform refresh
If jq is not available or not desired, sed can be used to convert Terraform HCL output into variables, even with upper case variable names:
source <(terraform output | sed -r 's/^([a-z_]+)\s+=\s+(.*)$/\U\1=\L\2/')
or using -chdir argument if Terraform templates / modules are in another folder:
source <(terraform -chdir=$TARGET_INFRA_FOLDER output | sed -r 's/^([a-z_]+)\s+=\s+(.*)$/\U\1=\L\2/')
Then these variables are available in bash script:
LOCATION="westeurope"
RESOURCE_GROUP="my-rg"
and can be addressed as $LOCATION and $RESOURCE_GROUP.

Change name of Variable while in a loop

I have this idea in mind:
I have this number: CN=20
and a list=( "xa1-" "xa2-" "xb1-" "xb2-")
and this is my script:
for a in "${list[#]}"; do
let "CN=$(($CN+1))"
echo $CN
Output:
21
22
23
24
I am trying to create a loop where it creates the following variables, which will be referenced later in my script:
fxp0_$CN="fxp-$a$CN"
fxp0_21="fxp-xa1-21"
fxp0_22="fxp-xa2-22"
fxp0_23="fxp-xb1-23"
fxp0_24="fxp-xb2-24"
However, I have not been able to find a way to change the variable name within my loop. Instead, I was trying myself and I got this error when trying to change the variable name:
scripts/srx_file_check.sh: line 317: fxp0_21=fxp0-xa2-21: command not found
After playing around I found the solution!
for a in "${list[#]}"; do
let "CN=$(($CN+1))"
fxp_int="fxp0-$a$CN"
eval "fxp0_$CN=${fxp_int}"
done
echo $fxp0_21
echo $fxp0_22
echo $fxp0_23
echo $fxp0_24
echo $fxp0_25
echo $fxp0_26
echo $fxp0_27
echo $fxp0_28
Output:
fxp0-xa1-21
fxp0-xa2-22
fxp0-xb1-23
fxp0-xb2-24
fxp0-xc1-25
fxp0-xc2-26
fxp0-xd1-27
fxp0-xd2-28
One common method for maintaining a dynamically generated set of variables is via arrays.
When the variable names vary in spelling an associative array comes in handy whereby the variable 'name' acts as the array index.
In this case since the only thing changing in the variable names is a number we can use a normal (numerically indexed) array, eg:
CN=20
list=("xa1-" "xa2-" "xb1-" "xb2-")
declare -a fxp0=()
for a in "${list[#]}"
do
(( CN++ ))
fxp0[${CN}]="fxp-${a}${CN}"
done
This generates:
$ declare -p fxp0
declare -a fxp0=([21]="fxp-xa1-21" [22]="fxp-xa2-22" [23]="fxp-xb1-23" [24]="fxp-xb2-24")
$ for i in "${!fxp0[#]}"; do echo "fxp0[$i] = ${fxp0[$i]}"; done
fxp0[21] = fxp-xa1-21
fxp0[22] = fxp-xa2-22
fxp0[23] = fxp-xb1-23
fxp0[24] = fxp-xb2-24
As a general rule can I tell you that it's not a good idea to modify names of variables within loops.
There is, however, a way to do something like that, using the source command, as explained in this URL with some examples. It comes down to the fact that you treat a file as a piece of source code.
Good luck

what's the difference between (%%)bash and bang(!)

In jupyter notebook, following gcloud commands work with bang(!) but not with %%bash
import os
PROJECT = 'mle-1234'
REGION = 'us-central1'
BUCKET = 'mle-1234'
# for bash
os.environ['PROJECT'] = PROJECT
os.environ['BUCKET'] = BUCKET
os.environ['REGION'] = REGION
os.environ['TFVERSION'] = '1.14.0' # Tensorflow version
# Set GCP Project and Region
%%bash
gcloud config set project $PROJECT
gcloud config set compute/region $REGION
gcloud config list
I get this error message when I execute the last snippet above with %%bash
File "<ipython-input-16-f93912dbcc34>", line 3
gcloud config set project $[PROJECT]
^
SyntaxError: invalid syntax
However, project and region values get set with same lines of code but by removing %%bash and prefixing (!) with all gcloud commands.
# Set GCP Project and Region
!gcloud config set project $PROJECT
!gcloud config set compute/region $REGION
!gcloud config list
Result with using (!)
Updated property [core/project].
Updated property [compute/region].
[compute]
region = us-central1
zone = us-central1-a
[core]
account = my-service-account#mle-1234.iam.gserviceaccount.com
disable_usage_reporting = False
project = mle-1234
What could be the reason for this behavior?
%%bash
%%bash is considered part of the Built-in magic commands. Run cells with bash in a subprocess. This is a shortcut for %%script bash. You can combine code from multiple kernels into one notebook. For example:
%%HTML
%%python2
%%python3
%%ruby
%%perl
implementation:
%%bash
factorial()
{
if [ "$1" -gt "1" ]
then
i=`expr $1 - 1`
j=`factorial $i`
k=`expr $1 \* $j`
echo $k
else
echo 1
fi
}
input=5
val=$(factorial $input)
echo "Factorial of $input is : "$val
! command
Starting a code cell with a bang character, e.g. !, instructs jupyter to treat the code on that line as an OS shell command
!cat /etc/os-release | grep VERSION
Output:
VERSION="16.04 LTS (Xenial Xerus)"
VERSION_ID="16.04"
Answer: since you are using gcloud commands, Jupyter will interpret those as OS shell commands; and therefore, using !glcoud will work.

How To set Azure pipeline variable from PowerShell

I am trying to set the Azure pipeline variable value in PowerShell. I have created one variable winversion in the Azure pipeline. Now, in a PowerShell task, I want to assign some values to the winversion variable.
My simple question is how can I change the value of an Azure PipeLine variable at run time?
Write-Host "Main value is $winversion"
$env:WINVERSION="abhinav";
Write-Host "Modified value is $env:WINVERSION"
Write-Host "Main value is $(winversion)"
Firstline print: original value is 123
Thirdline Print: Modified value is abhinav
Fourth Line print: 123
I want when I change the value of winversion from "123" to "abhinav" so it actually changes the pipeline variable value to abhinav.
I want to update this variable through Powershell. I am using one PowerShell script calling the API and trying to update its variable but getting the page not found error:-
param(
[string]$winVersion
)
$body = "{ 'definition' : { 'id' :85}
}"
$valueName="Winver"
$definitionId=85
$User=""
$Password=""
$base64authinfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User, $Password)))
$Uri = "https://Muac.visualstudio.com/OSGCXE/_apis/release/releases?api-version=2.0"
$urlDef = "https://Muac.visualstudio.com/OSGCXE/_apis/release/definitions/" + $definitionId + "?api-version=2.0"
$definition = Invoke-RestMethod -Headers #{Authorization=("Basic {0}" -f $base64authInfo)} -Method Get -Uri $urlDef
#Write-Host $definition
$definition.variables.$valueName.Value = "$winVersion"
$definitionJson = $definition | ConvertTo-Json -Depth 50 -Compress
#Write-Host (ConvertTo-Json $definition -Depth 100)
$update=Invoke-RestMethod -Headers #{Authorization=("Basic {0}" -f $base64authInfo)} -Method Put -Uri $urlDef -Body $definitionJson -ContentType "application/json"
#Write-Host "$update"
#$buildresponse = Invoke-RestMethod -Method Post -ContentType application/json -Uri $Uri -Headers #{Authorization=("Basic {0}" -f $base64authinfo)} -Body $body
#write-Host $buildresponse.status
How To set azure pipeline variable from PowerShell
There is a bit of confusion here, you use the variable $winversion in the powershell scripts, but the variable is set testvar in the pipeline variable.
Anyway, no matter we overwrite the pipeline variable value directly like you, or use the script "##vso[task.setvariable variable=testvar;]testvalue" to overwrite it, the overwrite value only work for current build pipeline. When you use the $(winversion) to get the value, it will still pull the value from pipeline variable value. To get the current value, you need use $env:WINVERSION.
Besides, you said:
I want when I change the value of winversion from "123" to "abhinav"
so it actually changes the pipeline variable value to abhinav.
If you mean you want change the pipeline variable value on the web portal, you need the REST API (Definitions - Update) to update the value of the build pipeline definition variable from a build task.
There is a very similar thread, you can check the answer for the details:
How to modify Azure DevOps release definition variable from a release task?
Note:Change the API to the build definitions:
PUT https://dev.azure.com/{organization}/{project}/_apis/build/definitions/{definitionId}?api-version=5.0
Hope this helps.
I found this link helpful: https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=powershell
This has the complete options of what you can do:
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch
You can reuse set variable from task to task, and also job to job.
I couldn't find anything on stage to stage.
In summary:
jobs:
# Set an output variable from job A
- job: A
pool:
vmImage: 'vs2017-win2016'
steps:
- powershell: echo "##vso[task.setvariable variable=myOutputVar;isOutput=true]this is the value"
name: setvarStep
- script: echo $(setvarStep.myOutputVar)
name: echovar
# Map the variable into job B
- job: B
dependsOn: A
pool:
vmImage: 'ubuntu-16.04'
variables:
myVarFromJobA: $[ dependencies.A.outputs['setvarStep.myOutputVar'] ] # map in the variable
# remember, expressions require single quotes
steps:
- script: echo $(myVarFromJobA)
name: echovar

in bash use parameter inside another parameter

I have list of parameters that take from a property file looks like that:
db_instanceid=i-0c2b12ae02d454018
db_secgrp=sg-8c2efcf3
backend_instanceid=i-0199621ba358d1814
backend_secgrp=sg-5e508221
frontend_instanceid=i-0199621ba358d1814
frontend_secgrp=sg-e152809e
in bash, I want to use an array to perform actions using those parameters,
Something like that:
declare -a arr=("frontend" "backend" "db")
for i in "${arr[#]}"
do
inter=$i
echo "Get PublicIp for $inter server"
echo "$inter security group - $inter_secgrp" ;
done
But $inter_secgrp itself will be read as a parameter,
so I get an empty string (which make sense). How can I read this parameter
the right way so I will get the value of all "secgrp"
needed output:
Get PublicIp for frontendserver
frontendserver security group - sg-e152809e
Get PublicIp for backend
backendsecurity group - sg-5e508221
Get PublicIp for db
dbsecurity group - sg-8c2efcf3
Could do it with indirect expansion
. parameterfile
declare -a arr=("frontend" "backend" "db")
for inter in "${arr[#]}"
do
echo "Get PublicIp for $inter server"
inter_secgrp=${inter}_secgrp
echo "$inter security group - ${!inter_secgrp}" ;
done
The temptation to use eval is particularly strong here.
. parameterfile
declare -a arr=("frontend" "backend" "db")
for inter in "${arr[#]}"
do
echo "Get PublicIp for $inter server"
eval inter_secgrp=\$${inter}_secgrp
echo "$inter security group - $inter_secgrp" ;
done
And then $inter_secgrp is what you want.
To be simple, eval tells Bash to evaluate the line for an extra time before executing it. Here after the first evaluation, the eval line turns to (for example
eval inter_secgrp=$db_secgrp
And then things after eval is evaluated again, so $db_secgrp gets expanded, giving what you want.

Resources