Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

GitLab ๋ฌด๋ฃŒ ๋ฒ„์ „์—๋Š” ์—†๋Š” ๊ฐ€์žฅ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋Š” ํ•„์ˆ˜ ์ฝ”๋“œ ๊ฒ€ํ† ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ์†Œ ๋ฌดํšจํ™”์— ๋ฐ˜๋Œ€ํ•˜๊ณ  ๋ณ‘ํ•ฉ ์š”์ฒญ(MR)์„ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์ตœ์†Œํ•œ์˜ ๊ธฐ๋Šฅ์€ ์Šค์Šค๋กœ ํ•ด๋ณด์ž. ์—ฌ๋Ÿฌ ๊ฐœ๋ฐœ์ž๊ฐ€ MR์— ์—„์ง€์†๊ฐ€๋ฝ์„ ์น˜์ผœ์„ธ์šธ ๋•Œ๊นŒ์ง€ Merge๋ฅผ ๊ธˆ์ง€ํ•  ๊ฒƒ์ด๋‹ค.

์ด๊ฒƒ์ด ์™œ ํ•„์š”ํ•œ๊ฐ€์š”?

์šฐ๋ฆฌ ์กฐ์ง์€ GitLab ๋ผ์ด์„ผ์Šค๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌ์ž…ํ•  ์—ฌ์œ ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฐœ๋ฐœ์€ ์ธํ„ฐ๋„ท ์ ‘์† ์—†์ด ํ์‡„ ๋ฃจํ”„๋กœ ์ง„ํ–‰๋˜๊ณ  ์—„๊ฒฉํ•œ ์˜ˆ์‚ฐ ๊ณ„ํš์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ์ž์ฒด ๊ด€๋ฆฌํ˜• ๋ผ์ด์„ ์Šค๋ฅผ ๊ตฌ๋งคํ•˜๋Š” ๋ฐ ์ˆ˜๊ฐœ์›”์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์ง€๋งŒ ์ง€๊ธˆ ์ž‘์—…์„ ์™„๋ฃŒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋˜๋Š” ์ผ๋ถ€ ๊ฐœ๋ฐœ์ž์˜ ๊ฒฝ์šฐ ๋ณดํ˜ธ๋œ ๋ธŒ๋žœ์น˜์—์„œ ๋ณ‘ํ•ฉ์„ ์™„์ „ํžˆ ๊ธˆ์ง€ํ•˜์ง€๋งŒ ๋ณ‘ํ•ฉ ๊ถŒํ•œ์ด ์žˆ๋Š” ๊ฐœ๋ฐœ์ž๋Š” ๋ณด๋„ˆ์Šค๋กœ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์˜ MR์„ ๋ณ‘ํ•ฉํ•  ๋•Œ ์ถฉ๋Œ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.
  • ๋˜๋Š” ์–ด์ œ ๊ณ ์šฉ๋œ ์ฃผ๋‹ˆ์–ด๋ผ๋„ ์ฝ”๋“œ ๊ฒ€ํ†  ์—†์ด ๋งˆ์Šคํ„ฐ ๋ธŒ๋žœ์น˜์™€ ํ†ต์ œ๋˜์ง€ ์•Š์€ ๋ณ‘ํ•ฉ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ํ•œ ์ฒซ ๋ฒˆ์งธ ์ผ์€ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๋ฏธ ๋น„์Šทํ•œ ์ผ์„ (์ฝ”๋“œ ์ˆ˜์ • ์—†์ด) ํ™•์‹คํžˆ ์ˆ˜ํ–‰ํ–ˆ๋‹ค๊ณ  ๋ฏฟ์—ˆ์ง€๋งŒ ์ปค๋ฎค๋‹ˆํ‹ฐ ๋ฒ„์ „์—๋Š” ์•„์ง ๊ทธ๋Ÿฌํ•œ ๊ตฌํ˜„์ด ์—†๋‹ค๋Š” ๊ฒƒ์ด ๋ฐํ˜€์ง„ Google์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์ž‘์—… ๊ณ„ํš

์˜ˆ๋ฅผ ๋“ค์–ด ํ…Œ์ŠคํŠธ ์ €์žฅ์†Œ์—์„œ ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์„ ๊ตฌ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋งˆ์ด์•ฑ:

  1. GitLab API์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•œ ํ† ํฐ์„ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด "์ฐฌ์„ฑ" ๋ฐ "๋ฐ˜๋Œ€" ํˆฌํ‘œ ์ˆ˜์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  2. GitLab ๋ณ€์ˆ˜์— ํ† ํฐ์„ ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  3. ํŒŒ์ดํ”„๋ผ์ธ์— ์˜ค๋ฅ˜๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ณ‘ํ•ฉ์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค(์ฐฌ์„ฑ ํˆฌํ‘œ๊ฐ€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ).
  4. CI/CD ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ผ๋ถ€๋กœ ํˆฌํ‘œ ํ™•์ธ์„ ์„ค์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
  5. ๋ณดํ˜ธ๋œ ๋ธŒ๋žœ์น˜์— ๋Œ€ํ•œ ์ปค๋ฐ‹์„ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๋ณ€๊ฒฝ์€ MR์„ ํ†ตํ•ด์„œ๋งŒ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค.
  6. ๊ฒฐ๊ตญ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚ฌ๋Š”์ง€ ํ™•์ธํ•ด ๋ณด์ž

1. API์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ํ† ํฐ ์ƒ์„ฑ

์‚ฌ์šฉ์ž ์„ค์ • โ†’ ์•ก์„ธ์Šค ํ† ํฐ์œผ๋กœ ์ด๋™ํ•˜์—ฌ ํ† ํฐ์„ ์ ์–ด ๋‘์„ธ์š”.

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

ํ† ํฐ์„ ๋ฐ›์„ ๊ณ„์ •
API ์•ก์„ธ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ ๊ฑฐ์˜ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๋ณ„๋„์˜ Gitlab ๊ณ„์ •์„ ๋งŒ๋“ค์–ด ๋ฆฌํฌ์ง€ํ† ๋ฆฌ(์˜ˆ: Reporter)์— ๋Œ€ํ•œ ์ตœ์†Œํ•œ์˜ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๊ณ  ํ•ด๋‹น ๊ณ„์ •์— ๋Œ€ํ•œ ํ† ํฐ์„ ์–ป๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

2. Gitlab ๋ณ€์ˆ˜์— ํ† ํฐ์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.

์˜ˆ๋ฅผ ๋“ค์–ด ์ด์ „ ๋‹จ๊ณ„์—์„œ ํ† ํฐ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค. QmN2Y0NOUFlfeXhvd21ZS01aQzgK

์„ค์ • ์—ด๊ธฐ โ†’ CI/CD โ†’ ๋ณ€์ˆ˜ โ†’ ๋ณ€์ˆ˜ ์ถ”๊ฐ€ โ†’ GITLAB_TOKEN_FOR_CI

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋‹ค์Œ์„ ์–ป์Šต๋‹ˆ๋‹ค:

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

์ด๋Š” ํ•˜๋‚˜์˜ ์ €์žฅ์†Œ ๋˜๋Š” ์ €์žฅ์†Œ ๊ทธ๋ฃน์—์„œ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ์ฝ”๋“œ ๊ฒ€ํ†  ํ›„ ๋™๋ฃŒ์˜ ์Šน์ธ์„ ๋ฐ›์ง€ ๋ชปํ•  ๊ฒฝ์šฐ Merge๋ฅผ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ๋ณ‘ํ•ฉ์— ๋Œ€ํ•œ ๊ธˆ์ง€ ์‚ฌํ•ญ์€ ํˆฌํ‘œ๊ฐ€ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์œผ๋ฉด ์–ด์…ˆ๋ธ”๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ์ด ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์„ค์ • โ†’ ์ผ๋ฐ˜ โ†’ ๋ณ‘ํ•ฉ ์š”์ฒญ โ†’ ๋ณ‘ํ•ฉ ํ™•์ธ์œผ๋กœ ์ด๋™ํ•˜์—ฌ ์กฐ๋ฆฝ ๋ผ์ธ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์–ด์•ผ ํ•จ ์˜ต์…˜์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

4. ํŒŒ์ดํ”„๋ผ์ธ ์„ค์ •

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ CI/CD ํŒŒ์ดํ”„๋ผ์ธ์„ ์•„์ง ์ƒ์„ฑํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ
์ €์žฅ์†Œ ๋ฃจํŠธ์— ํŒŒ์ผ ์ƒ์„ฑ .gitlab-ci.yml ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋‚ด์šฉ์œผ๋กœ:

stages:
  - build
  - test

variables:
  NEED_VOTES: 1

include:
  - remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

run-myapp:
  stage: build
  script: echo "Hello world"

CI/CD ๊ตฌ์„ฑ์„ ์œ„ํ•œ ๋ณ„๋„์˜ ์ €์žฅ์†Œ
ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด myapp.gitlab-ci.yml ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์•ผ ํ•˜๋Š” ๋ณ„๋„์˜ ์ €์žฅ์†Œ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋นŒ๋“œ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ฐธ๊ฐ€์ž์˜ ์•ก์„ธ์Šค๋ฅผ ๋” ์ž˜ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ƒˆ ํŒŒ์ดํ”„๋ผ์ธ ํŒŒ์ผ์˜ ์œ„์น˜๋Š” myapp ์ €์žฅ์†Œ - ์„ค์ • - CI/CD - ์กฐ๋ฆฝ ๋ผ์ธ - ์‚ฌ์šฉ์ž ์ •์˜ CI ๊ตฌ์„ฑ ๊ฒฝ๋กœ - ์ƒˆ ํŒŒ์ผ ์ง€์ •์œผ๋กœ ์ด๋™ํ•˜์—ฌ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. myapp.gitlab-ci.yml@gitlab-ce-mr-approvals/Ci

ํŒ: ๋ฆฐํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GitLab CI ํŒŒ์ผ ๋ณ€๊ฒฝ
ํ˜ผ์ž ์ž‘์—…ํ•˜๋”๋ผ๋„ MR์„ ํ†ตํ•ด ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์€ ํŒŒ์ดํ”„๋ผ์ธ ํŒŒ์ผ์— ๋Œ€ํ•œ ๋ชจ๋“  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ฆฐํ„ฐ๋ฅผ ํ†ตํ•ด ์‹คํ–‰ํ•˜๋Š” ๋ฐ ํฐ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. YAML ํŒŒ์ผ์˜ ๊ตฌ๋ฌธ์— ์‹ค์ˆ˜๊ฐ€ ์žˆ์–ด๋„ ํ”„๋กœ๋•์…˜ ํŒŒ์ดํ”„๋ผ์ธ์ด ์ค‘๋‹จ๋˜์ง€๋Š” ์•Š์ง€๋งŒ ๋‹จ์ˆœํžˆ ๋ณ‘ํ•ฉ์ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค.

ํŒŒ์ดํ”„๋ผ์ธ์— ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋Š” Linter๊ฐ€ ํฌํ•จ๋œ ์ปจํ…Œ์ด๋„ˆ์˜ ์˜ˆ:

Hub.docker.com/r/gableroux/gitlab-ci-lint
Hub.docker.com/r/sebiwi/gitlab-ci-validate

๊ฒ€์ฆ ๋‹จ๊ณ„์˜ ์˜ˆ:

stages:
  - lint

lint:
  stage: lint
  image: sebiwi/gitlab-ci-validate:1.3.0
  variables:
    GITLAB_HOST: https://gitlab.com
  script:
    - CI_FILES=(./*.yml)
    - for f in "${CI_FILES[@]}"; do
        gitlab-ci-validate $f;
      done;

์ž‘๋™ํ•˜๋ ค๋ฉด ํŒŒ์ดํ”„๋ผ์ธ์— ๋ช‡ ๊ฐ€์ง€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

stages:
- test

variables:
NEED_VOTES: 1

include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

NEED_VOTES ๋ณ€์ˆ˜๋Š” ๋ณ‘ํ•ฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ ค๋ฉด MR์ด ์–ผ๋งˆ๋‚˜ ๋งŽ์€ "์ข‹์•„์š”"๋ฅผ ๊ฐ€์ ธ์•ผ ํ•˜๋Š”์ง€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. XNUMX๊ณผ ๊ฐ™์€ ๊ฐ’์€ ์ž์‹ ์ด MR์— "์ข‹์•„์š”"๋ฅผ ํ‘œ์‹œํ•˜์—ฌ ์Šน์ธํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

include์—๋Š” '์ข‹์•„์š”' ์ˆ˜๋ฅผ ํ™•์ธํ•˜๋Š” ํ…Œ์ŠคํŠธ ๋‹จ๊ณ„๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

myapp.gitlab-ci.yml์˜ ์˜ˆ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ํŒŒ์ดํ”„๋ผ์ธ
stages:
- build
- test

variables:
NEED_VOTES: 0

include:
- remote: "https://gitlab.com/gitlab-ce-mr-approvals/ci/-/raw/master/check-approve.gitlab-ci.yml"

run-myapp:
stage: build
image: openjdk
script:
- echo CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- java HelloWorld.java

๋‚ด์šฉ check-approve.gitlab-ci.yml
ci-mr:
stage: test
script:
- echo ${CI_API_V4_URL}
- echo "CI_PROJECT_ID ${CI_PROJECT_ID}"
- echo "CI_COMMIT_SHA ${CI_COMMIT_SHA}"
- "export MR_ID=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .id else {} end" | grep --invert-match {})"
- "export MR_TITLE=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .title else {} end" | grep --invert-match {})"
- "export MR_WIP=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .work_in_progress else {} end" | grep --invert-match {})"
- "export MR_UPVOTES=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .upvotes else {} end" | grep --invert-match {})"
- "export MR_DOWNVOTES=$(curl --silent --request GET --header "PRIVATE-TOKEN: $GITLAB_TOKEN_FOR_CI" ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests | jq ".[] | if .sha == \"${CI_COMMIT_SHA}\" then .downvotes else {} end" | grep --invert-match {})"
- MR_VOTES=$(expr ${MR_UPVOTES} - ${MR_DOWNVOTES})
- NEED_VOTES_REAL=${NEED_VOTES:-1}
- echo "MR_ID ${MR_ID} MR_TITLE ${MR_TITLE} MR_WIP ${MR_WIP} MR_UPVOTES ${MR_UPVOTES} MR_DOWNVOTES ${MR_DOWNVOTES}"
- echo "MR_VOTES ${MR_VOTES} Up vote = 1, down vote = -1, MR OK if votes >=${NEED_VOTES_REAL}"
- if [ "${MR_VOTES}" -ge "$(expr ${NEED_VOTES_REAL})" ];
then
echo "MR OK";
else
echo "MR ERROR Need more votes";
exit 1;
fi
image: laptevss/gitlab-api-util
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release/.*$/'

์ธ์ฆ ์ค‘์— ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ •๋ณด:

  • master ๋˜๋Š” release/* ๋ธŒ๋žœ์น˜์—์„œ MR์„ ์ƒ์„ฑํ•  ๋•Œ๋งŒ ๊ฒ€์‚ฌ๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค๋Š” ์ œํ•œ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • GitLab API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ "์ข‹์•„์š”"์™€ "์‹ซ์–ด์š”" ์ˆ˜๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.
  • ๊ธ์ •์ ์ธ ์‘๋‹ต๊ณผ ๋ถ€์ •์ ์ธ ์‘๋‹ต์˜ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.
  • ์ฐจ์ด๊ฐ€ NEED_VOTES์— ์„ค์ •ํ•œ ๊ฐ’๋ณด๋‹ค ์ž‘์œผ๋ฉด ๋ณ‘ํ•ฉ ๊ธฐ๋Šฅ์ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค.

5. ๋ณดํ˜ธ๋œ ๋ธŒ๋žœ์น˜์— ๋Œ€ํ•œ ์ปค๋ฐ‹์„ ๊ธˆ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ฝ”๋“œ ๊ฒ€ํ† ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜๋Š” ๋ถ„๊ธฐ๋ฅผ ์ •์˜ํ•˜๊ณ  MR์„ ํ†ตํ•ด์„œ๋งŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์„ค์ • โ†’ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ โ†’ ๋ณดํ˜ธ๋œ ๋ถ„๊ธฐ๋กœ ์ด๋™ํ•˜์„ธ์š”.

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

6. ํ™•์ธ

NEED_VOTES ์„ค์ •: 0

MR์„ ๋งŒ๋“ค๊ณ  '์‹ซ์–ด์š”'๋ฅผ ๋„ฃ์Šต๋‹ˆ๋‹ค.

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

๋นŒ๋“œ ๋กœ๊ทธ์—์„œ:

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

์ด์ œ "์ข‹์•„์š”"๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ๋‹ค์‹œ ํ™•์ธ์„ ์‹œ์ž‘ํ•˜์„ธ์š”.

Gitlab CE์˜ ์ฝ”๋“œ ๊ฒ€ํ† : ๋ณ‘ํ•ฉ ์š”์ฒญ ์Šน์ธ์ด ์—†์ง€๋งŒ ์ •๋ง ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€