Parsing Json differs between PowerShell and GitHub "run" statement - json

I am trying to extract a single property from a json file. I am planning to save it off to an env. variable to use in a compare later. What works at the PS command line does not produce the same results through Github workflow run on a windows-latest runner (github hosted).
$json = Get-Content integration-manifest.json | ConvertFrom-Json
$json.[some_property]
This command in the shell shows me the value I am expecting for this property. In GitHub action, only the command line appears and not the output.
How can I get just the one value?

Try this:
- name: Read json
id: read-json
shell: pwsh
run: |
$json = Get-Content yourfile.json | ConvertFrom-Json
echo "::set-output name=prop::$(echo $json.prop)"
- run: echo ${{ steps.read-json.outputs.prop}}

Related

How to safely write json output to a file in a github workflow?

I have a github workflow that obtains information about all Github Releases in my repo and then processes the JSON response using jq. The issue is the shell code I have doesn't handle single-quotes in the JSON data (which it does have sometimes). How can I pipe out steps.release.outputs.data safely to a file without the quotations and other characters being interpreted by the shell?
- name: Get Release Info
uses: octokit/request-action#v2.x
id: release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
route: GET /repos/{org_repo}/releases/tags/{tag}
- name: Get Information from Release
run: |
echo '${{ steps.release.outputs.data }}' > release.json
jq -r '.assets[].browser_download_url' release.json > assets.txt
jq -r '.body' release.json > changelog.txt
The part that fails above is the line with echo in the second step. Because the steps.release.outputs.data content has single-quotes in it, that breaks it.
Note that, I only write the JSON data to a file (release.json in the example above) in an attempt to bypass shell processing special characters in the data. If there's a better way to do this without writing to a file I'd prefer that. The part that makes this challenging is that the response JSON gets placed into the final shell script as a literal string instead of as a bash variable.
You can use an environment variable:
- name: Get Information from Release
env:
DATA: ${{ steps.release.outputs.data }}
run: |
jq -r '.assets[].browser_download_url' <<<"$DATA" > assets.txt
jq -r '.body' <<<"$DATA" > changelog.txt

yq - inserting JSON as a raw string

I am writing a GitHub Action that does some CD and it uses yq to insert environment variables into a yaml file for deployment.
I'm trying to read a JSON from a GH secret that will eventually be read from env and loaded into python, where said string will be evaluated as a dictionary.
Running this in a terminal, for example:
yq -i '.value="{\"web\": \"test\"}"' test.yaml
Gives me:
value: '{"web": "test"}'
But in a Github Action, where I am doing this:
env:
JSON="{\"web\": \"test\"}"
...
- name: test
run : |
yq -i '
.value=strenv(JSON)
' deployment.yaml
Gives me:
Error: Bad expression, please check expression syntax
Doing other variations of that string, e.g. '{\"web\": \"test\"}', '\"{\"web\": \"test\"}\"' etc also gives me the same error.
I've tried searching on the yq repository and consulted the documentation but can't seem to find what I am looking for.
To summarise, my problem is that I want to read a JSON string as a string when it is evaluated by yq.
One of yq users has recently contributed to yq's github action docs regarding using env variables in github actions - it may help here:
- name: Get an entry with a variable that might contain dots or spaces
id: get_username
uses: mikefarah/yq#master
with:
cmd: yq '.all.children.["${{ matrix.ip_address }}"].username' ops/inventories/production.yml
- name: Reuse a variable obtained in another step
run: echo ${{ steps.get_username.outputs.result }}
See https://mikefarah.gitbook.io/yq/usage/github-action for more info.
Disclaimer: I wrote yq

How do I set an enviroment variable in GitHub action on a Windows Server?

First of all let me explain what I'm trying to do. I do write a c# .net application which I want to build if a tag was pushed to the master branch. This build should create a release named like Release {Tag}. The release should get all the artifacts which got build by the Windows Server. Right now I fail to get the tag only without the stuff in front of it.
I did find a question on how to set an environment variable here but this seems to work on linux only like this. I did try to find the information in the official documentation but I don't get it into a working state. Currently I'm using the following code trying to get the tag from the commit.
name: Live build
on: [push]
#push:
# tags:
# - '*'
jobs:
build:
name: Create build artifact
runs-on: windows-latest
steps:
- name: Clone repository
uses: actions/checkout#v2
with:
ref: develop
- name: Get current tag
run: echo '::set-env name=tag::${(("${env:GITHUB_REF}" -split "/")[-1] -replace " ","")}'
- name: Show current tag
run: echo "${env.tag}"
Unfortunately this is the result, which does not look correct to me
I did try to replace this part echo '::set-env name=tag::${(("${env:GITHUB_REF}" -split "/")[-1] -replace " ","")}' the call with the following test
echo '::set-env name=tag::(("${env:GITHUB_REF}" -split "/")[-1] -replace " ","")'
echo '::set-env name=tag::$(("${env:GITHUB_REF}" -split "/")[-1] -replace " ","")'
echo ::set-env name=tag::$(("${env:GITHUB_REF}" -split "/")[-1] -replace " ","")
echo ::set-env name=tag::(("${env:GITHUB_REF}" -split "/")[-1] -replace " ","")
Nothing did work just yet ... The default shell is set to powershell in this setup.
edit: Adding documentation from GitHub
With the latest changes to Github, the set-env command is deprecated. The new recommended way is to append text in UTF-8 encoding to a Github environmental file.
This is how I do it to get the current branch's name in windows powershell:
- run: |
chcp 65001 #set code page to utf-8
echo ("BRANCH_NAME=" + $env:GITHUB_REF.replace('refs/heads/', '')) >> $env:GITHUB_ENV
- run: echo "${{ env.BRANCH_NAME }}"
- run: echo $env:BRANCH_NAME
The method described in this answer is now deprecated. Please use this other answer.
---
Use this:
run: echo "::set-env name=tag::$(($env:GITHUB_REF -split '/')[-1] -replace ' ','')"
To get the variable, you just access it as if it were an environment variable:
run: echo "${env:tag}"

Github actions echo command not creating file

I'm in the process of moving a working CircleCI workflow over to Github Actions.
I'm running:
runs-on: ubuntu-latest
container:
image: google/cloud-sdk:latest
I run the following command:
echo ${{ secrets.GCLOUD_API_KEYFILE }} > ./gcloud-api-key.json
Before running this command, gcloud-api-key.json has not yet been created. This command works in CircleCI but in Github Actions I get the error:
/__w/_temp/asd987as89d7cf.sh: 2: /__w/_temp/asd987as89d7cf.sh: type:: not found
Does anyone know what this error means?
The reason was because my secret key was more then 1 line long. Once I made it one line it worked.
In order to use secrets which contain more than just one line (like secret jsons) one has to save the base64 encoded secret in Github which makes it one line.
On linux the encoding is done via:
cat mysecret.json | base64
Then in the action you need to decode it using
echo ${{ secrets.YOUR_SECRET }} | base64 -d > secret.json

Windows PowerShell command that changes text in a file

I need to change the my.ini file in my MySQL setup. I want to increase the max_connections. So basically have a .bat file that calls some powershell commands that replace the text file in a file and save it.
I am trying to do this by running a .bat file that will run a powershell command to change the text, so far this has been a huge headache. I have tried several solutions and it either doesn't give me the permissions to replace the text or it tells me that the object cannot be used in the piped command.
I managed to get it working in the admin powershell without using a .bat file but it won't let me do it in non admin and in a .bat file.
I tried this below
PowerShell -NoExit -Command "(Get-Content 'C:\ProgramData\MySQL\MySQL Server 5.7\my.ini') | ForEach-Object { $_ -replace \"max_connections=[0-9]+$\", \"max_connections=10000\" } | Set-Content 'C:\ProgramData\MySQL\MySQL Server 5.7\my.ini' -"
and get the following error
Set-Content : The input object cannot be bound to any parameters for the command either because the command does not
take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
I have also tried this variation using the admin powershell call
PowerShell -NoExit -Command "Start-Process powershell -verb runas -ArgumentList \"-NoExit -Command (Get-Content 'C:\ProgramData\MySQL\MySQL Server 5.7\my.ini') | ForEach-Object {{ $_ -replace \""max_connections=[0-9]+$\"", \""max_connections=10000\"" } | Set-Content 'C:\ProgramData\MySQL\MySQL Server 5.7\my.ini' -\""
but I get the following error
PowerShell -NoExit -Command "Start-Process powershell -verb runas -ArgumentList \"-NoExit -Command (Get-Content 'C:\ProgramData\MySQL\MySQL Server 5.7\my.ini') | ForEach-Object {{ $_ -replace \""max_connections=[0-9]+$\"", \""max_connections=10000\"" } | Set-Content 'C:\ProgramData\MySQL\MySQL Server 5.7\my.ini' -\""
'ForEach-Object' is not recognized as an internal or external command,
operable program or batch file.
I have looked at several stack overflow questions regarding this but I cannot seem to get it to work.
If there is an easier way get the solution done then I am open to suggestions.
UPDATE:
When I copy and paste the solution or get another program to pass it to powershell.exe I get these weird square brackets in the command, why does this happen? (I use innoscript to call powershell.exe)
Being able to do it in a batch file should just be getting your syntax right. Try this:
PowerShell -NoExit -Command {(Get-Content 'C:\ProgramData\MySQ‌​L\MySQL Server 5.7\my.ini') | ForEach-Object { $_ -replace "max_connections=[0-‌​9]+$", "max_connections=100‌​00" } | Set-Content 'C:\ProgramData\MySQ‌​L\MySQL Server 5.7\my.ini'}
As for not having to run in Admin, check the security tab on your file and make sure your user account has rights to it, and not just people in the Administrators group.