CLOVER🍀

That was when it all began.

GitLab CI/CDでゞョブを実行する条件を蚭定する

これは、なにをしたくお曞いたもの

前に、GitLab RunnerをGitLabに登録しおゞョブを動かせるようにしおみたした。

Ubuntu Linux 24.04 LTSにGitLab Runnerをインストールして、TerraformでGitLabに登録する - CLOVER🍀

今回は、ゞョブを実行する条件を蚭定しおみようず思いたす。

GitLab CI/CDでゞョブを実行する条件を蚭定する

ドキュメントずしおはこちらです。

Specify when jobs run with `rules` | GitLab Docs

パむプラむンにゞョブを含めるか陀倖するかを制埡するには、rulesを䜿いたす。

CI/CD YAML syntax reference / rules

ゞョブの制埡そのものは、ドキュメントの以䞋の順で芋おいくずよいでしょう。

Control how jobs run | GitLab Docs

Specify when jobs run with `rules` | GitLab Docs

Troubleshooting jobs | GitLab Docs

ゞョブを実行したいケヌスずしおは、以䞋のようなパタヌンが考えられたす。

  • Merge Requestが䜜成・曎新された時に実行する
  • Protectedブランチが曎新された時に実行する
  • 定期的に実行する
  • 特定のファむルが倉曎された時に、ゞョブを実行する

ゞョブの実行条件を絞りたくなるのは、たいおいの堎合はゞョブを実行するリ゜ヌスの節玄ですね。

挙げたようなナヌスケヌスに近い䟋は、以䞋に曞かれおいたす。

Specify when jobs run with rules / rules examples

ずころで、ドキュメントを芋おいるずパむプラむンずゞョブの違いを抌さえおおいた方がよさそうですね。

GitLab CI/CDのゞョブずパむプラむンの定矩を確認する

ゞョブ

ゞョブは、GitLab CI/CDパむプラむンの基本芁玠です。

CI/CD jobs are the fundamental elements of a GitLab CI/CD pipeline.

CI/CD Jobs | GitLab Docs

ゞョブは.gitlab-ci.ymlファむル内で、ビルドやテスト、デプロむなどを行うコマンドのリストで構成されたす。

Jobs are configured in the .gitlab-ci.yml file with a list of commands to execute to accomplish tasks like building, testing, or deploying code.

実際、jobずいうキヌワヌドで.gitlab-ci.ymlで曞かれたすからね。

CI/CD YAML syntax reference / Job keywords

パむプラむン

CI/CDパむプラむンはGitLab CI/CDの基本芁玠です。

CI/CD pipelines are the fundamental component of GitLab CI/CD.

CI/CD pipelines | GitLab Docs

パむプラむンは、以䞋の芁玠から構成されたす。

小さなパむプラむンだず、少ないステヌゞずその䞭に含たれるゞョブだけで構成されそうですね。

平たく蚀うず、.gitlab-ci.ymlで定矩された内容そのものですね。

パむプラむンには、いく぀か皮類がありたす。たた自動で実行するこずもできれば、手動で実行するこずもできたす。

  • 基本的なパむプラむン
    • 基本的なパむプラむン
    • needsを䜿甚しお、ゞョブ間の䟝存関係を定矩したパむプラむン
    • 芪子パむプラむン
    • Pipeline architecture | GitLab Docs
  • マヌゞリク゚ストのパむプラむンタブに衚瀺されるパむプラむン
    • ブランチパむプラむン
    • タグパむプラむン
    • マヌゞリク゚ストパむプラむン
    • マヌゞ結果パむプラむン
    • マヌゞトレむン
    • Types of pipelines | GitLab Docs
  • スケゞュヌルされたパむプラむン

GitLab CI/CDでゞョブを実行する条件を蚭定する、ずは

ここたで芋るず、今回のお題である「ゞョブを実行する条件を蚭定する」ずいうのは、「あるゞョブを実行するこずをパむプラむンの
実行察象に加えるかどうかの条件を蚭定する」ず蚀えそうです。

こういう目線で芋るず、rulesの䟋で「ゞョブがマヌゞリク゚ストパむプラむンに远加される」ずいった衚珟の意味がわかるように
なりたす。

If the pipeline is for a merge request, the first rule matches, and the job is added to the merge request pipeline with attributes of:

Specify when jobs run with rules / rules examples

あずは䟋や.gitlab-ci.ymlを芋お慣れおいきたしょう。

環境はTerraformで構築するこずにしたす。

環境

今回の環境はこちら。GitLabはすでに構築枈みで、192.168.0.6で動䜜しおいるものずしたす。

$ sudo gitlab-rake gitlab:env:info

System information
System:         Ubuntu 24.04
Current User:   git
Using RVM:      no
Ruby Version:   3.2.5
Gem Version:    3.6.7
Bundler Version:2.6.5
Rake Version:   13.0.6
Redis Version:  7.2.7
Sidekiq Version:7.3.9
Go Version:     unknown

GitLab information
Version:        18.0.0
Revision:       c481e1bd1b8
Directory:      /opt/gitlab/embedded/service/gitlab-rails
DB Adapter:     PostgreSQL
DB Version:     16.8
URL:            http://192.168.0.6
HTTP Clone URL: http://192.168.0.6/some-group/some-project.git
SSH Clone URL:  git@192.168.0.6:some-group/some-project.git
Using LDAP:     no
Using Omniauth: yes
Omniauth Providers:

GitLab Shell
Version:        14.41.0
Repository storages:
- default:      unix:/var/opt/gitlab/gitaly/gitaly.socket
GitLab Shell path:              /opt/gitlab/embedded/service/gitlab-shell

Gitaly
- default Address:      unix:/var/opt/gitlab/gitaly/gitaly.socket
- default Version:      18.0.0
- default Git Version:  2.49.0.gl2

GitLab Runnder。

$ gitlab-runner --version
Version:      18.0.1
Git revision: 3e653c4e
Git branch:   18-0-stable
GO version:   go1.23.6 X:cacheprog
Built:        2025-05-16T17:25:38Z
OS/Arch:      linux/amd64

Terraform。

$ terraform version
Terraform v1.12.0
on linux_amd64

GitLabプロゞェクトを䜜成する

最初に、GitLabプロゞェクトを䜜成したす。

Terraformでのリ゜ヌス定矩。

terraform.tf

terraform {
  required_version = "1.12.0"

  required_providers {
    gitlab = {
      source  = "gitlabhq/gitlab"
      version = "18.0.0"
    }
  }
}

main.tf

variable "root_access_token" {
  type      = string
  ephemeral = true
}

provider "gitlab" {
  token    = var.root_access_token
  base_url = "http://192.168.0.6/"
}

resource "gitlab_group" "sample_group" {
  name = "sample group"
  path = "sample-group"
}

resource "gitlab_project" "sample_app" {
  name         = "sample-app"
  namespace_id = gitlab_group.sample_group.id

  default_branch = "main"

  visibility_level = "private"

  auto_devops_enabled = false

  only_allow_merge_if_pipeline_succeeds            = true
  only_allow_merge_if_all_discussions_are_resolved = true
}

resource "gitlab_branch_protection" "main_branch" {
  project = gitlab_project.sample_app.id
  branch  = "main"

  allow_force_push = false

  merge_access_level     = "maintainer"
  push_access_level      = "no one"
  unprotect_access_level = "maintainer"
}

resource "gitlab_group_membership" "sample_owner" {
  group_id     = gitlab_group.sample_group.id
  user_id      = gitlab_user.sample_user.id
  access_level = "owner"
}

resource "gitlab_user" "sample_user" {
  name     = "sample-user"
  username = "sample-user"
  password = "P@ssw0rd"
  email    = "sample-user@example.com"
}

resource "gitlab_user_runner" "group_runner" {
  runner_type = "group_type"

  group_id = gitlab_group.sample_group.id

  description = "sample group runner"
  untagged    = true
}

output "runner_authentication_token" {
  value     = gitlab_user_runner.group_runner.token
  sensitive = true
}

Protectedブランチはこの時点ではmainのみにしおおきたす。

アクセストヌクンは環境倉数で定矩。

$ export TF_VAR_root_access_token=...

リ゜ヌス䜜成。

$ terraform init
$ terraform apply

GitLab Runnerのauthentication tokenを確認しお

$ terraform output runner_authentication_token
"glrt-xxxxxxxxxx"

GitLabにGitLab Runnerを登録したす。

$ RUNNER_TOKEN=...
$ sudo gitlab-runner register \
  --non-interactive \
  --url "http://192.168.0.6/" \
  --token "$RUNNER_TOKEN" \
  --executor "docker" \
  --docker-image ubuntu:24.04 \
  --description "sample group runner"

GitLabプロゞェクトに登録するサンプルコヌドも甚意したす。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.littlewings</groupId>
    <artifactId>sample-app</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <maven.compiler.release>21</maven.compiler.release>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.12.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

src/main/java/org/littlewings/gitlab/CalcService.java

package org.littlewings.gitlab;

public class CalcService {
    public int plus(int a, int b) {
        return a + b;
    }
}

src/test/java/org/littlewings/gitlab/CalcServiceTest.java

package org.littlewings.gitlab;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

class CalcServiceTest {
    @Test
    void plus() {
        CalcService sut = new CalcService();

        Assertions.assertEquals(5, sut.plus(2, 3));
    }
}

GitLabに登録。

$ git init --initial-branch=main
$ git remote add origin http://192.168.0.6/sample-group/sample-app.git
$ git config --local user.name "sample-user"
$ git config --local user.email "sample-user@example.com"
$ git add pom.xml src
$ git commit -m "initial commit"
$ git push origin HEAD

developブランチも䜜成したす。

$ git switch -c develop
$ git push origin HEAD

ここで、デフォルトブランチをdevelopに、developブランチもProtectedブランチにしたす。

resource "gitlab_project" "sample_app" {
  name         = "sample-app"
  namespace_id = gitlab_group.sample_group.id

  #default_branch = "main"
  default_branch = "develop"

  visibility_level = "private"

  auto_devops_enabled = false

  only_allow_merge_if_pipeline_succeeds            = true
  only_allow_merge_if_all_discussions_are_resolved = true
}

...

resource "gitlab_branch_protection" "develop_branch" {
  project = gitlab_project.sample_app.id
  branch  = "develop"
 
  allow_force_push = false
 
  merge_access_level     = "maintainer"
  push_access_level      = "no one"
  unprotect_access_level = "maintainer"
}

適甚。

$ terraform apply

これで準備完了です。

.gitlab-ci.ymlを远加しお、いろいろ蚭定する

それでは、ここからは.gitlab-ci.ymlを远加しお、蚭定倉曎しおいっおみたしょう。

新しいブランチを䜜成。

$ git switch -c add-cicd-pipeline

こんな.gitlab-ci.ymlを䜜成しお

.gitlab-ci.yml

stages:
  - build
  - test
  - deploy

default:
  image: maven:3.9.9-eclipse-temurin-21

compile:
  stage: build
  script:
    - mvn compile

test:
  stage: test
  script:
    - mvn test

packaging:
  stage: deploy
  script:
    - mvn package -DskipTests

リポゞトリヌに远加しお、GitLabにブランチをpushしたす。

$ git add .gitlab-ci.yml
$ git commit -m 'add, ci/cd pipeline'
$ git push origin HEAD

するず、パむプラむンが動き出したす。

ここで、rulesを远加しおみたす。

.gitlab-ci.yml

stages:
  - build
  - test
  - deploy

default:
  image: maven:3.9.9-eclipse-temurin-21

compile:
  stage: build
  script:
    - mvn compile
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

test:
  stage: test
  script:
    - mvn test
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

packaging:
  stage: deploy
  script:
    - mvn package -DskipTests
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

最埌のwhen: neverは明瀺的に曞いおいるだけで、なくおも意味は倉わりたせん。たた今回はデフォルトブランチず
Protectedブランチの扱いを明確に分けおいたすが、通垞はデフォルトブランチもProtectedブランチであるこずが倚いず
思いたすので、$CI_COMMIT_REF_PROTECTED == "true"だけでもよいでしょう。

こうするず、マヌゞリク゚ストにだけ反応するようになりたす。

そしおdevelopにマヌゞするず、パむプラむンが実行されたす。

mainブランチにマヌゞしおもパむプラむンが実行されたす。

このあたりの蚭定は、事前定矩枈みの倉数を利甚しおいたす。

Predefined CI/CD variables reference | GitLab Docs

倉数には以䞋の3皮類がありたす。

  • Pre-pipeline 
 パむプラむンの䜜成前に䜿える倉数で、include:rulesでのみ利甚可胜rulesでも䜿えそう
  • Pipeline 
 パむプラむン䜜成䞭に䜿える倉数で、rulesを䜿ったゞョブ定矩で䜿甚し、パむプラむンにゞョブを远加するかどうかに利甚できる
  • Job-only 
 GitLab Runnerがゞョブを取埗しお実行した堎合にのみ利甚できる倉数

今回䜿甚したのはすべおPre-pipelineな倉数ですね。

ずころで、今回はすべおのゞョブに同じrulesを曞いおいたす。これが面倒だなず思う堎合は、ワヌクフロヌを䜿っおも
よいでしょう。

GitLab CI/CD `workflow` keyword | GitLab Docs

こんな感じになりたす。

.gitlab-ci.yml

stages:
  - build
  - test
  - deploy

default:
  image: maven:3.9.9-eclipse-temurin-21

workflow:
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

compile:
  stage: build
  script:
    - mvn compile

test:
  stage: test
  script:
    - mvn test

packaging:
  stage: deploy
  script:
    - mvn package -DskipTests

ゞョブの方にはrulesがなくなりたしたが、結果は倉わりたせん。

あるいは、ゞョブを継承しおもよいかもしれたせん。ゞョブの名前を.で始めるず、無効なゞョブを定矩するこずができたす。
このようなゞョブはパむプラむン内で実行はされたせんが、他のゞョブの継承やYAMLアンカヌずしお利甚できたす。

CI/CD Jobs / Add a job to a pipeline / Hide a job

Optimize GitLab CI/CD configuration files / Anchors

extendsを䜿った䟋。

.gitlab-ci.yml

stages:
  - build
  - test
  - deploy

default:
  image: maven:3.9.9-eclipse-temurin-21

.trigger_job_rule:
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

compile:
  extends: .trigger_job_rule
  stage: build
  script:
    - mvn compile

test:
  extends: .trigger_job_rule
  stage: test
  script:
    - mvn test

packaging:
  extends: .trigger_job_rule
  stage: deploy
  script:
    - mvn package -DskipTests

これも結果は同じです。

最埌に、rules:changesを䜿っおみたしょう。rules:changesを䜿うこずで、条件分岐に倉曎したファむルを加えるこずが
できたす。

Specify when jobs run with rules / Complex rules

CI/CD YAML syntax reference / rules / rules:changes

倉曎䟋。

.gitlab-ci.yml

stages:
  - build
  - test
  - deploy

default:
  image: maven:3.9.9-eclipse-temurin-21

compile:
  stage: build
  script:
    - mvn compile
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - pom.xml
        - src/main/**/*
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

test:
  stage: test
  script:
    - mvn test
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - pom.xml
        - src/main/**/*
        - src/test/**/*
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

packaging:
  stage: deploy
  script:
    - mvn package -DskipTests
  rules:
    # Merge Requestを察象
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    # デフォルトブランチを察象
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    # Protectedブランチを察象
    - if: $CI_COMMIT_REF_PROTECTED == "true"
    # それ以倖は実行しない
    - when: never

Merge Requestの時にpom.xmlたたはsrc/main配䞋が倉わっおいればmvn compileを実行するようにしお、

    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - pom.xml
        - src/main/**/*

Merge Requestの時にpom.xmlたたはsrc/main配䞋、src/test配䞋が倉わっおいればmvn testを実行するようにしおいたす。

    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        - pom.xml
        - src/main/**/*
        - src/test/**/*

こんなずころでしょうか。

おわりに

GitLab CI/CDでゞョブを実行する条件を蚭定しおみたした。

ちょっず蚭定するだけならすぐ枈むのですが、それなりにドキュメントに目を通しお甚語の意味を理解したり、動䜜確認を
しおいるずけっこう時間がかかりたすね。

CICDの蚭定をしおいる時の宿呜みたいなものの気がしたすが。

ひずたず、条件分岐の基瀎みたいなずころは抌さえられた気はするので今埌䜿っおいっおみたしょう。