38

I have a workflow for CI in a monorepo, for this workflow two projects end up being built. The jobs run fine, however, I'm wondering if there is a way to remove the duplication in this workflow.yml file with the setting up of the runner for the job. I have them split so they run in parallel as they do not rely on one another and to be faster to complete. It's a big time difference in 5 minutes vs. 10+ when waiting for the CI to finish.

jobs:
  job1:
    name: PT.W Build
    runs-on: macos-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v1

      - name: Setup SSH-Agent
        uses: webfactory/ssh-agent@v0.2.0
        with:
          ssh-private-key: |
            ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Setup JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Setup Permobil-Client
        run: |
          echo no | npm i -g nativescript
          tns usage-reporting disable
          tns error-reporting disable
          npm run setup.all

      - name: Build PT.W Android
        run: |
          cd apps/wear/pushtracker
          tns build android --env.uglify

  job2:
    name: SD.W Build
    runs-on: macos-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v1

      - name: Setup SSH-Agent
        uses: webfactory/ssh-agent@v0.2.0
        with:
          ssh-private-key: |
            ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Setup JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Setup Permobil-Client
        run: |
          echo no | npm i -g nativescript
          tns usage-reporting disable
          tns error-reporting disable
          npm run setup.all

      - name: Build SD.W Android
        run: |
          cd apps/wear/smartdrive
          tns build android --env.uglify

You can see here the jobs have almost an identical process, it's just the building of the different apps themselves. I'm wondering if there is a way to take the duplicate blocks in the jobs and create a way to only write that once and reuse it in both jobs.

Brad Martin
  • 5,157
  • 4
  • 27
  • 43
  • I haven't nailed the correct syntax to achieve it. However, I'm trying to create a local action that runs the duplicated steps inside my main workflow. Reference: https://github.community/t5/GitHub-Actions/Path-to-action-in-the-same-repository-as-workflow/td-p/38761 This seems to be the way to go about it, but currently the job fails and haven't figured out the correct syntax to set this up with the paths. – Brad Martin Jan 15 '20 at 21:01
  • Current error: ``` ##[error]Can't find 'action.yml' or 'Dockerfile' under '/Users/runner/runners/2.163.1/work/-client/-client/.github/actions/build-setup-action.yml'. Did you forget to run actions/checkout before running your local action? ``` – Brad Martin Jan 15 '20 at 21:06

3 Answers3

19

As I know currently there is no way to reuse steps
but in this case, you can use strategy for parallel build and different variation:

jobs:
  build:
    name: Build
    runs-on: macos-latest
    strategy:
      matrix:
        build-dir: ['apps/wear/pushtracker', 'apps/wear/smartdrive']
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v1

      - name: Setup SSH-Agent
        uses: webfactory/ssh-agent@v0.2.0
        with:
          ssh-private-key: |
            ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Setup JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Setup Permobil-Client
        run: |
          echo no | npm i -g nativescript
          tns usage-reporting disable
          tns error-reporting disable
          npm run setup.all

      - name: Build Android
        run: |
          cd ${{ matrix.build-dir }}
          tns build android --env.uglify

For more information please visit https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategy

Arakis
  • 739
  • 4
  • 15
Seongbok Youn
  • 306
  • 3
  • 4
8

Since Oct. 2021, "Reusable workflows are generally available"

Reusable workflows are now generally available.
Reusable workflows help you reduce duplication by enabling you to reuse an entire workflow as if it were an action. A number of improvements have been made since the beta was released in October:

  • You can utilize outputs to pass data from reusable workflows to other jobs in the caller workflow
  • You can pass environment secrets to reusable workflows
  • The audit log includes information about which reusable workflows are used

See "Reusing workflows" for more.

workflow

A workflow that uses another workflow is referred to as a "caller" workflow.
The reusable workflow is a "called" workflow.

One caller workflow can use multiple called workflows.
Each called workflow is referenced in a single line.

The result is that the caller workflow file may contain just a few lines of YAML, but may perform a large number of tasks when it's run. When you reuse a workflow, the entire called workflow is used, just as if it was part of the caller workflow.

Example:

In the reusable workflow, use the inputs and secrets keywords to define inputs or secrets that will be passed from a caller workflow.

# .github/actions/my-action.yml
# Note the special trigger 'on: workflow_call:'

on:
  workflow_call:
    inputs:
      username:
        required: true
        type: string
    secrets:
      envPAT:
        required: true

Reference the input or secret in the reusable workflow.

jobs:
  reusable_workflow_job:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: ./.github/actions/my-action
        with:
          username: ${{ inputs.username }}
          token: ${{ secrets.envPAT }}

With ./.github/actions/my-action the name of the my-action.yml file in your own repository.

A reusable workflow does not have to be in the same repository, and can be in another public one.

Davide Benvegnù aka CoderDave illustrates that in "Avoid Duplication! GitHub Actions Reusable Workflows" where:

VonC
  • 1,129,465
  • 480
  • 4,036
  • 4,755
  • This answer would be improved by adding code snippets that demonstrate how to use the feature. Currently it is a borderline link-only answer IMO. – jtbandes Feb 14 '22 at 22:08
  • @jtbandes Thank you for this feedback. I have edited the answer accordingly. – VonC Feb 14 '22 at 22:13
  • 1
    Thanks for the update. To address the spirit of the question, I think it's still unclear how to use the snippets, since `my-action` is referenced in the second snippet but not the first — is my-action supposed to be a file name of the first snippet? – jtbandes Feb 15 '22 at 00:41
  • @jtbandes I have further clarified the answer and added a concrete example. – VonC Feb 15 '22 at 06:49
  • `not the special trigger on: workflow_call` I think you mean note ? – maerteijn Feb 16 '22 at 09:56
  • @maerteijn Thank you. I have edited the answer and fixed the typo. – VonC Feb 16 '22 at 13:15
5

There are 3 main approaches for code reusing in GitHub Actions:

There is an article describing their pros and cons.

In your case, it's better to use composite actions.

Cardinal
  • 141
  • 2
  • 2