# yaml-language-server: $schema=https://schema.zeabur.app/template.json
apiVersion: zeabur.com/v1
kind: Template
metadata:
    name: OpenAB Review Council (GitHub App)
spec:
    description: |
        GitHub App webhook install for a self-hosted, CodeRabbit-style PR-review
        council: a control plane + 3 stock OpenAB Claude pods deliberate on a PR and
        post one verdict as your GitHub App bot. After deploy, point the App webhook at
        /api/v1/github_webhooks and provision the chair volume with the App private key.
        Do not also install the copied Action on the same repo.
    icon: https://cdn-console.zeabur.com/f/6qNF8/ocp-icon.webp
    variables:
        - key: PUBLIC_DOMAIN
          type: DOMAIN
          name: Control plane domain
          description: Public domain for the control plane's REST/SSE API.
        - key: CLAUDE_CODE_OAUTH_TOKEN
          type: PASSWORD
          name: Claude Code OAuth Token
          description: Agent auth for every pod. From `claude setup-token` (or use ANTHROPIC_API_KEY).
        - key: GITHUB_WEBHOOK_SECRET
          type: PASSWORD
          name: GitHub Webhook Secret
          description: HMAC secret used by POST /api/v1/github_webhooks. Use the same value in the GitHub App webhook settings.
    tags:
        - AI
        - Developer Tools
    readme: |
        # OpenAB Review Council (GitHub App)

        Use this template when you want a webhook trigger with no copied workflow file
        in each target repo. PR events arrive through a GitHub App webhook, and the
        chair posts the verdict as your GitHub App bot after you provision its
        persistent volume.

        It deploys a control plane plus 3 stock OpenAB Claude pods (1 chair + 2
        reviewers). No per-bot setup is needed; every pod uses the same Claude Code
        OAuth token.

        ## Required variables

        - `PUBLIC_DOMAIN`: the control-plane domain, for example `my-council`.
        - `CLAUDE_CODE_OAUTH_TOKEN`: from `claude setup-token`.
        - `GITHUB_WEBHOOK_SECRET`: random HMAC secret, for example from `openssl rand -hex 32`.

        ## GitHub App setup

        1. Create a GitHub App with:
           - Permissions: `Pull requests: Read and write`, `Contents: Read-only`.
           - Events: Pull requests and Issue comments.
           - Webhook URL: `https://my-council.zeabur.app/api/v1/github_webhooks`.
           - Webhook secret: the same `GITHUB_WEBHOOK_SECRET` value.
        2. Install the App on the target repo.
        3. Generate a private key (`.pem`) and note the App ID and installation ID.

        ## Chair App identity

        1. Copy `scripts/get-gh-app-token.sh` from the source repo and set its `APP_ID`
           and `INSTALLATION_ID`:
           `https://github.com/canyugs/openab-control-plane/blob/main/scripts/get-gh-app-token.sh`
        2. Upload the private key to the chair service at `/home/node/.github-app.pem`.
        3. Upload the edited token-minter to `/home/node/bin/get-gh-app-token.sh`.
        4. Set permissions in the chair service:

           ```sh
           chmod 600 /home/node/.github-app.pem
           chmod +x /home/node/bin/get-gh-app-token.sh
           chown node:node /home/node/.github-app.pem /home/node/bin/get-gh-app-token.sh
           ```

        5. Restart the chair service.
        6. Verify in the chair service that `HOME=/home/node gh auth status` shows the
           App bot account.

        ## Triggers

        - Automatic: PR opened, reopened, or marked ready for review.
        - Manual review: an OWNER / MEMBER / COLLABORATOR comments `/review` on the PR.
        - Follow-up questions: `/ask <question>` works through the webhook path.
          `@mention` also works after setting `OABCP_BOT_HANDLE` on the control-plane.

        Use this GitHub App template or the PAT template, not both on one repo, or one
        PR event can convene two councils. The control plane does not need
        `GITHUB_APP_ID`, `GITHUB_APP_INSTALLATION_ID`, or `GITHUB_APP_PRIVATE_KEY` for
        this pod-local posting path.

        For private repos, reviewer pods also need GitHub read access to self-fetch the
        PR diff. Public repos work anonymously; private repos should add read-only
        reviewer credentials or use the separate per-role App token path.

        Full guide:
        `https://github.com/canyugs/openab-control-plane/blob/main/docs/template.md`
    services:
        - name: control-plane
          icon: https://cdn-console.zeabur.com/f/6qNF8/ocp-icon.webp
          template: PREBUILT_V2
          spec:
            id: control-plane
            source:
                image: docker.io/canyu/openab-control-plane:0.1.11
            ports:
                - id: web
                  port: 8090
                  type: HTTP
            volumes:
                - id: data
                  dir: /data
            env:
                GITHUB_WEBHOOK_SECRET:
                    default: ${GITHUB_WEBHOOK_SECRET}
                OABCP_ADDR:
                    default: 0.0.0.0:8090
                OABCP_API_KEY:
                    default: ${PASSWORD}
                    expose: true
                OABCP_BOTS:
                    default: chair:chair,rev1:reviewer,rev2:reviewer
                OABCP_DB:
                    default: /data/plane.db
                OABCP_WS_URL:
                    default: ws://control-plane.zeabur.internal:8090/ws
            healthCheck:
                type: HTTP
                port: web
                http:
                    path: /healthz
          domainKey: PUBLIC_DOMAIN
        - name: chair
          icon: https://cdn-console.zeabur.com/f/0Ewi6/openab-icon.webp
          dependencies:
            - control-plane
          template: PREBUILT_V2
          spec:
            id: chair
            source:
                image: ghcr.io/openabdev/openab:0.9.0-beta.3-claude
                command:
                    - openab
                    - run
                    - -c
                    - http://control-plane.zeabur.internal:8090/bot-config/chair
            volumes:
                - id: home
                  dir: /home/node
            env:
                CLAUDE_CODE_OAUTH_TOKEN:
                    default: ${CLAUDE_CODE_OAUTH_TOKEN}
        - name: rev1
          icon: https://cdn-console.zeabur.com/f/0Ewi6/openab-icon.webp
          dependencies:
            - control-plane
          template: PREBUILT_V2
          spec:
            id: rev1
            source:
                image: ghcr.io/openabdev/openab:0.9.0-beta.3-claude
                command:
                    - openab
                    - run
                    - -c
                    - http://control-plane.zeabur.internal:8090/bot-config/rev1
            env:
                CLAUDE_CODE_OAUTH_TOKEN:
                    default: ${CLAUDE_CODE_OAUTH_TOKEN}
        - name: rev2
          icon: https://cdn-console.zeabur.com/f/0Ewi6/openab-icon.webp
          dependencies:
            - control-plane
          template: PREBUILT_V2
          spec:
            id: rev2
            source:
                image: ghcr.io/openabdev/openab:0.9.0-beta.3-claude
                command:
                    - openab
                    - run
                    - -c
                    - http://control-plane.zeabur.internal:8090/bot-config/rev2
            env:
                CLAUDE_CODE_OAUTH_TOKEN:
                    default: ${CLAUDE_CODE_OAUTH_TOKEN}
