Search code examples
gitlabgitlab-cipipelinecicd

In gitlab-ci.yml pipeline how can I use only and except keywords properly?


This is how my project's structure looks like

├── main_project
│   ├── service1
│   │   ├── [...]
│   ├── service2
│   │   ├── [...]
│   ├── docs
│   │   ├── [...]
│   ├── .gitlab-ci.yml
    └── Makefile

My .gitlab.ci-yml

 [...]
 service1_build:
  image: image
  stage: build
  script:
    - #doing something
  only:
    changes:
      - /service1/**/*
      - /.gitlab-ci.yml
      - /Makefile
  except:
    changes:
      - /docs/**/*

 service2_build:
  image: image
  stage: build
  script:
    - #doing something
  only:
    changes:
      - /service2/**/*
      - /.gitlab-ci.yml
      - /Makefile
  except:
    changes:
      - /docs/**/*

 test:
  image: image
  stage: test
  needs:
    - service1_build
    - service2_build
  script:
    - #doing something
  except:
    changes:
      - /docs/**/*

 service1_docker:
  image: image
  stage: docker
  needs:
    - test
  script:
    - #doing something
  only:
    refs:
      - master
    changes:
      - /service1/**/*
      - /.gitlab-ci.yml
      - /Makefile
  except:
    changes:
      - /docs/**/*

 service2_docker:
  image: image
  stage: docker
  needs:
    - test
  script:
    - #doing something
  only:
    refs:
      - master
    changes:
      - /service2/**/*
      - /.gitlab-ci.yml
      - /Makefile
  except:
    changes:
      - /docs/**/*
 [...]

I tried this, but it is not working properly. For example, if I change a file in docs folder, the test job will be executed by the pipeline.

These are the rules that I want to be applied to each job:

  • service1_build: run on all branches, when there is any modification within the service1 folder or if Makefile or .gitlab-ci.yml has been changed. But it should not run when files in docs folder have been modified.
  • service2_build: run on all branches, when there is any modification within the service2 folder or if Makefile or .gitlab-ci.yml has been changed. But it should not run when files in docs folder have been modified.
  • test: run on all branches every time, except when files in docs folder have been modified.
  • service1_docker: run only on master, when there is any modification within the service1 folder or if Makefile or .gitlab-ci.yml has been changed. But it should not run when files in docs folder have been modified.
  • service2_docker: run only on master, when there is any modification within the service2 folder or if Makefile or .gitlab-ci.yml has been changed. But it should not run when files in docs folder have been modified.

Is this applicable like this? Or how should I handle this? When I am giving the path, it always looking it from the gitlab-ci.yml's folder?


Solution

  • Following your project structure, you should try to change your only/except paths like this :

    only:
        changes:
          - main_project/service1/**/*
          - .gitlab-ci.yml
          - Makefile
      except:
        changes:
          - main_project/docs/**/*
    

    This include the main_project directory.

    You should also add some optional needs to your test job, because if there is only updates on service1, the test job will look to the service2 job and fail :

    test:
      stage: test
      needs:
        - job: service1_build
          optional: true
        - job: service2_build
          optional: true
    

    I made some tests with these new fix and your rules are working properly : https://gitlab.com/sandbox_fm/ci-rules.

    You also should consider moving from only/except to rules because :

    only and except are not being actively developed. rules is the preferred keyword to control when to add jobs to pipelines.