Thiết kế ứng dụng Google Apps Script CICD từ Github
Giới thiệu về Google Apps Script
[Phần giới thiệu tạo từ ChatGPT]
Google Apps Script là một nền tảng phát triển mã nguồn miễn phí do Google cung cấp, cho phép người dùng tạo các ứng dụng tùy chỉnh và tự động hóa các tác vụ trong các dịch vụ của Google như Google Sheets, Google Docs, Google Drive, Gmail, và nhiều hơn nữa.
-
Một số đặc điểm chính của Google Apps Script:
- Ngôn ngữ: Google Apps Script sử dụng JavaScript, rất thân thiện cho những người đã quen thuộc với ngôn ngữ này.
- Tích hợp sẵn với dịch vụ Google: Apps Script có các API tích hợp sẵn, giúp dễ dàng truy cập và thao tác với dữ liệu trong các ứng dụng Google Workspace, như tạo email tự động với Gmail, xử lý dữ liệu trong Google Sheets, hoặc quản lý tập tin trong Google Drive.
- Khả năng tự động hóa: Người dùng có thể lên lịch các tác vụ tự động bằng cách sử dụng trình kích hoạt (trigger), chẳng hạn như tự động gửi báo cáo hàng ngày qua email hoặc cập nhật dữ liệu vào Google Sheets hàng tuần.
- Giao diện xây dựng web: Apps Script hỗ trợ xây dựng giao diện người dùng (UI) bằng HTML, CSS và JavaScript. Điều này giúp tạo ra các ứng dụng web đơn giản và tùy chỉnh giao diện người dùng cho các tác vụ phức tạp.
- Triển khai dễ dàng: Google Apps Script cho phép triển khai các dự án thành ứng dụng web, tiện ích bổ sung (add-ons) cho Google Workspace, hoặc API web để tích hợp với các dịch vụ khác.
-
Một số ứng dụng của Google Apps Script:
- Quản lý dữ liệu: Tự động cập nhật dữ liệu giữa Google Sheets, Google Forms và Google Drive.
- Gửi email tự động: Tạo các quy trình gửi email theo điều kiện trong Gmail.
- Xây dựng các tiện ích bổ sung cho Google Workspace: Tạo add-ons giúp mở rộng tính năng của Google Sheets, Google Docs và các ứng dụng khác.
- Tích hợp bên ngoài: Kết nối với các API bên ngoài để tích hợp với các dịch vụ khác, như Slack, Trello, hoặc các ứng dụng CRM.
Tạo một ứng dụng Apps Script
Chúng ta sẽ làm gì?
Tạo một ứng dụng Google Form hỗ trợ quyên góp/mượn/trả sách cho thư viện.
-
Người dùng quyên góp sách nhập thông tin sách vào form. Kết quả được thêm vào danh mục sách trong thư viện. Một email được gửi tới người quyên góp sách nhằm cảm ơn đóng góp, đồng thời thông tin người đóng góp được thêm vào danh sách để vinh danh.
-
Người dùng mượn sách lấy sách từ thư viện, nhập thông tin vào form. Kết quả là số lượng của đầu sách đó trong danh mục giảm đi. Một dòng nhật ký thể hiện thông tin về người mượn, đầu sách, thời gian mượn được ghi vào bảng. Từ thời gian mượn đếm ngược tới khi hết 14 ngày, một email tự động nhắc nhở việc trả sách được gửi cho người mượn.
-
Người dùng trả sách trả sách về thư viện, nhập thông tin vào form. Kết quả số lượng của đầu sách đó trong danh mục tăng lên. Dòng nhật ký thể hiện thông tin mượn sách được cập nhật ngày trả. Một email cảm ơn được gửi tới người vừa trả sách, đính kèm danh mục sách còn trong thư viện để người dùng đó có thể sẵn sàng tra cứu.
Tạo Google Form
Để đáp ứng các yêu cầu được đặt ra tại phần đặt vấn đề, ta cần tạo một Google Form đơn giản. Hình bên minh họa form vừa được tạo
Sau khi đã có thông tin cơ bản về form, tại góc trên bên phải, ta mở trình tạo script để bắt đầu tạo ứng dụng.
Thử những dòng code đơn giản
Trong giao diện appscript, ta nhập vào code của mình và nhấn Run để chạy thử code. Đoạn code mẫu dưới đây nhận vào thông tin được nhập trong form và in nó ra. Form ID chính là dòng chuỗi ký tự nằm trên link của form https://docs.google.com/forms/d/your-google-form-id-in-edit-version/edit
function onFormSubmitTrigger() {
var form = FormApp.openById("your-google-form-id-in-edit-version");
var formResponses = form.getResponses();
var formResponse = formResponses[formResponses.length - 1];
var itemResponses = formResponse.getItemResponses();
for (var j = 0; j < itemResponses.length; j++) {
var itemResponse = itemResponses[j];
console.info(itemResponse.getResponse())
}
}
Kết quả như hình nghĩa là script đã hoạt động
Setup CICD
Tại phần này, ta sử dụng Github Action để trigger hành động push lên branch và chạy runtime. Runtime là script clasp, xác thực với Google và push code lên Script đã chỉ định
Install clasp
-
Install clasp
-
Sau khi cài đặt thành công, tiến hành login vào clasp
-
Một web popup được mở lên, ta login vào bằng tài khoản Google, cho phép tất cả quyền với clasp. Sau khi có thông báo
Logged in! You may close this page
. Ta tắt trình duyệt. Clasp secret được lưu tại /home/your-user/.clasprc.json. Nội dung file có dạng:Ta lưu thông tin này và add vào github Action{"token":{"access_token":"ya29.a0AeDClZDSqUjpogftPSUV2YEbqcmdzm583fr3Rd_JoURVY7fQ0175","refresh_token":"1//0gXg54AF-AkdBCgYIARAAGBASNwF-L9IrB_UcEiO2xoywoMncHEQX31g9X0uKyVTAOMoxVwcgpyNeuBoiCtqz-jB2NPr96QSy0nU","scope":"https://www.googleapis.com/auth/logging.read https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/script.projects https://www.googleapis.com/auth/script.webapp.deploy https://www.googleapis.com/auth/userinfo.email openid https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/service.management https://www.googleapis.com/auth/script.deployments https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/cloud-platform","token_type":"Bearer","id_token":"eyJhbGciOjE3MzAzOTIzMTZ9.i06D7jynHSvjAKRaMucEK3vQYF7aRRHy9H_8zp5uglcnKecMdXbyqL1x334UXx2vggEutNvzAdFUr9M8ec6y9LWcNCJx8l8tHgakMA-0hpp-bp3wBx4Gzac-H-8DSo7wTw3E9XEBDTYZBe1kPqiN0ivVqzfQ6PusaGvsuuY8n0dVvNC559EFkyGfklE_xIxKNJbUBem9NednIfkkfKbuA-eURN16BE86cdO8MBE99pCrdy2w7eYO0s8wd-Xl46OhQKm4TRFz5ZGf06NdkC_SQtHwphurxKCYVuECjon7iVXLpjpKmdHAS6jyYl78qd6bTVloonLA9kl4o_HCjcbOyQ","expiry_date":1730392315187},"oauth2ClientSettings":{"clientId":"1072944n0.apps.googleusercontent.com","clientSecret":"v6V3fKV_zWU7iw1DrpO1rknX","redirectUri":"http://localhost"},"isLocalCreds":false}
Thao tác trên App Script
Để có thể clasp làm việc với appscirpt, source code của chúng ta cần có các file config.
Đầu tiên là appscript.json
, đây là một file cài đặt của project, nó quy định runtime, dependencies... Ta có thể dễ dàng kiểm tra nó bằng cách
-
Trên giao diện Apps Script, tại thanh công cụ bên trái, chọn biểu tượng cài đặt, vào Project Settings.
-
Tại giao diện cài đặt, phần Genral settings, chọn dấu tích vào ô bên trái của lưạ chọn Show "appsscript.json" manifest file in editor
-
Quay trở lại giao diện Editor, ta sẽ thấy file appsscript.json, file có nội dung tương tự phía dưới.
{
"timeZone": "Asia/Ho_Chi_Minh",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"webapp": {
"access": "ANYONE",
"executeAs": "USER_DEPLOYING"
}
}
Thứ hai là file .clasp.json, file này chỉ dấu project nào, script nào bạn muốn thao tác. File này có thể tạo ra bằng các câu lệnh của clasp. Ở đây mình đưa ra file mình đã sử dụng
{
"scriptId": "your-script-id",
"rootDir": ".",
"projectId": "your-project-id",
"fileExtension": ["js","html"]
}
Các thông tin scriptID và projectID có thể lấy tạị giao diện cài đặt. Nếu là script mới, thông số Project Number sẽ không có. Bạn cần tạo một project và change project ID cho script đó.
Ngoài việc hard code project ID và script ID ở code, bạn có thể sử dụng github variables và script để parse thông tin đó vào file .clasp.json. Ở đây mình không sử dụng variables đó.
Có một thông tin cần nữa là Deployment ID. Sau khi deploy script, bạn lưu lại nó để sử dụng sau. Thông tin này lấy được bằng cách
-
Tại giao diện chính của Apps Script, phía trên bên phải, chọn Deploy
-
Tại pop-up deploy, chọn Manage deployments
-
Lựa chọn deployments cần quản lý, copy và lưu lại thông tin Deployment ID
Thao tác trên github
-
Sử dụng Github Action, ta tạo các secrets
- CLASPRC_JSON: Là chuỗi được lấy từ clasp ở trên
- REPO_ACCESS_TOKEN: Là chuỗi access token của tài khoản github
- DEPLOYMENT_ID: đã được nhắc tới ở trên.
-
Project structure như sau
Các file .clasp.json
và appsscript.json
ta đã có ở trên. Các file trong thư mục src
chứa source code của project. File cicd.yml
như dưới đây
name: CI/CD
on:
workflow_dispatch:
push:
branches: ["main"]
schedule:
- cron: "0 1 * * *"
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
apps_script_deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Install clasp
id: install-clasp
run: sudo npm install -g @google/clasp
- name: Write CLASPRC_JSON secret to .clasprc.json file
id: write-clasprc
run: echo "$CLASPRC_JSON_SECRET" > ~/.clasprc.json
env:
CLASPRC_JSON_SECRET: ${{ secrets.CLASPRC_JSON }}
- name: Check clasp login status
id: clasp_login
run: clasp login --status
- name: Save current .clasprc.json contents to CLASPRC_JSON_FILE environment variable
id: save-clasprc
run: |
echo ::add-mask::$(tr -d '\n\r' < ~/.clasprc.json)
echo "CLASPRC_JSON_FILE=$(tr -d '\n\r' < ~/.clasprc.json)" >> $GITHUB_ENV
- name: Save CLASPRC_JSON_FILE environment variable to CLASPRC_JSON repo secret
id: set-clasprc-secret
if: ${{ env.CLASPRC_JSON_FILE != env.CLASPRC_JSON_SECRET }}
uses: hmanzur/[email protected]
env:
CLASPRC_JSON_SECRET: ${{ secrets.CLASPRC_JSON }}
with:
name: "CLASPRC_JSON"
value: ${{ env.CLASPRC_JSON_FILE }}
repository: ${{ github.repository }}
token: ${{ secrets.REPO_ACCESS_TOKEN }}
- name: Checkout repo
id: checkout-repo
if: ${{github.event_name != 'schedule' }}
uses: actions/checkout@v2
- name: set environtment
id: set-env
if: ${{github.event_name != 'schedule' }}
run: rsync -auvh --delete config/.clasp.json config/appsscript.json src/
- name: debug location of directory
if: ${{github.event_name != 'schedule' }}
run: |
pwd
ls -lah
- name: Push script to scripts.google.com
id: clasp-push
if: ${{ github.event_name != 'schedule'}}
run: cd src && clasp push -f
- name: Deploy Script
id: clasp-deploy
if: ${{github.event_name != 'schedule' }}
run: cd src/ && clasp deploy -i "$DEPLOYMENT_ID" -d "$GITHUB_REF"
env:
DEPLOYMENT_ID: ${{ secrets.DEPLOYMENT_ID }}
- name: remove .clasprc.json credential file
run: rm -rf ~/.clasprc.json
Như vậy, sau khi chúng ta push code lên branch main
, clasp sẽ sử dụng REPO_ACCESS_TOKEN để truy cập vào repository, sử dụng CLASPRC_JSON để login vào google, push code lên scriptID được cấu hình sẵn, tạo một deployments mới thay cho DeploymentID cũ.