I am unable to generate a summary for github actions on windows. The following script encapsulates the script.
Using the following script:
name: Testing windows summaries
on:
pull_request:
branches: [master]
types: [synchronize, opened, reopened, ready_for_review]
jobs:
build-and-test:
name: Test
runs-on: "windows-latest"
steps:
- name: Adding markdown
run: |
echo '### Hello world! ' >> $GITHUB_STEP_SUMMARY
cat $GITHUB_STEP_SUMMARY
Produces the following error:
Get-Content: D:\a\_temp\e90ee597-2b32-4d33-ba5c-0ae6be835be0.ps1:7
Line |
7 | cat $GITHUB_STEP_SUMMARY
| ~~~~~~~~~~~~~~~~~~~~
| Cannot bind argument to parameter 'Path' because it is null.
Error: Process completed with exit code 1.
So the problem seems that the variable $GITHUB_STEP_SUMMARY never gets a value.
After looking for some time I found the solution to the problem. On windows the default shell does not seem to work well with the >> operator. The solution is to change the script above for:
name: Testing windows summaries
on:
pull_request:
branches: [master]
types: [synchronize, opened, reopened, ready_for_review]
jobs:
build-and-test:
name: Test
runs-on: "windows-latest"
steps:
- name: Adding markdown
run: |
echo '### Hello world! ' >> $GITHUB_STEP_SUMMARY
cat $GITHUB_STEP_SUMMARY
shell: bash
Where we have added a explicit shell instruction at the end.
Related
I have scoured the forums and couldn't find a solution.
I have a config.yml file which contains a set of key/value pairs. One of those pairs I want to set as a GITHUB_ENV to be used in my workflow. But I am running into issues as the logs say
"reusable workflows should be referenced at the top-level
`jobs.*.uses' key, not within steps"
How do I get around this?
name: "Deploy The Kraken"
on:
push:
branches:
- dev
pull_request:
branches:
- dev
workflow_dispatch:
jobs:
call-build:
steps:
- name: Set env
run: |
echo "FEATURE_BRANCH=$(cat config.yml | awk -F: '/^branch:/ { print $2 }'
| sed 's/ //g')" >> $GITHUB_ENV
- name: Test
run: echo $FEATURE_BRANCH
- uses: ######/#####/.github/workflows/kraken.yml#$FEATURE_BRANCH
with:
environment: #####
workspace: #####
contract: #####
production-ref: #####
I have tried multiple variations of placing the shell command in different parts. But I still can't get it to point to my chosen branch.
Given a repository structure with two packages like this:
$ tree
.
└── packages
├── foo
└── bar
$ cat pnpm-workspace.yaml
packages:
- 'packages/**'
$ pnpm -s m ls --depth -1
monorepo /monorepo
#mono/foo#0.0.0 /monorepo/packages/foo
#mono/baz#0.0.0 /monorepo/packages/bar
I'd like to run GitHub Actions CI such that it automatically runs each project as separate job. Here I've set up a job that manually does that parallelization:
name: CI
on:
push:
jobs:
build:
strategy:
matrix:
package: ["#mono/foo", "#mono/bar" ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: pnpm/action-setup#v2
with:
version: 6.9.1
- run: pnpm run --filter ${{ matrix.package }} test
That runs fast because each project is run as parallel jobs, but I don't want to manually maintain that matrix.package list. How can I utilize pnpm to provide a list of workspace projects that gets fed into GitHub Actions CI?
Hmmm... I hit my head on this a bit more and I've found a solution.
I first made a package.json script to turn pnpm output into a json array-fragment:
$ cat package.json
{
"scripts": {
"list-packages": "echo [$(pnpm -s m ls --depth -1 | tr \" \" \"\n\" | grep -o \"#.*#\" | rev | cut -c 2- | rev | sed -e 's/\\(.*\\)/\"\\1\"/' | paste -sd, - )]",
}
}
$ pnpm -s list-packages
["#mono/foo","#mono/bar"]
(I'm not good enough with shell to know if there's a much easier way to express this transformation so I'd be happy to learn!)
I then followed GitHub documentation on dynamically setting matrix variables and created this workflow:
name: CI
on:
push:
workflow_dispatch:
jobs:
packages:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout#v2
- uses: pnpm/action-setup#v2
with:
version: 6.9.1
- run: $(echo pnpm -s list-packages2)
- id: set-matrix
run: echo "::set-output name=matrix::{\"packages\":$(pnpm -s list-packages)}"
build:
needs: packages
strategy:
matrix: ${{ fromJson(needs.packages.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- run: echo ${{ matrix.package }}
The packages job now takes the output of $(pnpm -s list-packages) and puts it into the matrix variable, and that makes GitHub Actions run them all in parallel:
Using GitHub Actions, I would like to invoke a shell script with a list of directories.
(Essentially equivalent to passing an Ansible vars list to the shell script)
I don't really know how, is this even possible? Here's what I have until now, how could one improve this?
name: CI
on:
push:
branches:
- master
tags:
- v*
pull_request:
jobs:
run-script:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout#v2
- name: Run script on targets
run: ./.github/workflows/script.sh {{ targets }}
env:
targets:
- FolderA/SubfolderA/
- FolderB/SubfolderB/
Today I was able to do this with the following YAML (truncated):
...
with:
targets: |
FolderA/SubfolderA
FolderB/SubfolderB
The actual GitHub Action passes this as an argument like the following:
runs:
using: docker
image: Dockerfile
args:
- "${{ inputs.targets }}"
What this does is simply sends the parameters as a string with the newline characters embedded, which can then be iterated over similar to an array in a POSIX-compliant manner via the following shell code:
#!/bin/sh -l
targets="${1}"
for target in $targets
do
echo "Proof that this code works: $target"
done
Which should be capable of accomplishing your desired task, if I understand the question correctly. You can always run something like sh ./script.sh $target in the loop if your use case requires it.
I'm not able to access environment variables defined at the top-level of a GitHub Action configuration file from within a script run by the action.
For example, given the following config file:
name: x-pull-request
on: pull_request
env:
FOO: bar
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- name: does a thing
run: ./scripts/do-a-thing.sh
... and the following script:
X=${FOO:default}
echo "X: $X" # X: default
The FOO environment variable defined in the config file is not available to the script and the default value is being used.
So, how can I access the environment variable from a Bash script run by the build step? Am I missing a prefix or something? (I know values defined in the input hash require you to use an INPUT_ prefix when referencing them.)
You can use env at any level also in jobs and steps.
I wrote a test action and a test script to validate it:
The action file:
name: Env tests
on: push
env:
FOO_ROOT: bar on root
jobs:
test:
runs-on: ubuntu-latest
env:
FOO_JOB: bar on job
steps:
- uses: actions/checkout#v1
- name: Test envs
run: ./env-test.sh
env:
FOO_STEP: bar on step
The script file:
#!/usr/bin/env bash
echo "FOO_ROOT: $FOO_ROOT"
echo "FOO_JOB: $FOO_JOB"
echo "FOO_STEP: $FOO_STEP"
echo " "
printenv
The results:
FOO_ROOT: bar on root
FOO_JOB: bar on job
FOO_STEP: bar on step
LEIN_HOME=/usr/local/lib/lein
M2_HOME=/usr/share/apache-maven-3.6.3
...
Check my results and, in fact, I don't know why it didn't work on your side because it must work.
If some one else is searching for a solution you have to explicitly pass the environment variables to the bash script. Otherwise they are not available:
name: x-pull-request
on: pull_request
env:
FOO: bar
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v1
- name: does a thing
run: ./scripts/do-a-thing.sh $FOO
and in the script you have to map the parameter to a variable.
X=$1
echo "X: $X" # X: default
In a circleci config.yml file I have a number of jobs defined similarly this way:
defaults: &defaults
working_directory: ~/repo/appengine
docker:
- image: circleci/python
version: 2
jobs:
deploy_uat:
<<: *defaults
steps:
- attach_workspace:
at: ~/repo
- checkout
- run: *setup_secret
- run: *enable_npm
- run: *appengine_dep
- run: *webview_dep
- run: *apps_dep
- run:
name: Setup key file
command: |
mkdir ~/gcloud_keys
echo ${GCLOUD_UAT_ENV_KEY} | base64 --decode --ignore-garbage > ${HOME}/gcloud_keys/uat-env.json
- run: deployt.sh uat
deploy_dev:
# ... Skipped for brevity
deploy_staging:
# ...
I would like to further simplify the yaml code to something like this
defaults: &defaults
working_directory: ~/repo/appengine
docker:
- image: circleci/python
# Common steps
deploy_steps: &deploy_steps
steps:
- attach_workspace:
at: ~/repo
- checkout
- run: *setup_secret
- run: *enable_npm
- run: *appengine_dep
- run: *webview_dep
- run: *apps_dep
version: 2
jobs:
deploy_uat:
<<: *defaults
steps:
*deploy_steps
- run:
name: Setup key file
command: |
mkdir ~/gcloud_keys
echo ${GCLOUD_UAT_ENV_KEY} | base64 --decode --ignore-garbage > ${HOME}/gcloud_keys/uat-env.json
- run: deployt.sh uat
deploy_dev:
<<: *defaults
steps:
*deploy_steps
- run:
name: Setup key file
command: |
mkdir ~/gcloud_keys
echo ${GCLOUD_DEV_ENV_KEY} | base64 --decode --ignore-garbage > ${HOME}/gcloud_keys/dev-env.json
- run: deployt.sh dev
deploy_staging:
<<: *defaults
steps:
*deploy_steps
- run:
name: Setup key file
command: |
mkdir ~/gcloud_keys
echo ${GCLOUD_STAGING_ENV_KEY} | base64 --decode --ignore-garbage > ${HOME}/gcloud_keys/staging-env.json
- run: deployt.sh staging
However if I do it this way, I got did not find expected key error at the line *deploy_steps
If I change it to
deploy_uat:
<<: *defaults
steps:
<<: *deploy_steps
# ...
I got the same error
What is the right way to write simpler yaml config?
Well, the value of steps is expected to be an array. In the first case, there is an alias which points to a mapping (containing a steps key), followed by two sequence items. This is not a valid YAML structure and won't even get past the parser.
In the second case, you are using the (deprecated) merge key. That is only defined for mappings, there is no equivalent for sequences.
What you want to do is to merge two sequences inside YAML. There is no way to do that as YAML is not a programming language and does not support transformations on input data (apart from the merge key, which current YAML devs agree was a bad idea from the start).
Since YAML does not allow you to do what you want, you can turn to templating languages like Jinja, which is what Ansible and SaltStack do to enable doing such things in their YAML configs. Since CircleCI does not support it, you'd need to write yourself a script to transform your input YAML into the version CircleCI understands. It's up to you whether this is a feasible solution to your problem.