TypeScript設定:さらばYAMLの疲れ
複雑なYAMLファイルを使わず、型安全なTypeScriptコードを使ってCloudflareのネイティブCI/CD Workflowsを設定する方法を詳細に解説。
GitHub Actionsのパイプラインを書いたことがある人なら、いわゆる「YAMLの疲れ(YAML Fatigue)」の苦しみがよく分かるはずです。条件分岐を一つ追加したり、テストを並列化したりするだけで、インデントのスペース調整に苦労し、複数行の文字列の中に無理やりシェルスクリプトを書き、デバッグのためだけに20回もコミットを繰り返すことになります。
Cloudflare of 新しいネイティブCI/CDシステムでは、YAMLは不要になり、TypeScriptで記述できるようになりました。
CI/CDパイプラインの本質はステップバイステップの実行指示であるため、Cloudflareは型安全な TypeScriptコード を使った設定を可能にしました。その具体的な書き方を分かりやすく詳細に解説します。
YAML vs TypeScript#
従来の構成では、パイプラインは静的な設定文字列でした。Cloudflare CI Workflowsでは、パイプライン自体がアクティブなプログラムとして動作します:
graph LR
YAML["📄 静的なYAML<br/>- ループ処理が困難<br/>- ネイティブ関数の不在<br/>- 複雑なシェルスクリプトの埋め込み"]
TS["🦕 TypeScriptコード<br/>- ループやTry/Catchの活用<br/>- 簡単な並列実行の記述<br/>- 充実した型補完機能"]
YAML -->|置き換え| TS
TypeScriptでCIパイプラインを書く#
以下は、TypeScriptで記述されたCI/CDワークフローの具体的な設定例です。
import { CIWorkflow, CiRunnerResult, isCiRunnerFailure } from '@cloudflare/ci';
export class MyProjectCI extends CIWorkflow {
async run(event, step) {
let deps: CiRunnerResult;
try {
// 1. キャッシュ機能付きの依存関係インストール
deps = await ci.runner({
name: 'install',
command: 'bun install --frozen-lockfile',
cache: { inputs: ['package.json', 'bun.lock'] },
});
// 2. テスト群を並列で実行
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. エラー処理と自己修復AIエージェントの呼び出し
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. 並列実行ステップがすべて成功した場合のみデプロイを実行
await deps.runner({
name: 'deploy',
command: 'bun wrangler deploy',
});
}
}typescriptコメント解説#
1. インストールとキャッシュ#
deps = await ci.runner({
name: 'install',
command: 'bun install --frozen-lockfile',
cache: { inputs: ['package.json', 'bun.lock'] },
});typescriptディレクトリの手動キャッシュルールを書く代わりに、ロックファイルを指す cache ブロックを渡すだけです。Cloudflareは自動的に依存関係のサンドボックススナップショットを取得してR2に保存します。ロックファイルが変わっていなければ、次の実行時は一瞬でロードされます!
2. 並列実行のシンプルさ#
await Promise.all([
deps.runner({ name: 'lint', command: 'bun run lint' }),
deps.runner({ name: 'test', command: 'bun run test' }),
...
]);typescriptYAMLで並列処理を行うには、複数のジョブを定義し、依存関係の依存マトリックスを作る必要がありますが、TypeScriptならJavaScript標準の Promise.all() を呼び出すだけです。Cloudflareは各コマンド用に隔離されたサンドボックスを立ち上げ、並行して実行します。
3. 自己修復を行う Try/Catch#
catch (failure) {
if (isCiRunnerFailure(failure)) {
// AIエージェントを呼び出して、自動で修正ブランチを作成・プッシュさせる!
}
}typescriptテストが失敗した際、ただエラーを出して止まるのではなく、catch ブロックが実行エラーをキャッチし、AIエージェント(Workers AIなど)を呼び出します。AIがエラーログを読み取り、コードの修正案を作成して新しいGitブランチに自動プッシュします。
ビルドのトリガー設定 (wrangler.toml)#
リポジトリへのプッシュイベントとこのワークフローを結びつけるには、wrangler.toml ファイルにトリガーの設定を追加します:
{
"triggers": {
"events": [
{
"type": "cf.artifacts.repo.pushed",
"filter": {
"namespace": "CI",
"repoName": "my-app"
},
"target": {
"type": "workflow",
"workflow_name": "ci-workflow"
}
}
]
}
}jsonコードがArtifactsの名前空間にプッシュされるたびに、CloudflareはこのTypeScriptワークフローの新しいインスタンスを自動的に立ち上げます。