rzlvmp
rzlvmp

Reputation: 9442

How to separate conditions for different event types in GitHub Actions

We have a workflow file:

---
name: 'Deploy Test Env'

on:
  pull_request:
    types:
      - edited
      - opened
      - synchronize
    branches:
      - develop
    paths:
      - '**.js'

jobs:
  deploy:
    # yamllint disable rule:line-length
    name: '[DEV] DEPLOY'
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Deploy
        run: |
          echo 'Deploy Dev Env by ${{ github.event.action }} event type' >> "${GITHUB_STEP_SUMMARY}"

When new Pull Request (feature_branchdevelop) is created or new commit inside feature_branch is occured, pull_request's opened (or synchronize) event is triggering Job.

Here is a paths condition: if none of JavaScript files are changed, application source code is the same and we don't need to deploy new test environment. That is correct.

But, here is third action type: edited. It is used because we have environment parameters passed inside Pull Request message. And if message is changed (edited), it means that parameters possibly changed too, and we have to re-deploy test environment even if **.js files are not changed. But because of paths condition edited event will not be triggered too.

In other words, description should be looks like:

---
name: 'Deploy Test Env'

on:
  # will be triggered only if *.js files changed
  pull_request:
    types:
      - opened
      - synchronize
    branches:
      - develop
    paths:
      - '**.js'

  # will be triggered anytime when PR contents are updated
  pull_request:
    types:
      - edited
    branches:
      - develop

But YAML doesn't support duplicated keys and this format is wrong.

OR:

on:
  pull_request:
    types:
      # paths are set only for `opened` and `synchronize` types
      - type: edited
      - type: opened
        paths:
          - '**.js'
      - type: synchronize
        paths:
          - '**.js'
    branches:
      - develop

But types should be a list...

The question is: Is it possible to describe desired behavior? Maybe pull_request may be passed twice as array or paths may be set under the edited type (something like my second example)

Upvotes: 2

Views: 1221

Answers (2)

rzlvmp
rzlvmp

Reputation: 9442

Here is one more example of reusable workflows:

  • .github/workflows/reuser_on_edited.yml
    the workflow will reuse to_reuse.yml jobs when PR contents are edited
---
name: 'Reuser on Edited'

on:
  pull_request:
    types:
      - edited
    branches:
      - 'develop'

jobs:
  reuse:
    uses: ./.github/workflows/to_reuse.yml
    with:
      original_github: ${{ toJSON(github) }}
      other_input: 'BOOM! edited'
  • .github/workflows/reuser_on_pr_changed.yml
    the workflow will reuse to_reuse.yml jobs when some of **.js files is changed.
---
name: 'Reuser on PR changed'

on:
  pull_request:
    types:
      - opened
      - synchronize
    branches:
      - 'develop'
    paths:
      - '**.js'

jobs:
  reuse:
    uses: ./.github/workflows/to_reuse.yml
    with:
      original_github: ${{ toJSON(github) }}
  • .github/workflows/to_reuse.yml
    the file to reuse jobs inside it
on:
  workflow_call:
    inputs:
      original_github:
        type: string
        required: true
        description: "github context that passed from original workflow (JSON)"
      other_input:
        type: string
        default: 'default'
        required: false
        description: "just for LOLs"

jobs:
  deploy_job:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout v2
        uses: actions/checkout@v2
        with:
          ref: ${{ fromJSON(inputs.original_github).event.pull_request.head.sha }}

      - name: Deploy
        run: |
          {
            echo 'Deploy Dev Env by `${{ fromJSON(inputs.original_github).event.action }}` event type';
            echo '';
            echo 'Also `${{ inputs.other_input }}` input is passed';
          } >> "${GITHUB_STEP_SUMMARY}"

Original github context may be passed as JSON string and reused inside different workflow.

Also, different conditions (paths, etc.) may be set for different pull_request action types.

Upvotes: 1

Azeem
Azeem

Reputation: 14677

You can use reusable workflows to achieve this.

Divide your workflow into three (3) workflows:

  • ci.yml: reusable workflow (workflow that performs stuff)
  • ci-pr-opened-synchronize.yml: reusable workflow caller (for PR opened/synchronize for .js files)
  • ci-pr-edited.yml: reusable workflow caller (for PR edited)

The above reusable workflow callers will call the ci.yml workflow.


Here's a complete working example with .md files filter and PRs to the main branch (https://github.com/iamazeem/github-actions-reusable-workflow-test):

ci.yml

name: CI

on:
  workflow_call:
    inputs:
      message:
        type: string
        description: custom message
        required: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Print message
        if: ${{ inputs.message }}
        env:
          MESSAGE: ${{ inputs.message }}
        run: |
          echo "message: $MESSAGE"

ci-pr-opened-synchronize.yml

name: PR opened/synchronize

on:
  pull_request:
    types:
      - opened
      - synchronize
    branches:
      - main
    paths:
      - '**.md'

jobs:
  pr-open-sync:
    uses: ./.github/workflows/ci.yml
    with:
      message: 'PR opened/synchronized'

ci-pr-edited.yml

name: PR edited

on:
  pull_request:
    types:
      - edited
    branches:
      - main

jobs:
  pr-edited:
    uses: ./.github/workflows/ci.yml
    with:
      message: 'PR edited'

You may check this PR and its respective actions for this sample:

Upvotes: 1

Related Questions