การทำ CI ใน Gitlab CI นั้น จำเป็นต้องสร้างไฟล์ .gitlab-ci.yml ไว้ในโฟลเดอร์ของโปรเจ็คซะก่อน ซึ่งทุกครั้งที่เรา push ไฟล์ขึ้นมา gitlab จะมาอ่านไฟล์ .gitlab-ci.yml นี้เพื่อสั่งให้ Gitlab CI ทำงานตามคำสั่งที่กำหนดไว้ในไฟล์ .gitlab-ci.yml ทุกครั้ง
Gitlab Runner คืออะไร
Gitlab Runner คือ Server ของ Gitlab ที่ไว้ทำงานพวก Pipeline ทั้งหมด โดยมันจะทำการ Run jobs และส่งค่ากลับมาที่ Gitlab
ซึ่งการใช้งาน Pipeline หากครบ 2,000 นาทีต่อเดือนแล้ว ตัว CI/CD ของเราก็จะไม่สามารถใช้งานได้ โดยใน Pipeline เราจะขึ้นเป็น Stuck หากอยากใช้งานต่อต้องสมัครแบบ Silver ซึ่งเขาคิดอยู่ที่ 19$ ต่อคน และเราจะได้ 10,000 นาทีต่อเดือนมา
การกำหนด Jobs ใน Gitlab CI คืออะไร
Jobs คือ องค์ประกอบพื้นฐานในการเขียนคำสั่ง Giblat CI ใช้กำหนดว่าใน Pipeline จะมีการสั่ง Runner ให้ทำงานอะไรบ้าง โดยในไฟล์ .gitlab-ci.yml จะมีกี่ Jobs ก็ได้ไม่จำกัด และเราสามารถตั้งชื่อ Jobs ได้เอง ยกเว้นคำว่า image, services, stages, types, before_script, after_script, variables, cache, include ใช้ตั้งชื่อ Jobs ไม่ได้
ภายใต้ Jobs เราจะต้องกำหนด jobs parameters (เช่น stage, script, image, ...) เพื่อบอกให้ Runner ทราบว่าต้องทำงานอะไร และอย่างไรบ้าง เช่น
job 0:
stage: .pre
script: make something useful before build stage
job 1:
stage: build
script: make build dependencies
job 2:
stage: build
script: make build artifacts
การกำหนด Default Parameters ให้ Jobs
เนื่องจาก parameters ก็คือคำสั่งการทำงานภายใน jobs ดังนั้นการกำหนด global parameters จึงเป็นการกำหนดคำสั่งการทำงานให้กับทุกๆ jobs เช่น
default:
image: ruby:2.5
rspec:
script: bundle exec rspec
rspec 2.6:
image: ruby:2.6
script: bundle exec rspec
jobs ชื่อ rspec จะเรียกใช้ image ruby:2.5 โดยอัตโนมัติ เพราะใน jobs ไม่ได้กำหนด parameters ค่า image ไว้ Runner จึงไปเรียกใช้ parameters ค่า image จาก default
jobs ชื่อ rspec 2.6 จะเรียกใช้ image ruby:2.6 เพราะใน jobs ได้กำหนด parameters ค่า image ไว้เป็น ruby:2.6 อยู่แล้ว
การกำหนด Default Variables ให้ Jobs
เป็นการกำหนด global variables ให้กับทุกๆ jobs เช่น
default:
image: 'ruby:2.4'
before_script:
- echo Hello World
variables:
DOMAIN: example.com
WEBHOOK_URL: https://my-webhook.example.com
rubocop:
inherit:
default: false
variables: false
script: bundle exec rubocop
rspec:
inherit:
default: [image]
variables: [WEBHOOK_URL]
script: bundle exec rspec
jobs ชื่อ rubocop จะไม่ทำการ inherit ทั้ง global parameters และ global variables มาใช้เลย ในขณะที่ jobs ชื่อ rspec จะทำการ inherit แค่ตัว global parameters image และ global variables WEBHOOK_URL มาใช้เท่านั้น
การกำหนด Stages ให้ Jobs
เป็นการกำหนด step การทำงานให้กับ jobs ใน pipeline เพื่อบอก Runner ว่าต้องทำ jobs ไหนให้เสร็จก่อน เสร็จแล้วต้องไปทำ jobs ไหนต่อบ้าง แต่ถ้าเราไม่กำหนด Stages ทุกๆ jobs จะถูกสั่งให้ทำงานพร้อมกัน
stages:
- build
- test
- deploy
job 1:
stage: build
script: make build dependencies
job 2:
stage: build
script: make build artifacts
job 3:
stage: test
script: make test
job 4:
stage: deploy
script: make deploy
Runner จะสั่งทำ jobs ตามค่า stages ที่เรากำหนด คือ build ไป test ไป deploy โดย
- 1. เริ่มทำ jobs ที่มีค่า stage เป็น build (job 1 และ job 2) ก่อน
- 2. เมื่อทำ build เสร็จไม่มี error จึงจะไปทำ jobs ที่มีค่า stage เป็น test (job 3)
- 3. เมื่อทำ test เสร็จไม่มี error จึงจะไปทำ jobs ที่มีค่า stage เป็น deploy (job 4)
Jobs Parameters (คำสั่งการทำงานภายใน jobs) มีอะไรบ้าง
- script : ใช้ระบุ คำสั่ง shell script ให้ Runner ทำงาน
- image : ใช้ระบุ Docker Image ที่จะใช้งาน
- services : ใช้ระบุ Services ใน Docker Image ที่จะใช้งาน
- before_script : ใช้ระบุคำสั่งที่จะให้ทำงาน ก่อนทำ jobs นี้
- after_script : ใช้ระบุคำสั่งที่จะให้ทำงาน หลังทำ jobs นี้เสร็จ
- stages : ใช้ระบุว่าใน pipeline จะต้องทำ stages อะไรบ้าง
- stage : ใช้ระบุว่า jobs นี้จะถูกทำใน stages ไหน
- only : ใช้จำกัดให้ jobs ทำกับ git แค่กับส่วน branches หรือ tags ที่กำหนดเท่านั้น
- except : ใช้จำกัดให้ jobs ไม่ต้องทำกับ git ในส่วน branches หรือ tags ที่กำหนด
- rules : ใช้กำหนดเงื่อนไขการทำงานของ jobs
- tags : ใช้เจาะจง Runner ที่จะใช้ run project
- allow_failure : ใช้กำหนดว่า jobs นี้ สามารถปล่อยให้เกิด fail ได้ โดยไม่กระทบการทำงาน
- when : ใช้กำหนดว่า jobs นี้ จะถูกสั่งทำงานเมื่อไร เช่น เมื่อเกิด fail ให้ jobs นี้ทำงานทันที
- environment : ใช้กำหนดชื่อ environment ที่จะให้ Runner ทำการ deploy
- cache : ใช้กำหนดชื่อไฟล์ หรือโฟลเดอร์ที่จะถูกทำ cache ในระหว่างที่ jobs ทำงาน
- artifacts : ใช้กำหนดชื่อไฟล์ หรือโฟลเดอร์ที่จะถูกแนบไปเก็บไว้บน Gitlab หลังจาก jobs นี้ทำงานเสร็จ
- dependencies : ใช้ระบุให้ jobs หนึ่งไปใช้ค่า artifacts ที่กำหนดจากอีก jobs หนึ่งได้
- retry : ใช้กำหนดจำนวนครั้งที่ Runner จะพยายามทำ jobs นี้ซ้ำ หาก jobs นี้เกิด fail
- timeout : ใช้กำหนดค่า timeout ให้กับ jobs
- parallel : ใช้กำหนดจำนวน script คำสั่งย่อยๆ ใน jobs ที่จะให้ Runner สามารถทำงานแบบขนานกันไปได้
- trigger : ใช้กำหนดว่าใน jobs นี้จะมีการไปเรียกอีก pipeline หนึ่งในอีกที่หนึ่งขึ้นมาทำงานด้วย
- include : ใช้กำหนดให้ Pipeline นี้ Runner ทำงานตามไฟล์ YAML จากภายนอกที่เรา include เข้ามาด้วย
- extends : ใช้กำหนดให้ jobs หนึ่งสามารถเสือบทอดคุณสมบัติ ของอีก jobs หนึ่งได้
- pages : เป็น jobs พิเศษ ใช้ส่ัง upload ไฟล์บน Gitlab
- variables : ใช้กำหนดตัวแปรให้ jobs
- interruptible : ใช้กำหนดว่าแต่ละ jobs ใน Pipeline จะมี jobs ไหนบ้างที่จะถูกยกเลิกการทำงาน หรือไม่ถูกยกเลิกการทำงาน เมื่อเกิดการ interrupt จากการสั่ง run Pipeline ใหม่
- resource_group : ใช้จำกัด jobs ไม่ให้ทำงานแบบขนานไปพร้อมๆ กัน เพื่อลด load ของ Runner
ตัวอย่างไฟล์ ไฟล์ .gitlab-ci.yml
image: node:latest
cache:
key: node_modules
paths:
- node_modules
stages:
- install
- build
- deploy
install:
stage: install
only:
- master
script:
- yarn install
artifacts:
paths:
- node_modules
build:
stage: build
only:
- master
script:
- yarn run build
dependencies:
- install
artifacts:
paths:
- build
deploy:
stage: deploy
only:
- master
script:
- yarn global add firebase-tools --cache-folder node_modules
- firebase deploy -m "Pipeline $CI_PIPELINE_ID, build $CI_BUILD_ID" --non-interactive --token $FIREBASE_DEPLOY_KEY --project $FIREBASE_PROJECT
dependencies:
- install
- build