CI/CD là gì?
Có rất nhiều khái niệm cả chính thống và cả tà đạo về CI/CD nhưng theo mình thì CI/CD hiểu đơn giản nhất là CI (Continuous Integration) và CD (Continuous Delivery) tức là quá trình tích và triển khai hợp nhanh và liên tục.
Về mặt khái niệm là vậy nhưng về mặt triển khai thì CI/CD là quá trình tự động thực hiện các quá trình build, test, release, deploy khi có các trigger như commit/merge code lên một branch định sẵn hoặc có thể là tự động chạy theo một lịch cố định.
Bạn có thể xem qua bài viết của mình về Tổng quan về CI/CD pipelines để tìm hiểu thêm về CI/CD nhé!
Đây là một mô hình mà công ty minh đã apply cho một dự án:
- Khi hoàn thành một feature thì teamlead tạo merge request rồi merge vào bran develop, đúng 5h chiều hàng ngày hệ thống sẽ tự động build, test, quét sonar…. và deploy lên develop eviroment (quá trình này là CD), không trtigger merger code để deploy với branch này vì code được merge vào đây liên tục nếu trigger merger code sẽ dẫn đến việc build liên tục, làm chậm hệ thống.
- Với branch prepro thì sẽ được trigger mỗi lần có sự thay đổi về code sẽ tự động thực hiện các bước như với branch develop.
- Với branch master thì có hơi khách một chúc, Git cũng sẽ tự động trigger và tiến hành các bước build, run unit test, quét sonar…. nhưng không tiến hành deploy (quá trình này chỉ là CI) lên server mà chỉ được deploy khi có confirm từ một người có quyền hoặc deploy bằng tay để đảm bảo quá trình delevery sản phẩm không xảy ra lỗi và đúng với thời gian khách hàng mong muốn.
Giới thiệu về GitHub Actions
Github actions được sinh ra để hỗ trợ việc tự động hóa các tác vụ trong vòng đời của một phần mềm. Git actions hoạt động theo hướng sự kiện, nghĩa là nó sẽ thực hiện một loạt commands đã được định nghĩa sẵn khi có một sự kiện được xảy ra. Ví dụ như, bạn có thể cấu hình để mỗi khi có người tạo một mergers request lên một repository nào đó hệ thống sẽ tự động run commands để run các unit test case của bạn.
Mô hình mô tả cách một git actions có thể tiến hành một công việc bất kì (như trong ví dụ trên là run các unit test case có sẵn). Một sự kiện sẽ tự động kích hoạt workflow đã được định nghĩa sẵn trong một job. Mỗi job sử dụng steps control để kiểm soát acttions. Actions là comands thực hiện một hành động cụ thể nào đó (run các unit test case)
Xem thêm: Sử dụng Git hiệu quả
Các thành phần của một Github Actions
Dưới đây là danh sách nhiều thành phần của GitHub Acttions hoạt động cùng nhau để chạy công việc. Bạn có thể thấy các thành phần này tương tác với nhau như thế nào.
Workflows là một tập các hành động mà bạn thêm và reponsitory của mình để định nghĩa các hành động. các jobs trong workflows có thể được thực thi theo lịch hoặc dựa vào một trigger nào đó. Workflows có thể được định nghĩa để build, test, release, deplpy…. một dự án trên Github. Một workflows được định nghĩa bằng file yml.
Events là một trigger đặc biệt để workflow bắt đầu. ví dụ như, bạn có thể cấu hình để workflow bắt đầu khi có một người nó đó push code hoặc tạo merger request lên branch develop. Bạn có thể sử dụng repository dispatch webhook để trigger một workflow khi một sự kiện bên ngoài xảy ra (Đọc cho vui chứ đoạn này cũng không dùng mấy 😉 ). Các bạn có thể xem danh sách các events có thể dùng để trigger một workflow ở đây.
Jobs là tập hợp các bước thược hiện một công việc của một runner. Mặc định thì các jobs trong một workflow được chạy song song. Bạn cũng có thể cấu hình để các jobs chạy một các tuần tự. Ví dụ trong một workflow có thể có jobs là build, run test case. Nhưng nếu build fails thì test case sẽ không được run.
Steps là một tác vụ độc lập nó có thể là một command trong một jobs. Mỗi steps có thể là một action hoặc một command để thực hiện một hành động nào đó. Mỗi step trong một job thực thi trong cùng một runner, có thể share data từ steps này với step khác.
Actions là một command độc lập khi kết hợp lại tạo thành một steps để tạo ra jobs trong workflow. Actions là đơn vị nhỏ nhất của một workflow là thành phần trực tiếp thực hiện các tác vụ mong muốn.
Runners là một server được cài đặt sẵn GitHub Actions runner application. Bạn có thể sử dụng runner hosted bởi GitHub hoặc bạn có thể tự host cho mình để sử dụng. Một runner luôn sẵn sàng lắng nghe các jobs, run một job tại một thời điểm, report process, logs và trả kết quả về cho GitHub. Với GitHub-hosted runner mỗi job được runs trên một máy ảo hoàn tòan mới (Điều này có nghĩa là mỗi job bạn đều cần có bước setup môi trường từ đầu )
GitHub-hosted runner chạy trên Ubuntu Linux, Microsoft Windows và MacOS. Các bạn có thể đọc thêm thông tin ở “Virtual environments for GitHub-hosted runners.”. Nếu bạn muốn một hệ điều hành khác hoặc một cấu hình phần cứng cụ thể bạn có thể host một Github-hosted runner cho mình, xem thêm thông tin ở “Hosting your own runners.”.
Tạo một workflow với Github actions.
Cách 1: tạo ra file yml sau đó push lên thư mục .github/workflows/ Với cách này đơn giản là chúng ta tạo ra một file yml trong thư mục .github/workflows/ rồi push lên git
Cách 2: tạo một workflow theo các mẫu có sẵn
Bước 1: Vào git responsitory của bạn chọp tab Action
Bước 2: Chọn “Setup this workflow” git sẽ chọn flow default hoặc chọn một mẫu có sẵn trong danh sách git sẽ tạo ra file workflows theo những mẫu có sẵn.
Bước 3: Update file yml theo ý muốn.
Cấu trúc thông thường của một Github actions
Đây là một file yml mình đang sử dụng để cấu hình một git action để tự động install, build và publish source vue native lên expo mỗi khi có một người push code lên branch develop.
1.Khai báo
name: Develop to Expo Pro2
2. Sự kiện – Trigger
on:
push:
branches:
- develop
3. Công việc – Jobs
publish:
name: Install and publish
runs-on: ubuntu-latest
- Setup enviroment
teps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12.x
- uses: expo/expo-github-action@v5
with:
expo-version: 3.x
expo-username: ${{ secrets.EXPO_CLI_USERNAME }}
expo-password: ${{ secrets.EXPO_CLI_PASSWORD }}
- Actions
- run: npm install
- run: expo publish --release-channel=pro2
- uses: unsplash/comment-on-pr@master
env:
GITHUB_TOKEN: ${{ secrets.EXPO_CLI_GIT_TOKEN }}
with:
msg: App is ready for review, you can [see it here](https://expo.io/@bycedric/use-expo?release-channel=pro2.
Setup secrets key
Secrests key để làm gì? có một số thông tin bảo mật các bạn không muốn public cho mọi người (kể cả những member trong dự án) biết: access token, password….. vậy các bạn cần một cơ chế để public một key ra ngoài để run time có thể access vào value được lưu trong setting của git. chúng ta có thể sử dụng Secrets key
Tạo một secrets key
Bước 1: Chuyển đến tab setting
Bước 2: Chọn sheet Secrets: ở đây hiển thị danh sách các secrets key trong responsitory
Bước 3: Click “new repository secret” để tạo một secret key mới: nhập key và value
Bước 4: Xong thì add secret thôi nào
Có một đặt điểm là bạn không thể xem giá trị hiện tại của một secret key để tránh việc người khác có thể có được những thông tin bảo mật của bạn.
Events trigger
Bạn có thể cấu hình cho workflows chạy khi có một sự kiện nào đó xảy ra trên GitHub, theo một lịch có sẵn hoặc cũng có thể là một sự kiện nào đó xảy ra ngoài GitHub.
Cấu hình cho một workflow events
Bạn có thể cấu hình cho một workflow run một hoặc một trong những events được thực hiện thông qua cú pháp on . Xem thêm cú pháp ở “Workflow syntax for GitHub Actions.“.
Syntax của một event trigger
on.<push | pull_request>.<branches | tags>
Ví dụ cấu hình trigger khi actions push, pull request và một branch.
# Triggered một workflow khi có push code lên một branch bất kì
# của responsotiry
on: push
# Triggers một workflow có push code hoặc pull request
on: [push, pull_request]
Hoặc bạn cũng có thể sử dụng nhiều events với các cấu hình khác nhau.
on:
# Trigger một workflow khi push or pull request,
# nhưng chỉ trên main branch
push:
branches:
- main
pull_request:
branches:
- main
# Cũng trigger khi page_build, cũng như release created events
page_build:
release:
types: # Cấu hình này không ảnh hưởng đến events page_build ở trên
- created
on.<push | pull_request>.paths
Ví dụ cấu hình trigger khi actions push, pull request và bỏ qua khi chỉ có action folder docs
.
on:
push:
paths-ignore:
- 'docs/**'
hoặc chỉ trigger khi có action trên các file có đuôi js
on:
push:
paths:
- '**.js'
Các bước xảy để một event có thể trigger một workflow run:
- Một event xảy ra trên reponsotory của bạn và kết quả trả về có một liên kết commit SHA và Git ref.
- Thư mục .github/workflows lưa trữ các yml file để định nghĩa các workflow. Github sẽ đọc những file đó để tham chiết tới commit SHA và Git ref. Các file yml có chứa các events mới được xem xét thực thi.
- Các workflow files có commit SHA và Git ref được triển khai, và một workflow mới sẽ chạy với các trigger khi các trigger trong file yml trùng với sự kiện đang trigger.
Trigger theo Scheduled
Để tạo một schedule chúng ta sử dụng cúp pháp schedule
. Một Scheduled
event cho phép trigger một workflow theo một lịch được định nghĩa sẵn. Một Scheduled
có thể bị delay do hệ thống đang load.
Bạn có thể tạo một scheduled trigger chạy trên UTC time sử dụng POSIX cron syntax. Một workkflow đã được lên lịch sẽ thực thi trên source của commit mới nhất trên default hoặc base branch. Thời gian ngắn nhất để tạo ra một scheduled workflows tối thiểu là 5 phút.
Ví dụ trigger schedule đơn giản, thực hiện run workflows mỗi 15 phút:
on:
schedule:
- cron: '*/15 * * * *' // thực hiện trigger mỗi 15 phút
Cú pháp Cron syntax có 5 fields được phân cách bằng một khoảng trắng, mỗi field đại diện cho một đơn vị thời gian.
┌───────────── phút (0 - 59)
│ ┌───────────── giờ (0 - 23)
│ │ ┌───────────── ngày trong tháng (1 - 31)
│ │ │ ┌───────────── tháng (1 - 12 or JAN-DEC)
│ │ │ │ ┌───────────── ngày trong tuần (0 - 6 or SUN-SAT)
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
* * * * *
Bạn cũng có thể sử dụng các toán tử trong mỗi fields:
Toán tử | Mô tả | Ví dụ |
* | Tất cả các giá trị | * * * * Chạy mỗi phút trong tất cả các ngày. |
, | Giá trị trong danh sách | 2,10 4,5 * * * chạy phút thứ 2, 10, 4, 5 trong mỗi giờ. |
– | Khoảng giá trị | 0 4-6 * * * mỗi 0 phút giờ thức 4 đến 6 của ngày. |
/ | Bước nhảy giá trị | 20/15 * * * * chạy mỗi 15 bắt đầu từ phút thức 20 (phút thứ 20, 35 và 50) mỗi giờ. |
Ngoài ra còn một số cách khác để trigger một workflow nhưng mà mình chưa dùng nên cũng không giám chém, các bạn có thể tham khảo thêm ở đây
Các mẫu job cơ bản
Sau đây là một số mẫu Github action cơ bản mà các bạn có thể sử dụng để tạo một flow hoàn chỉnh, phụ thuộc vào yêu cầu của từng dự án khác nhau.
Ở đây mình chỉ liệt kê một số mẫu cơ bản có những trường hợp các bạn có thể áp cho dự án của mình. Các bạn có thể xem thêm ở đây, chọn ngôn ngữ của dự án và xem các mẫu có sẵn để có thể build một workflow trong nháy mắt.
Xem thêm: Setup Docker Hub và Github Workflow CI/CD pipelines
- Cơ bản nhất là echo ra câu “Hello, world” thần thánh
jobs:
# workflow này chứa một job tên là "build"
build:
# khai báo runner sẽ được chạy
runs-on: ubuntu-latest
# Các bước thể hiện một chuỗi các nhiệm vụ sẽ được thực hiện như một phần của công việc
steps:
# Kiểm tra kho lưu trữ của bạn dưới $ GITHUB_WORKSPACE, để công việc của bạn có thể truy cập nó
- uses: actions/checkout@v2
# Chạy một lệnh đơn bằng cách sử dụng trình bao của người chạy
- name: Run a one-line script
run: echo Hello, world!
- build một ứng dụng Nodejs và push lên Azure Web App
env:
# Khai báo một số biến để sử dụng
AZURE_WEBAPP_NAME: your-app-name # tên ứng dụng
AZURE_WEBAPP_PACKAGE_PATH: '.' # đường dẫn đến ứng dụng
NODE_VERSION: '10.x' # version sử dụng
jobs:
build-and-deploy:
name: Build and Deploy
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.NODE_VERSION }}
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: npm install, build, and test
run: |
# Build and test ứng dụng
# deploy lên Azure Web App.
npm install
npm run build --if-present
npm run test --if-present
- name: 'Deploy to Azure WebApp'
uses: azure/webapps-deploy@v2
with:
app-name: ${{ env.AZURE_WEBAPP_NAME }}
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
- build and push một container image lên Amazon ECR
jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-ecr-repo
IMAGE_TAG: ${{ github.sha }}
run: |
# Build một docker container
# đẩy nó lên ECR để nó có thể được triển khai tới ECS.
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: task-definition.json
container-name: sample-app
image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: sample-app-service
cluster: default
wait-for-service-stability: true
- tải một Ruby version, cài đặt cái gói phụ thuộc và run tests với Rake
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby-version: ['2.6', '2.7', '3.0']
steps:
- uses: actions/checkout@v2
- name: Set up Ruby
# Để tự động nhận các bản sửa lỗi và các phiên bản Ruby mới cho ruby/setup-ruby,
# thay đổi thành (see https://github.com/ruby/setup-ruby#versioning):
# sử dụng: ruby/setup-ruby@v1
uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests
run: bundle exec rake
- Building and testing .NET
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
dotnet-version: ['3.0', '3.1.x', '5.0.x' ]
steps:
- uses: actions/checkout@v2
- name: Setup .NET Core SDK ${{ matrix.dotnet-version }}
uses: actions/[email protected]
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Install dependencies
run: dotnet restore
- name: Build
run: dotnet build --configuration Release --no-restore
- name: Test
run: dotnet test --no-restore --verbosity normal
- Building and testing Python
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# dừng quá trình build nếu có lỗi cú pháp Python hoặc tên không xác định
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero coi tất cả các lỗi là cảnh báo. Trình chỉnh sửa GitHub rộng 127 ký tự
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
Nguồn tham khảo:
- https://docs.github.com/en/actions/learn-github-actions/introduction-to-github-actions
- https://docs.github.com/en/actions/reference/events-that-trigger-workflows
- https://github.com/actions/runner
- https://docs.github.com/en/actions/reference/specifications-for-github-hosted-runners
Một số bài viết liên quan có thể bạn sẽ thích:
- Docker và các kiến thức căn bản
- Docker Compose và những kiến thức cơ bản
- Set up Kubernetes Cluster trên Amazone Web Service
- Set up Kubernetes Cluster trên Google Cloud Platform
- Sử dụng Terraform để provision infratructure trên GCP
- Kubernetes Cluster và Các khái niệm cơ bản
Mọi thắc mắc xin hãy liên hệ
Email: [email protected]
(Nguồn: KhanhVQ-Viblo)