io khá phức tạp và không dễ sử dụng) - tại vin777

Ai cũng biết tôi chỉ là một lập trình viên frontend nghiệp dư, nhưng vẫn muốn tự tạo ra những công cụ hữu ích cho bản thân. Bạn bè đã giới thiệu tôi sử dụng ant design của Ant Financial - họ nói rằng chỉ cần copy-paste là xong. Tuy nhiên, đối với người mới như tôi thì vẫn hơi khó khăn một chút, nhưng cuối cùng tôi vẫn có thể viết được vài dòng mã.

Vấn đề lớn nhất bây giờ là làm thế nào để triển khai ứng dụng này lên server cá nhân. Ứng dụng được viết bằng ant design thực chất chỉ là một trang HTML duy nhất kèm theo CSS và JavaScript. Ban đầu, tôi build xong rồi dùng scp để upload lên server, cũng đã nghĩ đến rsync nhưng cảm thấy mọi thứ chưa đủ tự động hóa. Vì chưa có kinh nghiệm trong lĩnh vực này nên tôi quyết định tìm hiểu thêm. Tôi đang sử dụng Gogs làm hệ thống quản lý repository riêng, ban đầu tìm hiểu về cách tích hợp với Drone.io để làm CI/CD nhưng sau khi nghiên cứu kỹ hơn thì nhận ra chỉ cần dùng webhook là đủ (PS: drone.io khá phức tạp và không dễ sử dụng).

Để bắt đầu, tôi cần cài đặt webhook trên server. Ban đầu tôi dùng snap để cài đặt nhưng gặp vấn đề khi chạy vì không tìm thấy file hooks.json mà tôi đã b29 club chỉ định. Cuối cùng, tôi kết quả bóng đá hôm nay tải phiên bản mới nhất từ GitHub và đặt vào /usr/local/bin. Nguyên lý hoạt động của webhook rất đơn giản: nó khởi động một dịch vụ HTTP, nhận các yêu cầu POST, phân tích tham số và nếu khớp với cấu hình sẽ thực thi lệnh hoặc script tương ứng.

Cấu hình file hooks.json

Webhook cần hai file chính: hooks.json và script thực thi. File hooks.json là file cấu hình cho dịch vụ webhook, trông giống như sau:

 1[
 2  {
 3    "id": "redeploy-app",
 4    "execute-command": "/opt/scripts/redeploy.sh",
 5    "command-working-directory": "/opt/scripts",
 6    "pass-arguments-to-command": [
 7      {
 8        "source": "payload",
 9        "name": "head_commit.message"
10      },
11      {
12        "source": "payload",
13        "name": "pusher.name"
14      },
15      {
16        "source": "payload",
17        "name": "head_commit.id"
18      }
19    ],
20    "trigger-rule": {
21      "and": [
22        {
23          "match": {
24            "type": "payload-hash-sha1",
25            "secret": "your-github-secret",
26            "parameter": {
27              "source": "header",
28              "name": "X-Hub-Signature"
29            }
30          }
31        },
32        {
33          "match": {
34            "type": "value",
35            "value": "refs/heads/master",
36            "parameter": {
37              "source": "payload",
38              "name": "ref"
39            }
40          }
41        }
42      ]
43    }
44  }
45]

Trong ví dụ trên, id là tên nhận diện của hook này. File hooks.json có cấu trúc là một mảng JSON chứa các object cấu hình. Quan trọng nhất là phần trigger-rule, nơi xác định điều kiện để thực thi lệnh. Ví dụ ở đây kiểm tra xem request có chứa hash mã hóa trong header và branch push phải là master.

Tuy nhiên, khi sử dụng với Gogs, bạn sẽ gặp vấn đề với phương thức mã hóa. Gogs sử dụng SHA256 HMAC để tạo chữ ký và đặt vào header X-Gogs-Signature. Do đó, bạn cần thay đổi kiểu mã hóa trong trigger-rule thành payload-hash-sha256.

Script redeploy.sh

Script redeploy.sh thực hiện việc pull code mới và build lại dự án:

 1#!/bin/bash
 2
 3function cleanup {
 4   echo "Lỗi xảy ra"
 5}
 6
 7trap cleanup ERR
 8
 9commit_message=$1 # head_commit.message
10pusher_name=$2 # pusher.name
11commit_id=$3 # head_commit.id
12
13cd ~/do-react-example-app
14git pull origin master
15yarn && yarn build

Trong thực tế, bạn có thể cần copy thư mục build sang folder mà Nginx quản lý, thường sử dụng rsync hoặc cp. Một vấn đề phổ biến là quyền truy cập thư mục. Với hệ điều hành Ubuntu, người dùng mặc định là ubuntu còn thư mục của Nginx thường là www. Bạn có thể giải quyết bằng cách thêm người dùng vào group phù hợp hoặc cấu hình sudoers để không cần mật khẩu cho một số lệnh nhất định.

Ví dụ về file sudoers:

1myusername ALL = (ALL) ALL
2myusername ALL = (root) NOPASSWD: /path/to/my/program

Thực hành và khắc phục lỗi

Khi chạy webhook thông qua snap, tôi gặp lỗi không tìm thấy file hooks.json. Sau khi chuyển sang sử dụng binary chính thức từ GitHub, mọi thứ hoạt động ổn định hơn. Một lưu ý quan trọng khác là các trường dữ liệu từ payload của Gogs đôi khi không giống với tài liệu mô tả, ví dụ như không có head_commit.message và thay vào đó là mảng. Để debug hiệu quả hơn, bạn có thể thêm "include-command-output-in-response": true vào cấu hình hooks.json để xem kết quả thực thi script.

Hy vọng bài viết này giúp ích cho những ai đang tìm hiểu cách tự động hóa quá trình deploy với Gogs và webhook!