I'm trying to keep multiple github actions in the same monorepo using subdirectories, and run them like:
workflow.yml
// [...]
jobs:
run_my_script:
runs-on: ubuntu-latest
steps:
- name: Check out current repo
uses: actions/checkout#v2
- uses: ./my_action2
with:
my_input_var: "david"
./my_action2/action.yml
// [...]
runs:
using: "composite"
steps:
# Checkout files in this repo
- name: Checkout
uses: actions/checkout#v1
- name: Run myscript
run: python myscript.py "${{ inputs.my_input_var }}" # location: ./my_action2/myscript.py
shell: bash
The problem I'm having is that my action uses a python script in it's subdirectory, but the uses: action appears to run from the GITHUB_WORKING_DIR of the workflow and not the directory of the action itself.
python: can't open file 'myscript.py': [Errno 2] No such file or directory
I've looked through most of the working-directory questions surrounding github actions, but I'm still stumped.
I've also tried adding working-directory: ./my_action2 to the job's defaults: but it looks like it's not propagating to run: commands within the uses: step.
My workaround in the meantime has been to add an input for myaction2_working_directory in the workflow, and then add working-directory: ${{ inputs.myaction2_working_directory }} to every run: command in the action. This seems inelegant and repetitive. Is there a better way to do this?
contrary to the answer by Grzegorz, you cannot just run: cd foo and then expect all following steps to have a working directory of foo. as far as i can tell, the only way to do this is with the "workaround" the OP already posted -- add an input named e.g. working-directory to your action and then add working-directory: ${{ inputs.working-directory }} to every step. see https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runsstepsworking-directory
I had similar problem and for my composite actions I just added a first step as:
run: cd ${{ inputs.working_directory }}
and then all next steps are running in it.
I couldn't find a better way and having working-directory copy pasted was also something I didn't like.
Related
I currently have a GitHub Action that triggers on:
pull_request_review:
types: [submitted]
I then want to run a command, which expects the contents of changes of the Pull Request.
Previously, I was using
on:
push
and I had no issues with the contents of the files being available in the Action context.
However, my command is failing now, and I think it's because the context only includes the commit that the action was triggered on (no file changes.)
Previously I was running this action on push and that was always successful, with the file changes being available in the context.
I'm using:
steps:
- uses: actions/checkout#v2
(https://github.com/actions/checkout)
Is it possible to use this to have all the file changes on the Pull Request within the Action context?
Any help on this would be appreciated!
You can do that by using an open source Action available on marketplace:
jobs:
build:
runs-on: ubuntu-latest # windows-latest | macos-latest
name: Test changed-files
steps:
- uses: actions/checkout#v2
with:
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files#v14.6
- name: List all changed files
run: |
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
echo "$file was changed"
done
The solution above uses git checkout and git diff to get files changed by PR. Alternatively if you really need just information about paths changed and you don't really need files themselves (no checkout) - you can do it without checkout using gh CLI:
gh pr view XXX --json files -q '.files[].path'
You can run it like this:
jobs:
comment:
runs-on: ubuntu-latest
steps:
- run: gh pr view XXX --json files -q '.files[].path'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
I would like to use a pure solution in a GitHub action to increment a version of the package. I don't want to use any existing actions from the GitHub marketplace such as "gh-action-bump-version
". I have this workflow, which will increase the version and create a tag.
name: Version Increment
on:
push:
branches:
- main
tags-ignore:
- v*
jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
with:
token: ${{ secrets.ACCESS_TOKEN }}
- run: git config user.email "$GITHUB_ACTOR#users.noreply.github.com"
- run: git config user.name "$GITHUB_ACTOR"
- run: npm version minor -m "v%s"
- run: VERSION=$(node -p "require('./package.json').version")
- run: git tag ${VERSION}
- run: git push origin --tags
- run: git push origin --follow-tags
It works, but it also cause a circular runs of the actions because of the last row. I know that I can use a custom message like "[RELEASE]" and put there a "if" condition and skip these commits. But my question is, is there any better solution to skip these commits from this action and do not use the "if" condition? Because the "tags-ignore" obviously doesn't work.
So I found several solutions. The first is that you can put "[skip actions]" to your commit message and that commit will skip any github action that should run within the commit. The second one is to use an address of the repository with access token.
This works pretty well for me:
name: Version Increment
on:
push:
branches:
- main
jobs:
version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- run: git config user.email "$GITHUB_ACTOR#users.noreply.github.com"
- run: git config user.name "$GITHUB_ACTOR"
- run: npm version minor -m "v%s"
- run: VERSION=$(node -p "require('./package.json').version")
- run: git tag ${VERSION}
- run: git push "https://$GITHUB_ACTOR:${{ secrets.ACCESS_TOKEN }}#github.com/$GITHUB_REPOSITORY.git" --follow-tags
- run: git push "https://$GITHUB_ACTOR:${{ secrets.ACCESS_TOKEN }}#github.com/$GITHUB_REPOSITORY.git" --tags
Try using the built in GITHUB_TOKEN instead of your custom ACCESS_TOKEN. That should prevent the workflow from triggering another workflow.
From the docs (https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow):
When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.
Just wondering if there is a way to use a Github action across multiple repos. Basically seeing if there is a similar way to do something similar to this from azure devops.
I have the same script i need to run on multiple repos, which currently I have created a template of so I can quickly create it across repos, however if I need to modify that template I will need to change it in all the repos which would be fairly time consuming.
My thinking is that i can create a plugin similar to the ones you can get on the marketplace and create a step to use that, but is this the best way of doing it/is there a way to do this privately.
Thanks
EDIT:
With some looking i have got a action that looks like the following (ignore the names etc that are still in from a sample)
name: "Hello World"
description: "Greet someone"
inputs:
unity-key:
default: ""
description: "Unity Key"
required: true
runs:
using: composite
steps:
- uses: game-ci/unity-builder#v2
env:
UNITY_LICENSE: "${{ inputs.unity-key }}"
with:
buildMethod: UnityEditor.SyncVS.SyncSolution
targetPlatform: StandaloneWindows
- uses: nikeee/docfx-action#v1.0.0
name: Build
with:
args: Documentation/docfx.json
- uses: actions/upload-artifact#v2
name: "Upload site artifact"
with:
name: _site
path: _site
and then calling it in another repos step process as following snippet. It does find the action and attempts to run it. But then errors out. Looking around i can not see any references that say i can have uses steps within another action, but this seems like a very limited feature, so not sure if im just missing something.
jobs:
# This workflow contains a single job called "build"
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout#v2
# with:
# submodules: true
- uses: Greener-Games/Generate-Documentation#v1.0.5
with:
unity-key: ${{ secrets.UNITY_LICENCE_2019_4_12F1 }}
I recently hooked up my project with github actions for continuous integration. I created two separate jobs: the first one checks if the code in the pull request is accepted by our linter, and the second one checks if the code passes the test suite. I like that having two jobs like this shows up as two separate checkmarks in the Github webpage for the pull request:
The problem I'm having now is that there is some duplicated code in workflow YAML file: the first 3 steps, which install Lua and Luarocks. Not only is it annoying to maintain, but it also wastes CI minutes by running the same actions twice. Is there a way to avoid this? So that the setup code is only written in one place, and only runs once when the workflow executes?
But I am confused what would be the proper way to proceed:
Should I create my own Github Action with the shared setup code?
Should I create a Docker image that already has Lua and Luarocks pre-installed?
Should I use a single job? Can I still have independent checkmarks for the linter and the test suite if they are steps of the same job?
Something else?
Here is the current YAML file for my workflow:
name: Github Actions CI
on: [ pull_request ]
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: leafo/gh-actions-lua#v8.0.0
- uses: leafo/gh-actions-luarocks#v4.0.0
- run: luarocks install luacheck
- run: ./run-linter.sh
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: leafo/gh-actions-lua#v8.0.0
- uses: leafo/gh-actions-luarocks#v4.0.0
- run: luarocks install busted
- run: ./build-project.sh
- run: ./run-test-suite.sh
I tried searching for similar questions but couldn't find anything that exactly answered my question:
Caching APT packages in GitHub Actions workflow: I can't use this solution because I don't have a way to precisely specify all the versions of all the dependencies that I am using, so that they may be cached. I also don't mind if separate runs of the workflow are not cached. I'm more worried about the code duplication.
Github actions share workspace/artifacts between jobs? I don't want to have to manage uploading uploading artifacts to a separate service and then deleting them afterwards.
Reuse portion of github action across jobs: In that question the only difference between the jobs is a single variable, so accepted answer is to use a build matrix. But I don't think a build matrix would work as well in my case, where only the setup code is the same?
As of today (August 2021) composite action is no longer limited to run. GitHub Actions: Reduce duplication with action composition
name: "Publish to Docker"
description: "Pushes built artifacts to Docker"
inputs:
registry_username:
description: “Username for image registry”
required: true
registry_password:
description: “Password for image registry”
required: true
runs:
using: "composite"
steps:
- uses: docker/setup-buildx-action#v1
- uses: docker/login-action#v1
with:
username: ${{inputs.registry_username}}
password: ${{inputs.registry_password}}
- uses: docker/build-push-action#v2
with:
context: .
push: true
tags: user/app:latest
Old Answer
What you are looking for is composite action which help you reuse once defined set of steps.
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: octocat/say-hello#v1
- run: luarocks install luacheck
- run: ./run-linter.sh
test:
name: Test
runs-on: ubuntu-latest
steps:
- uses: octocat/say-hello#v1
- run: luarocks install busted
- run: ./build-project.sh
- run: ./run-test-suite.sh
octocat/say-hello/action.yml:
runs:
using: "composite"
steps:
- run: echo "Nice to meet you!"
shell: pwsh
For more details you can also check's ADR here.
And why you can't simply run it once for all jobs, because each job may run on a different machine.
A job is a set of steps that execute on the same runner. By default, a workflow with multiple jobs will run those jobs in parallel. You can also configure a workflow to run jobs sequentially. For example, a workflow can have two sequential jobs that build and test code, where the test job is dependent on the status of the build job. If the build job fails, the test job will not run.
There are 3 main approaches for code reusing in GitHub Actions:
Reusable Workflows
Dispatched workflows
Composite Actions
There is an article describing their pros and cons.
In your case if the duplicated steps are in the single workflow you also can:
extract them to the "preparation" job
upload build artifacts
add "preparation" job to "needs" key of both jobs
download build artifact in both jobs
The below code snippet should do the work for you. Instead of creating two jobs, one for lint and another for test, you can use one job and create multiple tasks
name: Github Actions CI
on: [ pull_request ]
jobs:
lint:
name: Lint and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: leafo/gh-actions-lua#v8.0.0
- uses: leafo/gh-actions-luarocks#v4.0.0
- name: Install Luacheck
run: luarocks install luacheck
- name: Run Lint Check
- run: ./run-linter.sh
- name: Install Busted
run: luarocks install busted
- name: Build Project
run: ./build-project.sh
- name: Run Test Suite
- run: ./run-test-suite.sh
After reading this answer:this
I tried to do the same.
I have a .net core project and in my case, I am using a repo with a publish version so my appsettings.json is in the root of the repo.
# This is a basic workflow to help you get started with Actions
name: DeployToStaging
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
pull_request:
types: [assigned, opened, synchronize, reopened]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
FTP-Deploy-Action:
name: FTP-Deploy-Action
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2.1.0
with:
fetch-depth: 2
- uses: microsoft/variable-substitution#v1
with:
files: '${{env.DOTNET_ROOT}}/appsettings.json'
env:
ConnectionStrings.ToBudget: 'This is just a test'
- name: FTP Deploy
uses: SamKirkland/FTP-Deploy-Action#3.1.0
with:
ftp-server: <MyServer>
# FTP account username
ftp-username: <MyUsername>
ftp-password: ${{ secrets.FtpPassword }}
So basically I want to transform my connection string (for now it is just a test, in the future I will create a secret) and then push it to the server through FTP.
Everything is working except the variable substitution. The error is: No file matched with specific pattern: /appsettings.json
Any help would be much appreciated
Just found the issue.
instead of files: '${{env.DOTNET_ROOT}}/appsettings.json' I just need to do files: 'appsettings.json'
Now I am having a second issue. SamKirkland/FTP-Deploy-Action#3.1.0 doesn't like the change. It is avoiding uploading because the repo is dirty.
EDIT: regarding the second issue I moved to sebastionpopp/ftpaction