
2026/04/23 1:09
【Show HN】ブルコリ:クラウド上で動作するワンショットコーディングエージェント
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
Broccoli は、Claude や Codex などの AI モデルを用いて Linear チケットを GitHub プルリクエストへ変換し、サーバーレスアーキテクチャにより独自の Google Cloud Platform (GCP) 上でソフトウェア開発ライフサイクルを自動化します。システムは Postgres データベースを共有する 2 つの明確なワークロードを採用しています:
broccoli-oss-service が Webフックと重複排除を管理し、broccoli-oss-runner が自動化タスクを実行します。デプロイには、請求機能付き GCP プロジェクト、認証された gcloud、Python 3.12 以降、Anthropic、OpenAI、GitHub、Linear 用の API キーといった特定の要件が必要です。セットアッププロセスには、GitHub App の作成、専用 Linear ボットユーザーの指定、これら認証情報を含む Google Secret Manager の設定、サービスをデプロイし安全な Webフック URL を生成するためのバースクriptの実行が含まれます。稼働すると、Broccoli はラベルやサイズ見積もりに基づいて問題をインテリジェントにルーティングし(小規模タスクには専門的な AI スキルを選択)、開発者は jobs や webhook_deliveries などの内部テーブル上の SQL クエリを通じて完全な可視性を維持できます。本プロジェクトは MIT ライセンスで公開されており、アーキテクチャやジョブ契約に関するドキュメントもオープンに提供されています。
- 欠けている要素(ある場合): なし。
- 推測/飛躍(ある場合): なし。
- 改善されたサマリー(必要な場合;なければ元のままを繰り返す): [上記を参照]
本文
エンジニアリングのループを支援する AI チームメイトです。Broccoli は Linear のチケットをレビュー可能な PR に変換し、Claude と Codex を使用して、あなたの Google Cloud プロジェクト上で動作します。
Broccoli を選ぶ理由
- 🎯 Linear チケット → 審査可能な PR。 イシューを Broccoli ボットに割り当てれば、寝ている間にボットが計画を立て、実装を行い、プルリクエストを作成してくれます。
- 🔒 あなたのインフラ。あなたのキー。あなたのデータ。 Postgres に対してデプロイされた GCP プロジェクト上で動作します。サードパーティによるコントロールプレーンはなく、テナNCY を脱出してデータを流出することはありません。
- 🧱 リリース日からプロダクショングレード。 サーブレスな Cloud Run + Secret Manager + ウェブフックの重複防止 + 永続的なジョブ状態管理を採用。これはおもちゃではありません。
- 🧩 プロンプトはすべてあなたがお持ち。 当社の見解を示すプロンプトテンプレートから始めて、コードと同期してフォークし、調整し、バージョン管理できます。
- ⚡ すべての PR に対する AI コードレビュー。 Claude と Codex は差分を読み取り、実行可能なコメントを残し、求められた際は修正コミットをプッシュします。
- 🛠️ 約 30 分以内でのデプロイ。 ブートストラップスクリプト一つ、設定ファイル一つ、ウェブフック二つでリリース準備完了。
コーディングエージェントと共に使用法
以下のプロンプトを好みのコーディングエージェント(例:codex cli)に貼り付けてください:
このリポジトリを Google Cloud プロジェクトにデプロイしてください。 GitHub リポジトリの URL だけを与えられた場合は、まずリポジトリをクローンしてください。すでにローカルでリポジトリを開いている場合は、既存のチェックアウトから作業を進めてください。 このリポジトリのデプロイ指示書、スクリプト、および`.agents/skills/broccoli-oss-gcp-deploy/SKILL.md` を使用してください。これはコードベースを検証するだけの依頼ではなく、アプリをデプロイするための依頼として処理してください。 前提条件がまだ満たされていないと仮定しないでください。発見フェーズでは、以下のチェックポイントを一つずつ説明し、各項目について私からの回答を確認してから次の項目に進んでください。README の該当セクションが存在する場合は、再説明するのではなくそのページを案内してください。 1. GCP プロジェクトおよび請求権限。Google Cloud プロジェクトがあり、かつbillingが適用された状態で、`gcloud` がそのアカウントにログイン済みかどうか確認してください。もしなければ、https://console.cloud.google.com/cloud-resource-manager でプロジェクトを作成し、https://console.cloud.google.com/billing/projects で billing を適用するための手順を案内するか、デプロイスキルがプロジェクト作成を代行してくれる旨を提示してください。Project ID を記録してください。 2. GitHub App。Broccoli に必要な権限(Contents: リード/ライト、Pull requests: リード/ライト、Issues: リード/ライト、Metadata: リードのみ)を持つ GitHub App を作成済みかどうか確認してください。なければ、`README.md -> デプロイを GCP で実行する -> 1. GitHub App を作成する` のステップごとに案内してください。App ID の数値と、プライベートキープ PEM ファイルをローカルにダウンロードして記録させてください。現時点ではプレースホルダーのホームぺージ/Webフック URL でも構いません;ブートストラップで実際の URL が出力されます。 3. Linear ボットユーザーおよび API キー。**重要:** Linear API キーは、専用の Linear ボットユーザーに属している必要があります。個人のアカウントからのキーを使用すると、「ボットに割り当てられたイシューがトリガーになる」というフローが静かに失敗します。すでに専用のボットユーザーが存在するかどうか確認してください。なければ、`README.md -> 2. Linear ボットユーザーを指定する`: Linear ユーザーを作成または指定し、Broccoli を介して問題がルーターされるすべてのチームに追加し、そのボットユーザーとしてログインする(または管理者がそのユーザーに変更する)ことで、該当ユーザーの設定ページから API キーを生成してください。キーが使用可能であるとして受け入れる前に、それが私の個人のアカウントからのものではなく、ボットユーザーからのものかについて明確に確認してください。ボットユーザー ID を記録してください。 4. OpenAI および Anthropic API キー。各アカウントで請求権限付きのアクティブな API キーが存在するかどうか確認してください。なければ、OpenAI および Anthropic の API キーページに送ってもらい、作成を行ってください。 5. Linear ウェブフック。これは後から行われ、ブートストラップがサービス URL を出力した後で設定されます。現時点では、サービス URL がある場合、`${Service URL}/webhooks/linear` への Linear ウェブフックを追加し、自動生成された `broccoli-oss-linear-webhook-secret` を使用してイシューおよびイシューラベルイベントを購読する必要がある旨をお伝えください。このステップについては現時点では何も行う必要はありません。 6. Secret Manager の population 。ターゲットプロジェクトが存在すれば、オペレーター管理の 4 つのシークレット(`broccoli-oss-github-app-private-key-pem`、`broccoli-oss-linear-api-key`、`broccoli-oss-openai-api-key`、`broccoli-oss-anthropic-api-key`)ごとに、ターゲットプロジェクト向けの正確な Secret Manager コンソール URL を提示し、各シークレットに `latest` バージョンが存在することの確認を受け取るまで一時停止します。ブートストラップ後に自動生成されたウェブフックおよびデータベースパスワードのシークレットはあなたが入手するものなので、それらには触れません。 上記チェックポイント後のワークフロー: - 変異を伴わない発見フェーズを実行し、`gcloud`認証、請求権限、組織またはプロジェクト権限、または必要なローカルツールなどの欠落で早期に失敗します。 - ターゲット GCP プロジェクトが存在しない場合は、まず作成または準備します。 - クラウド変更を行う前に、解決されたデプロイ計画および不足している非シークレット入力を表示します。 - シークレットをチャットに貼り付けることは決して行いません。必要なシークレットが不足している場合、ターゲットプロジェクトで population する必要があるシークレット名の正確な一覧を示し、存在が確認されるまで一時停止します。 - 推測よりも、リポジトリの既存のスクリプト、文書化されたデフォルト、およびデプロイ後のチェックを優先します。 - デフォルトでは Cloud Build パスをローカルの Docker よりも使用します。 - デプロイ後、安全に実行できる検証手順を継続し、サービス URL、残りの手動セットアップ(チェックポイント 5 の Linear ウェブフックを含む)、およびスモークテストの結果を報告します。 これはエージェントがデプロイを主導する際に最も高速なパスです。代わりに手動のステップバイステップのパスを使用したい場合は、以下のガイドを使用してください。それはプロジェクト作成から始まり、手動セットアップが行われる場所を正確に示しています。
目次
アークテクチャの概要
Broccoli は共有 Postgres 上で動作する 2 つの Cloud Run ワークロードとして稼働します:
| コンポーネント | ロール |
|---|---|
| GitHub と Linear のウェブフックを受信し、署名を検証し、配信を重複防止し、ジョブレコードを作成する FastAPI サービス。 |
| vendored プロンプトテンプレートに対して codex および claude CLI を使用して自動化を実行する Cloud Run ジョブ。 |
| Postgres | ジョブ、ウェブフック配信、PR ステート、Linear イシューステート、およびリポジトリ構成の永続的な状態。 |
| Secret Manager | GitHub App プライベートキー、ウェブフックシークレット、LLM API キー、データベース URL を保持します。 |
詳細な設計については ARCHITECTURE.md を参照し、ウェブフックおよび状態モデルの契約については JOB-CONTRACT.md を参照してください。
前提条件
- 新しいプロジェクトを作成して billing を適用するか、既存のプロジェクトを管理できる Google Cloud アカウントが必要です。
- その Google Cloud アカウントに認証された
です。最終的なプロジェクト ID を事前に知る必要はありません。gcloud - GitHub、Linear、および GCP コンソールへのブラウザアクセスが必要です。いくつかの最初のセットアップ手順は意図的に手動で行う必要がありますが、これに必要な値はこれらの製品内にあり、チャットに貼り付けるべきではありません。
- ローカルでの Docker の使用を意図する場合のみ
付きの Docker が必要です(デフォルトの Cloud Build パスの代わりに画像をローカルでビルドしたい場合)。buildx - オペレーターツール(マイグレーション、シード、プリフライト)のために Python 3.12+ および uv が必要です。
- Anthropic API キーおよび OpenAI(または Codex)API キー、またはそれらの作成能力が必要です。
GCP でのデプロイ方法
以下の手順は初回のオペレーター向けに書かれています。ゼロから始まり、値の源泉を説明し、セキュリティ上の理由から手動で行う必要があるステップを指摘します。
0. GCP プロジェクトの作成または選択
Broccoli シークレットを追加するか Cloud Run サービスをデプロイするには、Google Cloud プロジェクトが必要です。
すでに使用するプロジェクトがある場合:
- GCP コンソールでプロジェクトを開きます。
- プロジェクト ID を記録してください。これ以降の手順で使用されます。
- そのプロジェクトに billing が適用されていることを確認します。
まだプロジェクトがない場合:
- Google Cloud の「リソース管理」ページを開きます:https://console.cloud.google.com/cloud-resource-manager
- プロジェクトを作成するか、
スキルを使用してプロジェクトを作成してもらいます。broccoli-oss-gcp-deploy - billing プロジェクトページで billing を適用します:https://console.cloud.google.com/billing/projects
- 新しいプロジェクト ID を記録してください。
注記:Codex デプロイスキルを使用する場合、そのスキルはプロジェクトの作成、billing の適用、必要な API の有効化、および Secret Manager シークレットコンテナの作成を代行できます。これは初回オペレーターにとって最も簡単なパスであり、シークレットを追加する前に実際のプロジェクトをクリックできるためです。
1. GitHub App を作成する
GitHub App(PAT ではありません)を使用することで、Broccoli がスコープ付きインストールトークンを発行できます。
リポジトリ権限:
- Contents: リード/ライト
- Pull requests: リード/ライト
- Issues: リード/ライト
- Metadata: リードのみ
イベントの購読: プルリクエストレビュー。
現時点では、ホームぺージ URL および Webフック URL をプレースホルダーに設定してください。実際のサービス URL が出力されるステップ 6 で更新します。
App ID とプライベートキープ PEM をダウンロードして記録してください。
- GitHub App ID: GitHub アプリに割り当てられた数値識別子です。
はこれをサービスおよびランナーに渡し、インストールトークンを発行するために使用します。deploy/bootstrap.sh - GitHub App プライベートキー PEM: GitHub アプリ設定ページで生成するプライベートキーファイルです。Broccoli はこれを App ID と組み合わせて、アプリとして GitHub に認証するために使用します。PEM ファイルはローカルに保持してください。チャットには貼り付けてくださいません。
2. Linear ボットユーザーを指定する
イシューが特定の Linear ユーザーに割り当てられた際に Broccoli がトリガーされます。
- Broccoli ボットとして機能する専用の Linear ユーザーを作成または指定します。
- そのユーザーには、Broccoli を介してルーターされるすべてのチームへのアクセス権を与えます。
- 読み込み、コメント、ラベルを読み取るために、そのチーム用にスコープされた Linear API キーを生成します(トークンでも可)。
- ボットユーザー ID を記録してください。ステップ 8 でグローバル構成にシードされます。
3. 適切なプロジェクトで Secret Manager を開く
GCP を初めて使用する場合、これは通常混乱を引き起こすステップです:シークレットはあなたのデプロイプロジェクト内の Google Cloud Secret Manager に格納されます。
- Secret Manager を開きます:https://console.cloud.google.com/security/secret-manager
- ページの上部にあるプロジェクトセレクターを使用して、Broccoli デプロイプロジェクトに変更します。
- 選択されたプロジェクト ID がステップ 0 で記録したものと同じであることを確認します。
注記:Codex デプロイスキルでプロジェクトを準備した場合、一部またはすべてのシークレットコンテナが既に存在する可能性があります。これは問題ありません。既存のシークレットを開き、「新しいバージョンを追加」をクリックすればよいでしょう。
4. 必要なシークレット値を入力する
これらの値を手動で入力する必要があります。これらは GitHub、Linear、OpenAI、および Anthropic アカウントからきており、デプロイヘルパーがあなたの代わりに安全に読み取ることはできないからです。シークレット値をチャットに貼り付けてくださいません。GCP コンソールまたは独自のターミナルを通じて Secret Manager に追加してください。
以下の各シークレットについて:
- Secret Manager で「シークレットを作成」をクリックするか、同じ名前の既存のシークレットを開きます。
- 正確なシークレット名を使用します。
- 値を貼り付けるか、ファイルの内容をアップロードします。
- 保存し、シークレットに
バージョンが存在することを確認します。latest
ブートストラップ前の必要事項:
| シークレット | 値の元 | 対応策 |
|---|---|---|
| ステップ 1 で GitHub アプリ設定からダウンロードした PEM ファイル | 完全な PEM 内容をシークレット値として貼り付ける |
| ステップ 2 の Linear ボットユーザー用の Linear API キー | API キーをシークレット値として貼り付ける |
| OpenAI API キーページ | API キーをシークレット値として貼り付ける |
| Anthropic API キーページ | API キーをシークレット値として貼り付ける |
この README の生シェルパスに従っている場合、手動で作成するオプション:
| シークレット | 使用目的 | 取得または生成方法 |
|---|---|---|
| broccoli_oss PostgreSQL ユーザーのパスワード;Cloud SQL デプロイ用の broccoli-oss-database-url を導出するため | ローカルでランダムな値を生成、例: |
| GitHub が Broccoli へのウェブフックリクエストに署名するために使用する共有シークレット | ローカルでランダムな値を生成、例:、後に GitHub アプリのウェブフックシークレットフィールドに貼り付ける |
| Linear が Broccoli へのウェブフックリクエストに署名するために使用する共有シークレット | ローカルでランダムな値を生成、例:、後に Linear ウェブフック設定に貼り付ける |
注記:broccoli-oss-gcp-deploy ヘルパーを使用している場合、プロジェクトが存在した後、
、broccoli-oss-db-password
、および broccoli-oss-gh-webhook-secret
を自動生成できます。それでも、上記の 4 つのオペレーター管理シークレットはあなたが提供する必要があります。broccoli-oss-linear-webhook-secret
デフォルトの Cloud SQL パスの場合:
を事前にpopulation する必要はありません。broccoli-oss-database-url
はそれらを導出し、そのシークレットを代わりに書き込みます。deploy/bootstrap.sh
は必要です。Cloud SQL データベースユーザーのパスワードであり、ランダムで高エントリの文字列であるべきです。broccoli-oss-db-password
**ローカル開発またはカスタムデプロイの場合:**ランナーは
OPENAI_API_KEY の代わりに CODEX_API_KEY を受け付けます。
5. Cloud Build で画像をビルドしてプッシュする
cd path/to/this-repo export GCP_PROJECT_ID=your-project export GCP_REGION=us-central1 export TAG=v0.1.0 export PUSH=1 ./deploy/build-and-push.sh
デフォルトでは、
deploy/build-and-push.sh は Google Cloud Build を使用します。つまり、Google が GCP プロジェクト内で画像をビルドおよびプッシュするため、推奨されるデプロイパスにはローカル Docker は必要ありません。スクリプトは SERVICE_IMAGE=... および RUNNER_IMAGE=... を出力するため、次のステップにコピーできます。
ローカルで Docker を使用して意図的に画像をビルドしたい場合は、以下のようになります:
export BUILD_BACKEND=docker ./deploy/build-and-push.sh
6. ブートストラップを実行する
deploy/bootstrap.sh は冪等であり、増分的な Cloud Run env/secret アップデートを使用するため、安全に再実行できます。
export GCP_PROJECT_ID=your-project export GCP_REGION=us-central1 export GITHUB_APP_ID=123456 export SERVICE_IMAGE=us-docker.pkg.dev/your-project/containers/broccoli-oss-service:v0.1.0 export RUNNER_IMAGE=us-docker.pkg.dev/your-project/containers/broccoli-oss-runner:v0.1.0 # 一般的なオプションオーバーライド: export INGRESS_SERVICE_NAME=broccoli-oss-service export RUNNER_JOB_BASENAME=broccoli-oss-runner export RUNNER_TIMEOUT_SECONDS=3600 export DB_BACKEND=cloudsql export DB_INSTANCE_NAME=broccoli-oss-pg export DB_AUTHORIZED_NETWORKS=0.0.0.0/0 ./deploy/bootstrap.sh
ブートストラップは以下のものを出力します:
- デプロイされたサービス URL
- GitHub ウェブフック URL (
)${Service URL}/webhooks/github - Linear ウェブフック URL (
)${Service URL}/webhooks/linear - Cloud Run サービスおよびジョブリソース名
DB_BACKEND=cloudsql の場合、ブートストラップはさらに Public IPv4 ありで Cloud SQL インスタンスをパッチ適用し、DB_AUTHORIZED_NETWORKS から authorizedNetworks を設定します。デフォルトは 0.0.0.0/0 で、どこからの接続も許可されます。直接的な Postgres アクセスを制限したい場合は、より狭い CIDR リストでオーバーライドしてください。
GitHub アプリ設定に戻り、ホームぺージ URL および Webフック URL を上記の値に変更し、次に
broccoli-oss-gh-webhook-secret の値をアプリのウェブフックシークレットフィールドに貼り付けてください。
7. リポジトリに GitHub App をインストールする
GitHub アプリ設定から:
- 「Install App」をクリックします。
- ターゲットリポジトリが所有するアカウントまたは組織を選択します。
- 意図的に広範囲のスコープを持つ場合を除き、「Only select repositories」を選択します。
- ターゲットリポジトリへのアクセス権を与えます。
- インストール URL (
) からインストール ID をキャプチャします(次のステップで使用されます)。/settings/installations/<id>
8. マイグレーションを実行してリポジトリ構成をシードする
デフォルトの Cloud Run + Cloud SQL デプロイでは、
broccoli-oss-database-url は Cloud Run ランタイム向けに書き込まれ、/cloudsql/... Unix ソケットパスを使用します。これはデプロイされたサービスおよびランナーには正しい値ですが、ラップトップから直接使用する価値のある値ではありません。
ローカルオペレーターコマンドの場合は、Cloud SQL Auth Proxy でローカル TCP チュNEL を開始し、
broccoli-oss-db-password から ローカル DATABASE_URL を構築して実行してください:
cloud-sql-proxy your-project:us-central1:broccoli-oss-pg --port 5432
DB_PASSWORD="$(gcloud secrets versions access latest \ --secret=broccoli-oss-db-password \ --project your-project)" export DATABASE_URL="postgresql://broccoli_oss:${DB_PASSWORD}@127.0.0.1:5432/broccoli_oss" uv sync --dev uv run python -m app.operator migrate uv run python -m app.operator schema-version
ブートストラップ後の Codex デプロイスキルを使用している場合は、生成されたシークレットを Secret Manager から取得し、可能な限り既存のターゲットプロジェクト資格証明を使用する代わりにこれらのヘルパーコマンドを実行するよう指示される必要があります。以下のコマンドは手動フォールバックパスです。
GCP でのオペレーターフローをラップトップからの代わりに Codex で完了させたい場合は、次のようになります:
python .agents/skills/broccoli-oss-gcp-deploy/scripts/deploy.py \ --github-app-id <github-app-id> \ --project-id your-project \ --apply \ --post-deploy-operator \ --github-repo-full-name acme/demo \ [--git-clone-url https://github.com/acme/demo.git] \ [--default-branch main] \ [--github-installation-id 12345678] \ [--linear-team-id <linear-team-id>] \ [--linear-bot-user-id <linear-bot-user-id>]
このパスでは、一時的な Cloud Run ジョブを作成してオペレーターコマンドを実行し、完了するとその一時ジョブを削除することで、GCP 内で migrate、schema-version、seed、および preflight を実行します。ラッパーがターゲットプロジェクトの独自のシークレットおよび API から安全に発見できる場合、任意のオプションリポジトリまたは Linear フラグは省略できます。
Linear ボットユーザー ID および候補チーム ID は、ターゲットプロジェクトの既存の Linear API キーを使用して発見できます:
LINEAR_API_KEY="$(gcloud secrets versions access latest \ --secret=broccoli-oss-linear-api-key \ --project your-project)" curl -s https://api.linear.app/graphql \ -H "Authorization: ${LINEAR_API_KEY}" \ -H "Content-Type: application/json" \ -d '{"query":"query ViewerAndTeams { viewer { id name } teams { nodes { id key name } } }"}'
レスポンスには以下が含まれます:
: API キーがボットユーザーに属している場合、通常はボットユーザー ID ですviewer.id
: 候補となるteams.nodes[].id
値linear_team_id
リアルな値で
db/seed/example.seed.yaml(またはコピー)を編集します:
repos: - repo_key: demo enabled: true github_repo_full_name: acme/demo github_installation_id: 12345678 # ステップ 7 のインストール URL /settings/installations/<id> から git_clone_url: https://github.com/acme/demo.git default_branch: main base_branch: main linear_team_id: <linear-team-uuid> config_json: {} global: linear_bot_user_id: userId: <linear-bot-user-id> # ステップ 2 から
今日サポートされているトップレベルキー:
repos および global(linear_bot_user_id を含む)。シードは重複する repo_key、重複する github_repo_full_name、空の必要な文字列、および未知のキーを拒否します。
uv run python -m app.operator seed --file db/seed/example.seed.yaml
9. ウェブフックを登録する
GitHub または Linear に貼り付ける必要がある場合は、生成されたウェブフックシークレットを自分で取得してください:
gcloud secrets versions access latest \ --secret=broccoli-oss-gh-webhook-secret \ --project your-project gcloud secrets versions access latest \ --secret=broccoli-oss-linear-webhook-secret \ --project your-project
- GitHub: GitHub アプリのウェブフックはステップ 6 で既に構成されています;単に
を指していることを確認し、ウェブフックシークレットが${Service URL}/webhooks/github
と一致することを確認します。broccoli-oss-gh-webhook-secret - Linear:
に指針する新しいウェブフックを追加し、${Service URL}/webhooks/linear
の値を使用します。イシューおよびイシューラベルイベントへの購読を行います。このステップは手動で意図的に行われるか、Codex が管理者機能付きの Linear 資格証明を与えることを選択する場合を除き;通常のボット API キーは非管理者と想定されます。broccoli-oss-linear-webhook-secret
ルーティングルール:
- イシューは構成されたボットユーザーに割り当てられている必要があります。
- 正確に一つのルーティングラベルが有効な repo_key に一致する必要があります。
は小さな見積もりスキルパスを選択します;それ以外の場合はデフォルトパスを使用します。0 < estimate < 3
10. プリフライトを実行する
プリフライトは DB コネクティビティ、Secret Manager 存在、Cloud Run ジョブメタデータ、最初の有効なリポジトリへの GitHub アプリインストールトークン発行、Linear API アクセス、および vendored プロンプトテンプレート完全性の検証を行います。
export GITHUB_APP_ID=123456 export GITHUB_APP_PRIVATE_KEY_PEM="$(gcloud secrets versions access latest \ --secret=broccoli-oss-github-app-private-key-pem \ --project your-project)" export GH_WEBHOOK_SECRET="$(gcloud secrets versions access latest \ --secret=broccoli-oss-gh-webhook-secret \ --project your-project)" export LINEAR_API_KEY="$(gcloud secrets versions access latest \ --secret=broccoli-oss-linear-api-key \ --project your-project)" export LINEAR_WEBHOOK_SECRET="$(gcloud secrets versions access latest \ --secret=broccoli-oss-linear-webhook-secret \ --project your-project)" export RUNNER_JOB_NAME="projects/your-project/locations/us-central1/jobs/broccoli-oss-runner" export GCP_PROJECT_ID=your-project export GCP_REGION=us-central1 export APP_BASE_URL=https://your-service-url uv run python -m app.operator preflight
11. スモークテストを実行する
GitHub ウェブフックカナリ:
APP_BASE_URL=https://your-service-url \ DATABASE_URL=postgresql://... \ GH_WEBHOOK_SECRET=... \ CANARY_GITHUB_REPO_FULL_NAME=acme/demo \ CANARY_GITHUB_PR_NUMBER=12 \ uv run python tests/smoke/github_webhook_canary.py
Linear ウェブフックカナリ:
APP_BASE_URL=https://your-service-url \ DATABASE_URL=postgresql://... \ LINEAR_WEBHOOK_SECRET=... \ CANARY_LINEAR_ISSUE_ID=issue-id \ CANARY_LINEAR_BOT_USER_ID=bot-user-id \ CANARY_LINEAR_CREATOR_ID=creator-id \ CANARY_LINEAR_REPO_KEY=demo \ uv run python tests/smoke/linear_webhook_canary.py
両スクリプトは HTTP レスポンズに加えてマッチングする webhook_deliveries 行を出力します。これで稼働しています。
Broccoli の操作
ジョブ状態の確認
便利なテーブル:
webhook_deliveries、jobs、github_pr_state、linear_issue_state、repo_configs、global_config。
SELECT provider, delivery_id, processed_at, ignored_reason, error_stage, job_id FROM webhook_deliveries ORDER BY received_at DESC LIMIT 20; SELECT id, kind, status, routing_repo_key, error_kind, error_message FROM jobs ORDER BY created_at DESC LIMIT 20; -- ライフサイクルコメントおよび起動メタデータ(尽力) SELECT id, kind, run_metadata->'launch' AS launch, run_metadata->'linear'->'commentIds' AS linear_comment_ids, run_metadata->'githubReviewFeedback' AS github_review_feedback, run_metadata->'run' AS run_stage FROM jobs ORDER BY created_at DESC LIMIT 20;
ライフサイクルコメントは尽力による側面効果です。GitHub/Linear API が利用不可または権限が不足している場合でも、
jobs は実行されるべきであり、run_metadata は何が投稿できたかを記録します。
無視されたウェブフックレスポンス
すべての配信(無視されたものを含む)が記録されるため、ルーティング決定は監査可能です。一般的な
ignored_reason 値:
| 理由 | 意味 |
|---|---|
| unsupported_event | イベントは Broccoli がサポートする表面外にあります |
| duplicate_delivery | 配信 ID はすでに永続的に処理されました |
| missing_repo_routing | ウェブフックペイロードに一致する有効な repo_key がない |
| review_state_not_changes_requested | GitHub リビューは実行可能なアクションではありません |
| not_automation_ready | Linear イシューは現在、構成されたボットユーザーには割り当てられていません |
セーフな失敗したウェブフックの再試行
ウェブフック配信重複防止は Postgres に保存されています。安全な振る舞い:
- オリジナルの配信が既に処理された場合、再配信は
を返します。duplicate_delivery - オリジナルのジョブレコードが存在するが起動の帳簿作成が失敗した場合、再配信は保存されたジョブ ID を再利用します。
またはjobs
行を手動で変更しないでください。意図的に状態を修復する場合を除きます。webhook_deliveries
推奨される再試行パス:
- 根本原因を修正します。
- GitHub または Linear から元のウェブフックを再配信します。
- 同じ配信 ID が終端のジョブステートに到達することを確認します。
IAM
Broccoli は「厳格な最小権限モデル」よりも「最初のデプロイで動作する」方を好みます。稼働後に緊密化してください。
ランタイムサービスアカウント:
- ングレスサービスアカウント:
project-level roles/run.developer - ングレスおよびランナーサービスアカウント:
roles/secretmanager.secretAccessor - ングレスおよびランナーサービスアカウント:
(Cloud SQL を使用する場合のみ)roles/cloudsql.client
デプロイヤー権限: プロジェクトオーナーまたはエディター、およびサービスアカウントの作成と IAM バインディングを作成する権限。
IAM 決定のために参照されたドキュメント:
- Cloud Run: ジョブの作成
- Cloud Run: ジョブの実行
- Cloud Run IAM ロールおよび権限
ローカル開発
uv sync --dev cp .env.example .env # リアルな値を入力;.env をコミットしないでください uv run ruff check . uv run pytest
.env ファイルは gitignored です。完全なコントリビューターワークフローについては CONTRIBUTING.md を参照してください。
ドキュメンテーション
- ARCHITECTURE.md — 設計、コンポーネント、データフロー
- JOB-CONTRACT.md — ウェブフックおよび状態モデルの契約
- CONTRIBUTING.md — 貢献方法
- CHANGELOG.md — リリース履歴
ライフサイクルコメントパリティ注記:
- Linear イシュー自動化は尽力によるライフサイクルコメント(キューイング、開始、prOpened、終端)を投稿します。
- GitHub リビューフィードバックジョブは尽力による「ラウンサーが開始された」コメントおよび終端の失敗コメントを投稿します。
- その他のプライベートリポジトリ行動(デバッグモード、plan-verbatim モード、追加修復フロー)は意図的に範囲外です。
コントリビューション
イシューとプルリクエストをお待ちしています。設定、期待値、およびレビューループについては CONTRIBUTING.md から始めます。公的なイシューにシークレット、認証情報、または他の機密デプロイ詳細を投稿しないでください。
ライセンス
Broccoli OSS は MIT ライセンスの下でリリースされています。バンドルサードパーティの通知については NOTICE を参照してください。
FAQ
- 外部管理された Postgres を使用できますか?
はい —
をDB_BACKEND
以外の何かに設定し、cloudsql
をインスタントに指してください。DATABASE_URL - LLM を交換できますか? ランナーは codex および claude CLI にシェルアウトします;交換にはランナーハンドラーおよび vendored プロンプトテンプレートのフォークが必要です。これをプラグ可能にするコントリビューションをお待ちしています。
- ホスト版がありますか? 今回はありません。Broccoli はあなたの GCP プロジェクトで、あなたのキーに対して動作します。
- クローズドソース版がありますか? 他のインフラストラクチャ上で動作する Broccoli のクローズドソース版が存在しますが、ここでは公開されていません。このリポジトリの OSS パスは自己完結しており、プロダクション準備ができています。