Rename a file based on release - github-actions

I'm trying to rename a file when a new release is tagged, but it is failing.
- name: rename file
run: mv ./Code/.pio/build/attiny841/firmware.hex ./Code/.pio/build/attiny841/megadesk-${{ $GITHUB_REF_NAME }}.hex
However when it runs I get an error
Invalid workflow file: .github/workflows/version_pio_build.yml#L44
The workflow is not valid. .github/workflows/version_pio_build.yml (Line: 44, Col: 12): Unexpected symbol: '$GITHUB_REF_NAME'. Located at position 1 within expression: $GITHUB_REF_NAME
If I change this to
- name: rename file
run: mv ./Code/.pio/build/attiny841/firmware.hex ./Code/.pio/build/attiny841/megadesk-${{ env.GITHUB_REF_NAME }}.hex
Then the resulting execution is
mv ./Code/.pio/build/attiny841/firmware.hex ./Code/.pio/build/attiny841/megadesk-.hex
Note this is triggered on a tag push.
- name: env list
run: env
This has a list of variables including
...
RUNNER_TOOL_CACHE=/opt/hostedtoolcache
ImageVersion=20220220.1
DOTNET_NOLOGO=1
GITHUB_REF_NAME=v25
GRAALVM_11_ROOT=/usr/local/graalvm/graalvm-ce-java11-22.0.0.2
GITHUB_JOB=build
AZURE_EXTENSION_DIR=/opt/az/azcliextensions
...

Your problem here is that you used the wrong syntax.
Neither ${{ $GITHUB_REF_NAME }} nor ${{ env.GITHUB_REF_NAME }} will work, but just $GITHUB_REF_NAME will.
Therefore, your command line should be:
run: mv ./Code/.pio/build/attiny841/firmware.hex ./Code/.pio/build/attiny841/megadesk-$GITHUB_REF_NAME.hex
If you want to take a look, here is a demo:
Workflow file: https://github.com/GuillaumeFalourd/poc-github-actions/blob/main/.github/workflows/49-rename-on-release.yml
Workflow run: https://github.com/GuillaumeFalourd/poc-github-actions/runs/5359686796?check_suite_focus=true

Related

Reference a variable in `uses` when pointing to a path to a container

I have a workflow yml file. At the top I have a section above where the jobs are defined to make them global across jobs:
env:
DBT_REPO: ${{ vars.DBT_REPO }}
This var is a repo variable and I have confirmed it is already set. Pretend it's value is fruits/apples.
Then, in one of my jobs I try to reference this var in a step:
- name: Checkout DBT repo
uses: actions/checkout#v2
with:
repository: ${{ env.DBT_REPO }}
token: ${{ secrets.WORKFLOW_TOKEN }}
ref: ${{ env.DBT_REPO_BRANCH }}
path: ./${{ env.DBT_REPO }}
- name: Run DBT
uses: ./${{ env.DBT_REPO }}/dbt-action
The last line is line 169.
Then, when I try to run this workflow I get an error:
Invalid workflow file: .github/workflows/main.yml#L169
The workflow is not valid. .github/workflows/main.yml (Line: 169, Col: 15): Unrecognized named-value: 'DBT_REPO'. Located at position 1 within expression: DBT_REPO
If I hard code it like so: uses: ./fruits/apples/dbt-action then things work fine. It's only when I attempt to use a variable.
How can I reference a variable in my uses keyword?
This is not possible because the env context is not available to uses. In fact, based on documentation no contexts are available to the uses key.
See: https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability
I believe this is an architectural limitation of GitHub Actions, it appears they want to resolve all workflows/actions at the start of all jobs and thus dynamic resolution isn't possible.

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

Is it possible to specify image used in steps according to the matrix strategy?

I'm going to setup a workflow on GitHub which uses some docker images to check my package on different platform. I'd like to use the matrix strategy. Then I wrote a workflow like this:
name: Main Workflow
on: [push]
jobs:
test_linux:
runs-on: ubuntu-latest
strategy:
matrix:
image: [ubuntu, fedora]
steps:
- name: Checkout
uses: actions/checkout#v3
- name: Test
uses: docker://${{ matrix.image }}:latest
with:
entrypoint: /bin/bash
args: ./test.sh
This is just a demo workflow. The real one is much more complicated.
However, after I pushed it, GitHub gave me the following error message:
Invalid workflow file: .github/workflows/main.yml#L16
The workflow is not valid. .github/workflows/main.yml (Line: 13, Col: 15): Unrecognized named-value: 'matrix'. Located at position 1 within expression: matrix.image
Actually, I got this error instantly when I pushed codes.
Why? Is the matrix context inaccessible when parsing workflow file? Are there some ways to resolve it?
I tried to export the full docker name to environment in the previous step before "Test", but context env is also inaccessible just like the context matrix. I got nearly the same error. The only different is:
Unrecognized named-value: 'env'...
Now I have to call docker run manually in run scripts like
steps:
- name: Test
run: docker run --rm -v $(pwd):/code --workdir=/code ${{ matrix.image }}:latest /bin/bash -c "/code/test.sh"
It did work but I still prefer to use the uses entry.

Reference the runner context in job's env clause

Here's a GitHub Actions workflow file for a Python project named spam:
name: PyInstaller
on:
[...]
jobs:
create_release:
[...]
make_artifact:
needs: create_release
strategy:
matrix:
os: [ ubuntu-latest, windows-latest ]
runs-on: ${{ matrix.os }}
env:
ARTIFACT_PATH: dist/spam.zip
ARTIFACT_NAME: spam-${{ runner.os }}.zip
steps:
[...]
When this runs, the workflow fails at startup with this:
The workflow is not valid. [...]:
Unrecognized named-value: 'runner'. Located at position 1 within expression: runner.os
I'm attempting to use the os attribute of the runner context. This SO Q&A mentions that the env context can only be used in specific places, so I suspect something similar is happening here. However, I can't find any official documentation addressing this.
Is there any way to reference the runner context to set an environment variable within the env clause of a job, as shown above?
I'm looking for a way to set the environment variable for all steps in the job, so an env inside a step item won't do.
The workaround I've got for now is to add a step specifically to set environment variables:
steps:
- name: Setup environment
run: |
echo "ARTIFACT_NAME=spam-${{ runner.os }}.zip" >> $GITHUB_ENV
however this only works on the Linux runner.
If you scroll down a bit further in the GitHub Actions docs you linked, there's an example workflow printing different contexts to the log.
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJson(runner) }}
I set up a test repo with a workflow demonstration:
on: push
jobs:
one:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os:
- 'ubuntu-latest'
- 'windows-latest'
- 'macos-latest'
steps:
- name: Dump runner context
env:
RUNNER_CONTEXT: ${{ toJson(runner) }}
run: echo "$RUNNER_CONTEXT"
- name: Get runner OS
env:
RUNNER_OS: ${{ runner.os }}
run: echo "$RUNNER_OS"
- name: Create file with runner OS in name
env:
OS_FILENAME: 'spam-${{ runner.os }}.zip'
run: |
echo "OS_FILENAME=spam-${{ runner.os }}.zip" >> $GITHUB_ENV
touch "./${{ env.OS_FILENAME }}"
touch blah.txt
- name: List created file
run: ls -l "./${{ env.OS_FILENAME }}"
It looks like you can also set and access env in steps, and those persist across workflow steps. For example, I set the environment variable $OS_FILENAME in step 3 using the echo syntax, and reference it in step 4. This works across all the OS options offered on GitHub Actions.
Note that the GitHub Actions docs state that "Environment variables must be explicitly referenced using the env context in expression syntax or through use of the $GITHUB_ENV file directly; environment variables are not implicitly available in shell commands.". Basically, it means you can't implicitly refer to env variables like $FOO and instead must refer to them as ${{ env.FOO }} in shell commands.
So for your scenario, does it satisfy your requirements if you set $ARTIFACT_NAME in the first step of the job? I wonder if the reason might be that the runner context isn't created until the first step - I'm not sure I have a way of testing this.

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