Need help with conditional workflows using paths

Hello, I am currently trying to build a workflow that enables Continuous Deployment for an web application.

I am currently creating 2 different docker images, one for Nginx, and another for the application.

Due to the fact that the Nginx docker image doesn’t change that often, but application image does, I am trying to make the Nginx deployment workflow run ONLY when certain files under “nginx” directory has changed.


First, I tried with the next configuration to recreate this manner, but due to the fact that “ignore-paths” only ignores the workflow IFF the changed file is under “nginx” directory, changing other files which is not in the “nginx” directory files would still trigger the Application workflow, running both workflows which is… quite not as I expected.

Applciation workflow yml

name: Automatic Application Deployment to Production

on:
push:
branches:
- master
ignore-paths:
- 'nginx/**'

jobs:
build-and-deploy:
name: build and deploy to production
...(build image for application, and push to ECR, and deploy to ECS)

Nginx workflow yml

name: Automatic Nginx and Application Deployment to Production

on:
push:
branches:
- master
paths:
- 'nginx/**'

jobs:
build-and-deploy:
name: build and deploy to production
...(build image for Nginx and application, and push to ECR, and deploy to ECS)

Another thing I tried, is to mash both the Nginx and Application workflow into one yml file, and try to conditionally change the workflow to run, or not to run the steps within the jobs like the following.

But due to the fact that there is currently no way to condition the steps using the file changes, I am currently stuck with how to go on with this method.

Application and Nginx workflow yml

name: Automatic Nginx and Application Deployment to Production

on:
  push:
    branches:
      - master

jobs:
  build-and-deploy:
 name: Build application image and deploy to production
 runs-on: ubuntu-latest
 steps:
-uses: actions/checkout@master
 with:
 ref: ${{ github.ref }}
-name: Configure for AWS deployment...
 ...  
 - name: Build and push Nginx image to ECR  
 if: \*\*SOME WAY TO DETECT THE FILE CHANGE\*\* \<==== NEED HELP HERE...  
 ...  
 - name: Build and push application image to ECR, and Deploy to production  
 ...

I’m hoping to gather any information, or any third-party actions that enables me to run this conditional steps.

Any information, suggestion, critisism is welcome. 

Thank you in advance.

Your first two workflows look right to me.  The first one will build based on any push that includes changes that are not under the Nginx path but if the push only changes the Nginx path it will not run.  The second should run only if the changes are under the Nginx path.  

Is that not the behavior you are seeing?

chirspat,

Greatly appreciate your reply.

@chrispat wrote:

Your first two workflows look right to me.  The first one will build based on any push that includes changes that are not under the Nginx path but if the push only changes the Nginx path it will not run.  The second should run only if the changes are under the Nginx path.  

 

Is that not the behavior you are seeing?

Yes, what you are stating is correct and it is the behaviour I am seeing, but this was not the behaviour I wanted…

I am very sorry that I didn’t mention another constraint in the first post, but this is how I wanted things to go.

Constraints

Due to how application container depends on the Nginx configuration, I MUST sequentially run the deployment like the following.

  • Nginx build and deploy => Application build and deploy

Rules of workflow

  1. If any of the files under “nginx” changes, it runs the Nginx workflow, but not the Application workflow 

  2. If any of the files under “nginx” does not change, it does not run the Nginx workflow, but instead runs the Application workflow

  3. If multiple files change INCLUDING the files under “nginx” directory, it runs the Nginx workflow, but it does not run the Application workflow.

  4. If mutliple files change other than the files under “nginx” directory, it does not run the Nginx workflow, but instead runs the Application workflow

Workflow configuration

  • Nginx workflow => build and push “Nginx image” AND build and push “Application image” to ECR, and deploys to ECS
  • Applciation workflow => build and push “Applciation image” to ECR, and deploys to ECS

So, yes paths and ignore-paths works for 1 and 2 for this case.

But for 3 and 4, specifying paths and ignrore-paths wouldn’t work, because it runs both workflows due to its conditioning nature.

I thought of a way to go about this for 2 ways, but I couldn’t find a way to materialize these thoughts.

A. If there was a way to configure (order) the workflows sequentially, so that the Nginx workflow always starts and ends before the Application workflow, then I could be able to run Nginx workflow => Application workflow consistantly. (even though, 2 application deployment runs… it gets the job done.)

B. The second yml file I presented in the first post, which enables me to conditionally run a step when a file change is detected. This enables me to run the same workflow everytime, and consistantly run the steps in order.

jobs:
  build-and-deploy:
 name: Build application image and deploy to production
 runs-on: ubuntu-latest
 steps:
-uses: actions/checkout@master
 with:
 ref: ${{ github.ref }}
-name: Configure for AWS deployment...
 ...  
 - name: Build and push Nginx image to ECR  
 if: \*\*SOME WAY TO DETECT THE FILE CHANGE\*\* \<==== NEED HELP HERE...  
 ...  
 - name: Build and push application image to ECR, and Deploy to production  
 ...

I would like to know if there are any ways to materialize the above thoughts.

Thank you for taking your time with me.

I figured it out…

Writing with ignore-path will not run the workflow if and only if the changed files are under those certain paths.

on:
  push:
    branches:
      - master
    ignore-paths:
      - 'nginx/**'

But, by writing the path using ! like below, this will never run the workflow when there are changes under that specified path.
This enables me to condition the workflow which will never run, even when there are other file changes.

This was the behaviour I wanted.

on:
  push:
    branches:
      - master
    paths:
      - '!nginx/**'

Thank you for your help, chirspat :slight_smile:

1 Like

Is there another way based on context analysis?

This should be paths-ignore instead.

You could use paths-filter - it’s a 3rd party Github action created exactly for this purpose.
There’s quite self explanatory example in the README.

Workflows can’t be composed into bigger units and it’s not possible to specify order in which they will run. If you have conditional steps - based on which files were modified, you can either use paths + paths-ignore and create workflow for each possible combination of the steps or use the if clause with action to detect the modified files.

Having more workflows has a benefit of using just a built-in functionality.
However it wouldn’t work well for more complex scenarios.
With more components, you could end up with a dozen of workflows where some parts would have to be duplicated many times.

Using if clauses within single workflow job has also another benefit - all artifacts of previous steps are available without need to upload them somewhere.