I have the following GitHub action yml file that comments on the PR with stdout. However, I have noticed when using a bash script bash.sh, the comment is empty. Inside bash.sh it runs a series of commands that generates output. Is there any way to get the output from bash.sh?
- name: "Run bash"
id: plan
run: ./bash.sh
- name: "Comment PR"
uses: actions/github-script#0.9.0
env:
STDOUT: "```${{ steps.plan.outputs.stdout }}```"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
github.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.STDOUT
})
Related
I am trying to list all the changed files on file push. However my List all changed files command does not return anything even though I change the file and commit
name: test on: push:
branches: [ main ]
jobs: build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
with:
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
- name: Get changed files using defaults
id: changed-files
uses: actions/checkout#v2
- name: List all added files
run: |
for file in ${{ steps.changed-files.outputs.added_files }}; do
echo "$file was added"
done
- name: List all changed files
run: |
for file in ${{ steps.changed-files.outputs.modified_files }}; do
echo "$file was modified"
done
Try using the one available in marketplace https://github.com/jitterbit/get-changed-files#get-all-changed-files
In my GitHub workflow, I have a finish job that uploads the coverage report to Coveralls once all other jobs are finished.
jobs:
foo: ...
bar: ...
finish:
needs:
- foo
- bar
If either foo or bar fails though, or it is skipped (why a job may be skipped is not relevant to this question), the finish job won't be run.
Is there a way I could make finish run if at least one of the jobs provided in the needs field is run successfully?
It's currently not possible to get job.status or job.conclusion natively on the workflow to check them on other jobs through conditional.
A workaround could be to use outputs or artifacts to always save each job status.
Here is an example using artifacts with 3 jobs, where the third job would check the previous 2 jobs status before executing some operation:
jobs:
JOB_01:
name: Job 01
. . .
steps:
- name: Some steps of job 01
. . .
- name: Create file status_job01.txt and write the job status into it
if: always()
run: |
echo ${{ job.status }} > status_job01.txt
- name: Upload file status_job01.txt as an artifact
if: always()
uses: actions/upload-artifact#v1
with:
name: pass_status_job01
path: status_job01.txt
JOB_02:
name: Job 02
. . .
steps:
- name: Some steps of job 02
. . .
- name: Create file status_job02.txt and write the job status into it
if: always()
run: |
echo ${{ job.status }} > status_job02.txt
- name: Upload file status_job02.txt as an artifact
if: always()
uses: actions/upload-artifact#v1
with:
name: pass_status_job02
path: status_job02.txt
JOB_03:
needs: [JOB_01, JOB_02]
if: always()
name: Job 03
. . .
steps:
- name: Download artifact pass_status_job01
uses: actions/download-artifact#v1
with:
name: pass_status_job01
- name: Download artifact pass_status_job02
uses: actions/download-artifact#v1
with:
name: pass_status_job02
- name: Set the statuses of Job 01 and Job 02 as output parameters
id: set_outputs
run: |
echo "::set-output name=status_job01::$(<pass_status_job01/status_job01.txt)"
echo "::set-output name=status_job02::$(<pass_status_job02/status_job02.txt)"
- name: Show the values of the outputs
run: |
# using the syntax steps.<step_id>.outputs.<output_name> to access the output parameters
echo "status_job01 = ${{ steps.set_outputs.outputs.status_job01 }}"
echo "status_job02 = ${{ steps.set_outputs.outputs.status_job02 }}"
- name: Some other steps of job 03
. . .
Where the other steps of job03 would depend on the outputs results you got from the other jobs, to perform an action or not.
You can find more references about this example on the links below:
Get status of multiple jobs in the same workflow
How to get status of previous job
I also wrote an example here:
workflow file
workflow run
I have a cross-platform project which is to be built on 2 platforms: mac and linux(ubuntu).
My pipeline contains 3 jobs:
prepare docker image with all nessesary too to build the project.
build on ubuntu in prepared docker container, depends on step 1
build on MacOS, needs nothing
Steps for linux and macos are definitely the same. But matrixes differs much, and linux build is
run inside container.
Is there a way to share steps between two different jobs?
I tried YAML anchors but GitHub does not support them.
Full workflow
on:
push:
branches: [ main, support/1.2.x ]
pull_request:
branches: [ main, support/1.2.x ]
jobs:
Docker-iroha-builder:
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout#v2
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action#v1
-
name: Cache Docker layers
uses: actions/cache#v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
name: Login to DockerHub
uses: docker/login-action#v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action#v2
with:
file: docker/develop/Dockerfile.builder
# context: .
push: true
tags: ${{ secrets.DOCKERHUB_ORG }}/iroha:builder
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
-
# Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
build-iroha-ubuntu:
needs: Docker-iroha-builder
runs-on: ubuntu-latest
container: ikyb/iroha:builder
strategy:
fail-fast: false
matrix:
cc: [ gcc-9, gcc-10, clang ] ##todo g++-10
USE_BURROW: [ -DUSE_BURROW=OFF ]
debrel: [ Debug ] #,Release, RelWithDebInfo
steps:
- ## Takes 22 seconds with default github runner
name: Homebrew
run: brew install cmake ninja coreutils
if: ${{ runner.os == 'MacOS' }}
-
name: Checkout
uses: actions/checkout#v2
-
name: Cache vcpkg
uses: actions/cache#v2
with:
path: |
build-vcpkg
build/vcpkg_installed
$HOME/.cache/vcpkg
key: ${{ runner.os }}-vcpkg-${{ github.sha }}
restore-keys: ${{ runner.os }}-vcpkg-
-
name: Build Iroha vcpkg dependancies
run: ./vcpkg/build_iroha_deps.sh $PWD/build-vcpkg
-
name: CMake configure
run: |
export CC=${{ matrix.cc }} CXX=$(echo ${{ matrix.cc }} | sed -es,gcc,g++, -es,clang,clang++,)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$PWD/build-vcpkg/scripts/buildsystems/vcpkg.cmake \
${{ matrix.USE_BURROW }} -GNinja #-DCMAKE_VERBOSE_MAKEFILE=ON
-
name: CMake build
run: cmake --build build --config ${{ matrix.debrel }}
build-iroha-macos:
runs-on: macos-latest
strategy:
fail-fast: false
matrix:
USE_BURROW: [ -DUSE_BURROW=OFF ]
debrel: [ Debug,Release ]
steps:
- ## Takes 22 seconds with default github runner
name: Homebrew
run: brew install cmake ninja coreutils
if: ${{ runner.os == 'MacOS' }}
-
name: Checkout
uses: actions/checkout#v2
-
name: Cache vcpkg
uses: actions/cache#v2
with:
path: |
build-vcpkg
build/vcpkg_installed
$HOME/.cache/vcpkg
key: ${{ runner.os }}-vcpkg-${{ github.sha }}
restore-keys: ${{ runner.os }}-vcpkg-
-
name: Build Iroha vcpkg dependancies
run: ./vcpkg/build_iroha_deps.sh $PWD/build-vcpkg
-
name: CMake configure
run: |
export CC=${{ matrix.cc }} CXX=$(echo ${{ matrix.cc }} | sed -es,gcc,g++, -es,clang,clang++,)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$PWD/build-vcpkg/scripts/buildsystems/vcpkg.cmake \
${{ matrix.USE_BURROW }} -GNinja #-DCMAKE_VERBOSE_MAKEFILE=ON
-
name: CMake build
run: cmake --build build --config ${{ matrix.debrel }}
TL;DR
I solved my problem with shell tool yq
yq eval 'explode(.)' file.yml
The repository with example usage and detailed description https://github.com/kuvaldini/make-workflows.sh may be helpful to easy start. It was make from this answer. Pay attention to Actions tab.
Long answer
GitHub Workflow description in YAML does not support anchors.
There are several workarounds => anyway they come to building-editing workflow yaml from source.
So I suggest yet another one make-workflows.sh based on YAML tool yq.
USAGE
Move your workflows to .github/*.src.yml
Put make-workflows.sh to directory .github/
(optional) Copy or link pre-commit.sh to .git/hooks/pre-commit
Like ln -s ../../.github/pre-commit.sh .git/hooks/pre-commit
File make-workflows.sh
#!/usr/bin/env bash
set -euo pipefail
## The script expands '*.src.yml' from $1(default: script's directory)
## to $2 (default:subdirectory 'workflows') with corresponding name '*.yml'
## Main goal is to dereference YAML anchors.
## Deals only with Git cached/indexed files
## Set -x to debug
script_dir=$(dirname $(realpath "$0"))
dir_from=${1:-${script_dir}}
dir_to=${2:-workflows}
cd $dir_from
edited=
for f in $(git status -s -- \*.src.yml | sed 's,^.. ,,') ;do
readonly out=$(echo $f | sed s,.src.yml\$,.yml,)
readonly wout=$dir_to/$out
readonly tempout=$(mktemp)
trap "rm -f $tempout" EXIT
echo >>$tempout "## DO NOT EDIT"
echo >>$tempout "## Generated from $f with $(basename $0)"
echo >>$tempout ""
yq eval 'explode(.)' $f >>$tempout
if ! diff -q $wout $tempout &>/dev/null ;then
mv $tempout $wout
edited+="'$out' "
fi
done
if [[ -n "$edited" ]]
then echo >&2 "make-workflows: these files were edited: $edited"
else echo >&2 "make-workflows: everything is up to date"
fi
File pre-commit.sh
#!/usr/bin/env bash
set -euo pipefail
gitroot=$(git rev-parse --show-toplevel)
cd $gitroot
./.github/make-workflows.sh
git add .github/workflows
Links
ready to use solution with detailed description https://github.com/kuvaldini/make-workflows.sh
Share same steps for different GitHub Actions jobs
https://github.community/t/support-for-yaml-anchors/16128/60
https://github.com/mithro/actions-includes
https://github.com/allejo/gha-workflows
While github actions does not support YAML anchors directly, one can expand those e.g. by converting from YAML to JSON and then back to YAML. I am doing this here (Makefile in .github/workflows): https://github.com/agda/agda/blob/557681d04aae2100ccde2e045a8afcf30528c3a5/.github/workflows/Makefile
srcpath=../../src/github/workflows
sources=$(wildcard $(srcpath)/*.yml $(srcpath)/*.yaml)
targets=$(sort $(notdir $(sources)))
all : $(targets)
# Normalize YAML files by going via JSON.
# This expands anchors which are not understood by github workflows.
% : $(srcpath)/%
yaml2json $< | json2yaml - > $#
An example for a workflow file with anchors is here: https://github.com/agda/agda/blob/557681d04aae2100ccde2e045a8afcf30528c3a5/src/github/workflows/test.yml
jobs:
build:
runs-on: &runs_on ubuntu-22.04
steps:
- &checkout
uses: actions/checkout#v3
- &haskell_setup
uses: haskell/actions/setup#v2
with:
ghc-version: ${{ env.GHC_VER }}
...
test:
needs: build
runs-on: *runs_on
steps:
- *checkout
- *haskell_setup
...
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 have a workflow where after a push to master I want to create a release and upload an asset to it.
I'm using actions/create-release#v1 and actions/upload-release-asset#v1.
I would like to pass the outputs of a bash commands to the action parameters. However I found out the syntax of "$(command)" does not work.
How can I pass the output of a bash command to an action's parameter.
For example I'd like to do something like this:
- name: Create Release
id: create_release
uses: actions/create-release#v1
env:
GITHUB_TOKEN: ${{ secrets.token }}
with:
tag_name: $(cat projectFile | grep -Po '(?<=Version>).*(?=</Version>)')
Update: set-output is being deprecated as well "Starting 1st June 2023 workflows using save-state or set-output commands via stdout will fail with an error."
Now that set-env is deprecated and set-output is soon to be deprecated, you can use GITHUB_OUTPUT environment files: to accomplish the same thing in this answer
- name: Retrieve version
run: |
echo "TAG_NAME=$(cat projectFile | grep -Po '(?<=Version>).*(?=</Version>)')" >> $GITHUB_OUTPUT
id: version
- name: Create Release
id: create_release
uses: actions/create-release#v1
env:
GITHUB_TOKEN: ${{ secrets.token }}
with:
tag_name: ${{ steps.version.outputs.TAG_NAME }}
References:
https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#environment-files
How to save the output of a bash command to output parameter in github actions
Use environment files
steps:
- name: Set the value
id: step_one
run: |
echo "FOO=$(git status)" >> $GITHUB_ENV
- name: Use the value
id: step_two
run: |
echo "${{ env.FOO }}"
UPDATE: This answer will not work as GitHub as disabled this syntax for security reasons. You should use environment files instead.
I would create an environment variable based of your command output:
- name: Retrieve version
run: |
echo ::set-env name=TAG_NAME::$(cat projectFile | grep -Po '(?<=Version>).*(?=</Version>)')
And then access it like the following:
- name: Create Release
id: create_release
uses: actions/create-release#v1
env:
GITHUB_TOKEN: ${{ secrets.token }}
with:
tag_name: ${{ env.TAG_NAME }}