
หลังจากที่คราวก่อนได้โม้เกี่ยวกับ gitlab ไปแล้วว่าทำไมทีมผมจึงใช้งานมัน โดยประโยชน์ของมันหลักๆ ที่ผมชอบก็คือ รองรับการเขียน CICD ตั้งแต่การใช้งานฟรีเลย ฉะนั้นแล้วพวกเรามาทำ CICD กันเถอะ
CICD คืออะไร
CICD ย่อมาจาก Continuous integration and continuous delivery ผมขออธิบายแบบสั้นๆ ก็คือการทำให้โปรเจ็คของเราทำงานแบบอัตโนมัติทั้งหมด ตั้งแต่การ run unitest, build, packing ไปจน deploy หรือใครจะมี flow แบบอื่นก็แล้วแต่จะใส่เข้าไป
สิ่งที่ต้องรู้
ก่อนที่จะเริ่มเขียน gitlab ci กันผมอยากให้ทุกคนต้องใช้ git และ docker เป็นก่อนนะ และเข้าใจการทำงานของ Container ด้วย เพราะการทำพวกระบบ CICD เราจะใช้ docker เข้าช่วย หากใครไม่รู้ ก็ไปรู้ซะ…
สมัคร gitlab ก่อนเลย
แน่ละจะใช้ของเขาก็สมัครของเขาด้วยเพื่อจะได้ใช้งานได้ https://gitlab.com/users/sign_in#register-pane
สมัครเลยมันฟรี!!!
สร้าง Project ขึ้นมาหนึ่งอัน
ใน gitlab จะใช้คำว่า project แทน repository
สร้างไฟล์ .gitlab-ci.yml
ให้เราสร้างไฟล์ .gitlab-ci.yml
ไว้ที่ root project ซึ่งทุกครั้งที่เรา push ขึ้นมา gitlab จะมาอ่านไฟล์นี้ทุกครั้ง
ผมจะขอยกตัวอย่างการเขียนจาก https://gitlab.com/twin-opensource/laravel-nginx-phpfpm-k8s/blob/master/.gitlab-ci.yml ทุกคนสามารถโหลด project นี้ไปทดสอบได้
Ref: https://twinsynergy.co.th/structure-laravel5-nginx-phpfpm-k8s/
Stages
stages:
- build
- test
- release
- deploy
stages
เป็นการกำหนด flow การทำงานของ pipeline นี้ให้กับ job
ต่างๆ โดยมันจะเรียงตามลำดับที่เราได้กำหนดไว้ เช่น
- เริ่มต้นคือ
build
ถ้าสำเร็จมันก็จะไปที่test
และถ้าในbuild
นั้นมีหลาย jobs มันก็จะทำงานพร้อมกันเป็นแบบ parallel - ถ้า jobs ทั้งหมดใน
build
ทำงานสำเร็จทั้งหมดtest
ถึงจะทำงานต่อ - ถ้า jobs ทั้งหมดใน
test
ทำงานสำเร็จทั้งหมดrelease
ถึงจะทำงานต่อ - ถ้า jobs ทั้งหมดใน
release
ทำงานสำเร็จทั้งหมดdeploy
ถึงจะทำงานต่อ - ถ้า jobs ทั้งหมดใน
deploy
ทำงานสำเร็จทั้งหมด ก็คือจบ pipeline มันจะขึ้นว่า success

Job
job
คือการกำหนดว่าจะให้ทำอะไรใน stage
นั้นๆ เช่น
job1:
script: "execute-script-for-job1"
job2:
script: "execute-script-for-job2"
โดยภายใน job จะมีค่ากำหนดเพิ่มเติมอีกเช่น image, before_script, script เป็นต้น
npm:
stage: build
image: node:10-alpine
before_script:
- apk add --no-cache --update make gcc g++ libc-dev libpng-dev automake autoconf libtool
script:
- cd laravel/
- '[ -f package-lock.json ] && rm package-lock.json'
- npm install
- npm run prod
cache:
key: cache-node
paths:
- laravel/node_modules/
- laravel/public/
only:
- master
ตัวอย่างข้างบนคือ job ที่ชื่อว่า npm โดยค่าอื่นๆ มีดังนี้
stage
คือการบอกว่า job นี้อยู่ใน stage ไหนimage
กำหนด docker image มาใช้งานโดยมันจะเอามาจาก hub.docker.combefore_script
ก่อนเริ่มscript
ให้มันทำอะไร โดยเราสามารถใส่คำสั่ง command ของ docker image ที่เลือกมาจากimage
ได้ เช่นในตัวอย่างผมให้มันติดตั้งmake gcc g++ libc-dev libpng-dev automake autoconf libtool
เพื่อไว้เตรียมตัวติดตั้ง packet ต่างๆ ของ nodescript
เป็นการกำหนดคำสั่ง command ให้มันทำอะไรcache
เราสามารถให้มัน cache ไฟล์หรือโฟล์เดอร์ไว้ เพื่อนำไปใช้งานใน job อื่นต่อ เช่นในตัวอย่างผมทำการ cache โฟล์เดอร์laravel/node_modules/
และlaravel/public/
และตั้งชื่อ cache นี้ว่าcache-node
only
เป็นการกำหนดว่าให้ job นี้ทำงานเฉพาะ branch หรือ tag ชื่อmaster
นั้นหมายความว่าเมื่อไรก็ตามที่ผมทำการ push code หรือ merge request เข้าไปยัง branch master หรือสร้าง tag ชื่อ master ไป job นี้จะถูกทำงานทันที
การดึง cache มาใช้งาน
จากโค็ดด้านบนผมได้ทำการ cache ไฟล์ชื่อ cache-node
ใน job npm ไว้แล้ว คราวนี้เรามาดูวิธีการให้ job ที่เราต้องการดึง cache ชุดนี้มาใช้
release-nginx:
stage: release
image: docker:latest
services:
- docker:dind
cache:
key: cache-node
paths:
- laravel/public/
policy: pull
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build --pull -t $CI_REGISTRY_IMAGE:nginx -f Dockerfile-nginx .
- docker push $CI_REGISTRY_IMAGE:nginx
only:
- master
ที่นี่เรามาดูในส่วนของ cache
จากโค็ดชุดนี้กัน มันจะมี policy
เพิ่มขึ้นเป็นการกำหนดว่า job นี้จะให้มันทำการ pull
หรือดึงข้อมูลมาจาก cache ที่ชื่อว่า cache-node
ทุกครั้งก่อนทำการ script
และเรายังสามารถเลือกได้ว่าจะให้เอาเฉพาะไฟล์ หรือโฟล์เดอร์ไหนมา ซึ่งในตอนแรกผมผมทำการ cache โฟล์เดอร์ laravel/node_modules/
และ laravel/public/
ไว้ แต่เวลา pull
ลงมาผมเลือกเฉพาะ laravel/public/
เพียงเท่านี้เราก็สามารถเขียน pipeline ให้กับโปรเจ็คของเราได้แล้วง่ายๆ ซึ่งในบทความต่อๆ ผมจะบอกวิธีการใช้งาน .gitlab-ci.yml
เพิ่มเติม