- vừa được xem lúc

Khi Github Actions và CircleCI song kiếm hợp bích thì đỉnh không gì bằng [Phần 2]

0 0 49

Người đăng: linh

Theo Viblo Asia

Cách thức thực hiện

Có thể nói ưu điểm của Github Actions chính là số lượng trigger nhiều.

CircleCI chỉ có 1 trigger là lúc push vào nhánh. Còn Github Actions thì có một lượng trigger không thể đếm xuể.

Việc khởi động CircleCI sẽ gọi API của CircleCI từ phía Github Actions và kích hoạt trigger.

Thông thường, ta sử dụng Webhook để khởi động CircleCI, nhưng lần này sẽ dùng cách call API.

Cho nên, ở setting của repository, hãy cài OFF cho Webhook.

Chỉ cần không check vào ô Active là đã tắt được Webhook.

Cách thức khởi động CircleCI sau khi Reviewer đã thực hiện approve

Dù tôi có nhắc đến việc Github Actions có rất nhiều trigger, nhưng thật ra lại không có trigger giới hạn nào sau khi reviewer approve.

Đến đây có thể các bạn sẽ thốt lên: "Ôi thế thì sao mà được nhỉ?" "Haizzz cũng thế cả mà thôi"

Nhưng xin đừng vội vàng nói như vậy, bởi ta có thể thực hiện được chỉ cần kết hợp các trigger lại với nhau!

(Tham khảo chi tiết ở link này, ghi chú nhỏ là không phải tiếng Việt https://qiita.com/dosukoi_android/items/a3464548b3aa293c62dd)

Nói một cách đơn giản, bạn chỉ cần call API của CircleCI bằng cách: trigger = submit review, và trạng thái ('STATE') của review get được thông qua webhook của github là 'APPROVED' <= vậy là đã OK rồi.

Cách thức khởi động CircleCI tại thời điểm merge

Lại phải nói, do nó không có trigger vào thời điểm merge. Vậy ta phải làm sao? Đương nhiên là lại kết hợp các trigger!

(Chi tiết có thể đọc bài viết ở link sau, bài gốc không có vietsub nhé https://qiita.com/dosukoi_android/items/e41f5c2c2a7120685af8)

Nói một cách đơn giản, ta sẽ dùng combo trigger: sau khi được close; và flag đã được merge chưa, get được thông qua webhook => nếu đã được merge rồi, vậy thì API của CircleCI sẽ được gọi.

Vấn đề

Hẳn những ai từng sử dụng CircleCI đều hiểu, nó không thể khởi chạy từng job. (tôi cho là như vậy, cũng không chắc lắm, nếu điều này sai thì xin lỗi nhé, vì tôi nghĩ rằng chắc chắn không thể làm được vậy lúc call API)

Cho nên chỉ với vấn đề này thôi, thì sẽ nảy sinh câu chuyện là : lúc reviewer approve => merge => job bị khởi chạy.

Điều này không ổn cho lắm. Dù chỉ muốn test một chút thôi nhưng lại thành ra deploy... thế là muốn ngất luôn rùi.

Cách giải quyết

Có thể giải quyết vấn đề trên bằng cách sử dụng parameters có trong CircleCI v2.1.

Lúc call API của CircleCI, sẽ truyền đi parameters và như vậy có thể phán đoạn được job nào sẽ được chạy.

https://circleci.com/docs/api/v2/#operation/triggerPipeline

Thí dụ một chút nhé!

Lúc call API

curl -X POST -H "Content-Type:application/json" -d '{"branch": "master", "parameters": {"task": "build"}}' \
https://circleci.com/api/v2/project/github/username(Organizationname)/repositoryname/pipeline

Bên CircleCI

version: 2.1 parameters: task: type: enum enum: ["build", "test", "deploy"] default: "build" orbs: android: circleci/_@.com job: build: executor: android/android steps: Viết cái muốn làm vào đây test: Giống với build deploy: Như trên workflows: version: 2.1 build: # đây là phần chính nhé! when: equal: [ build, << pipeline.parameters.task >> ] jobs: - build test: when: equal: [ test, << pipeline.parameters.task >> ] jobs: - test deploy: when: equal: [ deploy, << pipeline.parameters.task >> ] jobs: - deploy

Kiểu như vậy là ta sẽ truyền được parameters "enum" => tuỳ vào giá trị được truyền đi thì sẽ quyết định xem job nào sẽ được chạy!

(tác giả bài báo cực kỳ mê "enum")

PHẦN KẾT ~~~~~~

Nhắc lại !!!!

Github Actions

  • Build
  • Lint check

CircleCI

  • Test
  • Notification to Slack
  • Automatic merge
  • Deploy

Thử với Android commands như dưới nhé~~~

BUILD


name: Build on: pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/_@.com - name: set up JDK 1.8 uses: actions/_@.com with: java-version: 1.8 - name: Build with Gradle run: ./gradlew compileDebugSources

Rất đơn giản! Thuần tuý chỉ cần viết xử lý của Github Actions là OK!

Lint check

name: Build on: pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/_@.com - name: set up JDK 1.8 uses: actions/_@.com with: java-version: 1.8 - name: Build with Gradle run: ./gradlew lintDebug

(Thực ra nó là multi-module và tác giả bài viết sử dụng Danger để hiển thị kết quả ở comment của Github)

TEST

Từ đây trở đi là bước chính nhé! Tác giả đăng toàn bộ workflow của Github Actions trước và đăng workflow của CircleCI ở cuối (Vì CircleCI đang quản lý tập trung ở config.yml)

Đây là chạy test sau khi reviewer thực hiện approve nhé.

Github Actions

name: UnitTest on: pull_request_review: types: [ submitted ] jobs: test: # Handling if approved here & handling by branch name if using Git-flow if: ${{ github.event.review.state == 'approved' && github.event.pull_request.base.ref == 'master' }} runs-on: ubuntu-latest steps: - uses: actions/_@.com - name: Call CircleCI API # Call CircleCI's API here run: | curl \ -X POST \ -H "Content-Type: application/json" \ -d '{ "branch": "master", "parameters": { "build_variant": "dev", "task": "test", "pull_request_title": "${{ github.event.pull_request.title }}", "pull_request_html_url": "${{ github.event.pull_request.html_url }}", "pull_request_user": "${{ github.event.pull_request.user.login }}", "pull_request_url": "${{ github.event.pull_request.url }}", "pull_request_sha": "${{ github.event.pull_request.head.sha }}"}}' \ https://circleci.com/api/v2/project/github/${{ github.event.repository.full_name }}/pipeline

DEPLOY

Github Actions

name: Deploy on: pull_request: types: [closed] branches: [master] jobs: build: # Only when PR is closed and merged is true → That is, it starts only when merged if: github.event.pull_request.merged == true runs-on: ubuntu-18.04 steps: - uses: actions/_@.com - name: Call CircleCI API run: | curl \ -X POST \ -H "Content-Type: application/json" \ -H "Circle-Token: ${{ secrets.CIRCLE_TOKEN }}" \ -d '{ "branch": "master", "parameters": { "build_variant": "dev", "task": "deploy", "pull_request_title": "${{ github.event.pull_request.title }}" } }' \ https://circleci.com/api/v2/project/github/${{ github.event.repository.full_name }}/pipeline

CircleCI

version: 2.1 parameters: # Handling which job to start task: type: enum enum: ["deploy", "test"] default: "deploy" # Can be changed for each environment build_variant: type: enum enum: ["dev", "stg", "production"] default: "dev" # From here on is used for Slack notifications pull_request_title: type: string default: "" pull_request_html_url: type: string default: "" pull_request_url: type: string default: "" pull_request_user: type: string default: "" pull_request_sha: type: string default: "" executors: android: docker: - image: circleci/android:api-30 environment: JVM_OPTS: -Xmx1536m GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx1536m -XX:+HeapDumpOnOutOfMemoryError" -Dorg.gradle.configureondemand=true -Dkotlin.compiler.execution.strategy=in-process -Dkotlin.incremental=false' orbs: android: circleci/_@.com jobs: deploy: executor: android steps: - checkout - run: # Create aab file name: Build with Gradle command: | ENV=(<< pipeline.parameters.build_variant >>) ENV_UPPER_CASE=${ENV[@]~} ./gradlew ":navigation:phone:bundle${ENV_UPPER_CASE}Release" - run: # Call DeployGate's API name: Distribute App command: | curl \ -H "Authorization: token $DEPLOY_GATE_API_KEY" \ -F "_@.com/phone/build/outputs/bundle/<< pipeline.parameters.build_variant >>Release/phone-<< pipeline.parameters.build_variant >>-release.aab" \ -F "message=<< pipeline.parameters.pull_request_title >>" \ -v "https://deploygate.com/api/users/$DEPLOY_GATE_USER_NAME/apps" test: executor: android steps: - checkout - run: name: Unit Test command: | ENV=(<< pipeline.parameters.build_variant >>) ENV_UPPER_CASE=${ENV[@]~} ./gradlew "test${ENV_UPPER_CASE}DebugUnitTest" - run: # Slack notification on failure when: on_fail name: Unit Test Failure Notification command: | curl \ -X POST \ -H "Content-Type: application/json" \ -d '{"attachments": [{"color": "#D73A49", "title": "<< pipeline.parameters.pull_request_title >>", "title_link": "<< pipeline.parameters.pull_request_html_url >>", "text": "Failure Unit Test", "author_name": "<< pipeline.parameters.pull_request_user >>"}]}' \ $SLACK_WEBHOOK auto_merge: executor: android steps: - run: name: Wait For Status Check command: sleep 5s - run: # Call MergeAPI of Github name: Auto Merge command: | curl \ -X PUT \ -H "Authorization: token $PERSONAL_ACCESSTOKEN" \ -H "Content-Type: application/json" \ -d '{"sha": "<< pipeline.parameters.pull_request_sha >>", "merged": "true", "message": "Pull Request successfully merged"}' \ "<< pipeline.parameters.pull_request_url >>/merge" workflows: version: 2.1 build_and_deploy: # Launch this job if the parameter (when calling the API)) is 'deploy' when: equal: [deploy, << pipeline.parameters.task >>] jobs: - deploy: name: Deploy test: # Launch this job if the parameter (when calling the API) is 'test' when: equal: [test, << pipeline.parameters.task >>] jobs: - test - auto_merge: name: Auto Merge requires: - test # When the 'test' job is finished, start the 'auto_merge' job

(Gần như là AUTOMATIC từ bước build cho đến deploy, việc duy nhất cần chạy cơm đó là lúc REVIEW Miễn là không có conflicts, thì có thể tự động hoá mọi thứ từ test, merge cho đến deploy đó!)

Hết rùi ạ, thanks for reading~~

Bình luận

Bài viết tương tự

- vừa được xem lúc

Cấu hình CI/CD với Github (phần 2): Trigger một work flow

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.

0 0 80

- vừa được xem lúc

Khi Github Actions và CircleCI song kiếm hợp bích thì đỉnh không gì bằng [Phần 1]

(Sau đây xin được dịch lại bài báo nọ, ngôi xưng là "Chế"). .

0 0 48

- vừa được xem lúc

Cấu hình CI/CD với Github (phần 4): 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. .

0 1 130

- vừa được xem lúc

Cách tạo một trang blog cá nhân miễn phí dành cho dev

Vào một ngày đẹp trời, bỗng dưng mình nảy ra ý định làm một trang blog cá nhân thay vì viết Blog trên các nền tảng có sẵn. .

0 0 42

- vừa được xem lúc

Cài đặt đơn giản automating publishing Flutter app lên Google Play bằng Github Actions

Introduction. Mỗi developer hay gặp phải các công việc lặp đi lặp lại gây ra sự nhàm chán.

0 0 45

- vừa được xem lúc

Deploy Github Self Host Runner với Docker Compose dùng Replicated Mode

Hello các bạn lại là mình đây . Cả tháng rồi mới lại được ngồi viết bài, mỗi ngày nhìn thấy blog mốc meo, muốn viết 1 cái gì đó nhưng toàn hết ngày, trong khi vẫn muốn được viết rất nhiều cùng các bạn

0 0 26