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:
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/[email protected] - uses: leafo/[email protected] - run: luarocks install luacheck - run: ./run-linter.sh test: name: Test runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: leafo/[email protected] - uses: leafo/[email protected] - 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:
You can run an unlimited number of jobs as long as you are within the workflow usage limits. For more information, see "Usage limits and billing" for GitHub-hosted runners and "About self-hosted runners" for self-hosted runner usage limits.
You can only have a reusable workflow call another reusable workflow, but you can't have it reference more than one.
You can configure a GitHub Actions workflow to be triggered when an event occurs in your repository, such as a pull request being opened or an issue being created. Your workflow contains one or more jobs which can run in sequential order or in parallel.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With