Cấu hình bằng TypeScript: Tạm biệt cơn ác mộng YAML
Cái nhìn chi tiết về việc cấu hình các luồng CI/CD nguyên bản của Cloudflare bằng mã nguồn TypeScript có kiểm tra kiểu dữ liệu thay vì các tệp YAML phức tạp.
Nếu em đã từng viết một quy trình chạy GitHub Actions, em chắc chắn đã trải nghiệm cảm giác mệt mỏi mang tên “YAML Fatigue”. Khi muốn thêm một bước điều kiện đơn giản hoặc chạy song song các bài test, em phải vật lộn với từng khoảng trống thụt lề, viết mã bash shell lồng trong chuỗi văn bản dài, và cam kết (commit) tới 20 lần chỉ để thử nghiệm sửa lỗi.
Với hệ thống CI/CD nguyên bản mới của Cloudflare, hãy quên tệp YAML đi. Chúng ta sẽ dùng TypeScript.
Bởi vì một đường ống CI/CD về bản chất là một tập hợp các hướng dẫn từng bước, Cloudflare cho phép em cấu hình toàn bộ quy trình bằng mã nguồn TypeScript an toàn. Dưới đây là bài viết chi tiết, dễ hiểu hướng dẫn cách thiết lập cấu hình này.
So sánh YAML và TypeScript#
Trong các thiết lập truyền thống, đường ống CI/CD chỉ là các chuỗi cấu hình tĩnh. Trong Cloudflare CI Workflows, chúng là các chương trình thực thụ hoạt động linh hoạt:
graph LR
YAML["📄 Tệp YAML tĩnh<br/>- Không hỗ trợ vòng lặp<br/>- Không có hàm nguyên bản<br/>- Lồng mã bash phức tạp"]
TS["🦕 Mã nguồn TypeScript<br/>- Dùng vòng lặp & Try/Catch<br/>- Chạy song song dễ dàng<br/>- Đầy đủ autocomplete tự gợi ý"]
YAML -->|Thay thế bởi| TS
Viết Quy Trình CI Bằng TypeScript#
Dưới đây là một ví dụ đầy đủ và chi tiết về quy trình CI/CD được viết bằng TypeScript.
import { CIWorkflow, CiRunnerResult, isCiRunnerFailure } from '@cloudflare/ci';
export class MyProjectCI extends CIWorkflow {
async run(event, step) {
let deps: CiRunnerResult;
try {
// 1. Cài đặt các thư viện phụ thuộc kèm cơ chế bộ nhớ đệm (caching)
deps = await ci.runner({
name: 'install',
command: 'bun install --frozen-lockfile',
cache: { inputs: ['package.json', 'bun.lock'] },
});
// 2. Chạy song song các tiến trình kiểm thử
await Promise.all([
deps.runner({ name: 'lint', command: 'bun run lint' }),
deps.runner({ name: 'test', command: 'bun run test' }),
deps.runner({ name: 'typecheck', command: 'bun run typecheck' }),
deps.runner({ name: 'build', command: 'bun run build' }),
]);
} catch (failure) {
// 3. Xử lý lỗi và gọi AI Agent tự sửa lỗi
if (isCiRunnerFailure(failure)) {
const healed = await step.do('heal', async () => {
const healer = await getAgentByName(this.env.HEALER, event.instanceId);
return await healer.heal({ failure, event });
});
throw new CiRunFailedWithFix(failure, healed);
}
throw failure;
}
// 4. Quá trình triển khai chỉ chạy khi tất cả các bước trước đó thành công
await deps.runner({
name: 'deploy',
command: 'bun wrangler deploy',
});
}
}typescriptGiải Thích Chi Tiết Từng Phần Mã Nguồn#
1. Cài Đặt & Lưu Bộ Nhớ Đệm#
deps = await ci.runner({
name: 'install',
command: 'bun install --frozen-lockfile',
cache: { inputs: ['package.json', 'bun.lock'] },
});typescriptThay vì phải lưu trữ thư mục thủ công một cách phức tạp, em chỉ cần truyền một khối cache trỏ đến tệp khóa (lockfile) của mình. Cloudflare sẽ tự động chụp ảnh môi trường hộp cát (sandbox snapshot) lưu vào R2. Nếu tệp khóa không đổi, lần chạy sau sẽ được tải ngay tức thì!
2. Chạy Song Song Cực Nhanh#
await Promise.all([
deps.runner({ name: 'lint', command: 'bun run lint' }),
deps.runner({ name: 'test', command: 'bun run test' }),
...
]);typescriptTrong YAML, chạy song song yêu cầu định nghĩa các công việc (jobs) phức tạp và thiết lập ma trận quy tắc. Trong TypeScript, em chỉ cần dùng lệnh Promise.all() tiêu chuẩn của JavaScript. Cloudflare sẽ tự khởi tạo các hộp cát cô lập cho mỗi dòng lệnh để chạy song song cùng lúc.
3. Tự Sửa Lỗi Với Try/Catch#
catch (failure) {
if (isCiRunnerFailure(failure)) {
// Kích hoạt LLM Agent để tự sửa lỗi và gửi commit mới!
}
}typescriptNếu một bài kiểm thử bị lỗi, thay vì chỉ dừng chương trình và gửi thông báo lỗi, khối catch sẽ bắt lỗi, khởi chạy một AI agent (ví dụ dùng Workers AI), đọc log lỗi, tự viết bản sửa lỗi và tự động đẩy lên một nhánh git mới cho em duyệt.
Kích Hoạt Tiến Trình Build (wrangler.toml)#
Để kết nối các sự kiện đẩy mã nguồn git (push events) với workflow này, em cấu hình liên kết trong tệp wrangler.toml:
{
"triggers": {
"events": [
{
"type": "cf.artifacts.repo.pushed",
"filter": {
"namespace": "CI",
"repoName": "my-app"
},
"target": {
"type": "workflow",
"workflow_name": "ci-workflow"
}
}
]
}
}jsonMỗi khi mã nguồn được đẩy lên không gian tên Artifacts của em, Cloudflare sẽ tự khởi động một phiên làm việc mới của kịch bản TypeScript này.