Question on workflow of gitlab-ci.yml

So here is an example of a gitlab-ci.yml file I have.

I have three different builds and three deploy stages.

I have to build the code three different ways due to passwords etc

I want to do the following:

build_dev → test_dev → deploy_dev

build_integration → test_integration → deploy_integration

The only statements are on the build jobs.

The issue is that the test_integration and deploy_integration still run. Why? do I need to put an only statement on those?

image: java:8-jdk

stages:
  - build_dev
  - test_dev
  - deploy_dev
  
  - build_integration
  - test_integration
  - deploy_integration

before_script:
#  - echo `pwd` # debug
#  - echo "$CI_BUILD_NAME, $CI_BUILD_REF_NAME $CI_BUILD_STAGE" # debug
  - export GRADLE_USER_HOME=`pwd`/.gradle

cache:
  paths:
    - .gradle/wrapper
    - .gradle/caches

build_dev:
  stage: build_dev
  script:
    - ./gradlew assemble
  artifacts:
    paths:
      - build/libs/*.jar
    expire_in: 1 week
  only:
    - develop

test_dev:
  stage: test_dev
  script:
    - ./gradlew check

deploy_dev:
  stage: deploy_dev
  script:
    - ./deploy
build_integration:
  stage: build_integration
  script:
    - ./gradlew assemble
  artifacts:
    paths:
      - build/libs/*.jar
    expire_in: 1 week
  only:
    - main

test_integration:
  stage: test_integration
  script:
    - ./gradlew check

deploy_integration:
  stage: deploy_integration
  script:
    - ./deploy

You can use needs keyword.

test_integration:
  needs:
    - build_integration

...

deploy_integration:
  needs:
    - test_integration
...

If you setup the dependencies on *_dev as well you can also drop the different stages and have just build, test, deploy
more details in here

so you are saying i can do the following:

image: gradle:latest

stages:
  - build
  - test
  - deploy
before_script:
#  - echo `pwd` # debug
#  - echo "$CI_BUILD_NAME, $CI_BUILD_REF_NAME $CI_BUILD_STAGE" # debug
  - export GRADLE_USER_HOME=`pwd`/.gradle
  - export TEST='test'

cache:
  paths:
    - .gradle/wrapper
    - .gradle/caches

build_dev:
  stage: build
  environment: development
  script:
    #- ./gradlew assemble
    - echo "building development"
  artifacts:
    paths:
      - build/libs/*.jar
    expire_in: 1 week
  only:
    - develop

test_dev:
  stage: test
  environment: development
  needs:
    - build_dev
  script:
    #- ./gradlew check
    - echo "testing development"

deploy_dev:
  stage: deploy
  needs:
    - test_dev
  environment: development
  script:
    #- ./deploy
    - echo "deploying development"

build_integration:
  stage: build
  environment: integration
  script:
    - echo "building integration"
    #- ./gradlew assemble
  artifacts:
    paths:
      - build/libs/*.jar
    expire_in: 1 week
  only:
    - main

test_integration:
  stage: test
  needs:
    - build_integration
  environment: integration
  script:
    #- ./gradlew check
    - echo "testing integration"

deploy_integration:
  stage: deploy
  needs:
    - test_integration
  environment: integration
  script:
    #- ./deploy
    - echo "deploying integration"

Yes, but I have overlooked that you are passing artifacts so to ensure the deploy_* jobs get artifacts also add relevant build_* job into the needs list.

deploy_dev:
...
  needs:
    - build_dev
    - test_dev

alternative is to use dependencies

deploy_dev:
...
  dependencies:
    - build_dev

You can also use CI/CD YAML syntax reference | GitLab to see full options.

This was an example. With that being said, if we are not using artifacts then we would not need the build_* in there.

What is better needs or dependencies?

My code is this

image: gradle:latest

stages:
  - build
  - test
  - deploy
before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle
  - export TEST='test'

cache:
  paths:
    - .gradle/wrapper
    - .gradle/caches

build_dev:
  stage: build
  environment: development
  script:
    #- ./gradlew assemble
    - echo "building development"
  only:
    - develop

test_dev:
  stage: test
  environment: development
  dependencies:
    - build_dev
  script:
    #- ./gradlew check
    - echo "testing development"

deploy_dev:
  stage: deploy
  dependencies:
    - build_dev
    - test_dev
  environment: development
  script:
    #- ./deploy
    - echo "deploying development"



build_integration:
  stage: build
  environment: integration
  script:
    - echo "building integration"
    #- ./gradlew assemble
  only:
    - main

test_integration:
  stage: test
  dependencies:
    - build_integration
  environment: integration
  script:
    #- ./gradlew check
    - echo "testing integration"

deploy_integration:
  stage: deploy
  dependencies:
    - build_integration
    - test_integration
  environment: integration
  script:
    #- ./deploy
    - echo "deploying integration"

I have updated the code. It is reflected above now. But as you can see in the image below, test_dev and deploy_dev still run why? What am I missing? Do I need to put an only statement in there?

but if i use the following code it works as i expect

image: gradle:latest

stages:
  - build
  - test
  - deploy
before_script:
  - export GRADLE_USER_HOME=`pwd`/.gradle
  - export TEST='test'

cache:
  paths:
    - .gradle/wrapper
    - .gradle/caches

build_dev:
  stage: build
  environment: development
  script:
    #- ./gradlew assemble
    - echo "building development"
  only:
    - develop

test_dev:
  stage: test
  environment: development
  dependencies:
    - build_dev
  script:
    #- ./gradlew check
    - echo "testing development"
  only:
    - develop

deploy_dev:
  stage: deploy
  dependencies:
    - build_dev
    - test_dev
  environment: development
  script:
    #- ./deploy
    - echo "deploying development"
  only:
    - develop


build_integration:
  stage: build
  environment: integration
  script:
    - echo "building integration"
    #- ./gradlew assemble
  only:
    - main

test_integration:
  stage: test
  dependencies:
    - build_integration
  environment: integration
  script:
    #- ./gradlew check
    - echo "testing integration"

deploy_integration:
  stage: deploy
  dependencies:
    - build_integration
    - test_integration
  environment: integration
  script:
    #- ./deploy
    - echo "deploying integration"

What am I missing or am I doing it correctly with the “only” statements?

You need to copy the only to all the jobs as required.

Doesn’t matter really in this case, both are fine.

Okay. The only statement is required. I figured as much but that seemed redundant. lol. Thank you @balonik for your assistance!

1 Like