Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contrib/chart/Chart.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,7 +2,7 @@ apiVersion: v2
name: centaur
description: Helm chart for the trusted Centaur control plane
type: application
version: 0.1.131
version: 0.1.135
appVersion: "0.1.0"
dependencies:
- name: connect
Expand Down
22 changes: 20 additions & 2 deletions contrib/chart/templates/_helpers.tpl
Original file line numberDiff line numberDiff line change
Expand Up@@ -157,8 +157,9 @@ so the defaults are safe for repos that only carry some surfaces.

{{- /*
The GitHub App PEM is intentionally a separate secret rather than a key in the
shared infra env Secret: it is mounted read-only into only the Console worker,
not translated to an environment variable or exposed to Console web pods.
shared infra env Secret: it is mounted read-only only into components that mint
installation tokens, never translated to an environment variable, and never
exposed to Console web pods.
*/ -}}
{{- define "centaur.githubAppInstallationChecksum" -}}
{{- $console := include "centaur.consoleValues" . | fromYaml -}}
Expand All@@ -170,6 +171,23 @@ not translated to an environment variable or exposed to Console web pods.
{{- end -}}
{{- end -}}

{{- /*
The githubbot can use the same App installation identity without placing its
PEM in an environment variable. Include both the mounted Secret generation and
the public identity in the checksum so key/client/installation rotation rolls
the controller immediately.
*/ -}}
{{- define "centaur.githubbotAppChecksum" -}}
{{- $app := .Values.githubbot.githubApp -}}
{{- if $app.enabled -}}
{{- $name := required "githubbot.githubApp.existingSecretName is required when GitHub App authentication is enabled" $app.existingSecretName -}}
{{- $payload := dict "secret" (include "centaur.secretResourceVersion" (dict "root" . "name" $name)) "clientId" (required "githubbot.githubApp.clientId is required when GitHub App authentication is enabled" $app.clientId) "installationId" (required "githubbot.githubApp.installationId is required when GitHub App authentication is enabled" $app.installationId) -}}
{{- toJson $payload | sha256sum | quote -}}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
{{- else -}}
{{- "disabled" | quote -}}
{{- end -}}
{{- end -}}

{{- /*
The upstream 1Password Connect subchart names its Service after
`connect.applicationName` (default `onepassword-connect`) and exposes the
Expand Down
42 changes: 37 additions & 5 deletions contrib/chart/templates/githubbot.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -42,6 +42,7 @@ spec:
metadata:
annotations:
checksum/infra-secrets: {{ include "centaur.infraSecretsChecksum" . }}
checksum/github-app-private-key: {{ include "centaur.githubbotAppChecksum" . }}
{{- if or .Values.githubbot.reviewPrompt .Values.githubbot.issuePrompt .Values.githubbot.managementPrompt }}
checksum/prompts: {{ dict "review" .Values.githubbot.reviewPrompt "issue" .Values.githubbot.issuePrompt "management" .Values.githubbot.managementPrompt | toJson | sha256sum }}
{{- end }}
Expand DownExpand Up@@ -70,14 +71,22 @@ spec:
# the deployment's default harness.
- name: GITHUBBOT_DEFAULT_HARNESS
value: {{ .Values.sandbox.harnessEngine | quote }}
# Personal access token for the bot's GitHub teammate account — kept
# distinct from the sandbox tool token so the bot acts as its own
# GitHub user (requestable as a reviewer, @-mentionable).
{{- if .Values.githubbot.githubApp.enabled }}
- name: GITHUB_APP_CLIENT_ID
value: {{ required "githubbot.githubApp.clientId is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.clientId | quote }}
- name: GITHUB_INSTALLATION_ID
value: {{ required "githubbot.githubApp.installationId is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.installationId | quote }}
- name: GITHUB_PRIVATE_KEY_FILE
value: {{ printf "%s/%s" (required "githubbot.githubApp.privateKeyMountPath is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.privateKeyMountPath) (required "githubbot.githubApp.privateKeySecretKey is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.privateKeySecretKey) | quote }}
{{- else }}
# Personal access token for the bot's GitHub teammate account. This
# compatibility mode remains available for deployments without an App.
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: {{ include "centaur.secretEnvName" . }}
key: {{ printf "%sGITHUBBOT_TOKEN" .Values.secretManager.envPrefix }}
{{- end }}
# githubbot's own webhook signing secret (the GitHub repo/org webhook).
- name: GITHUB_WEBHOOK_SECRET
valueFrom:
Expand All@@ -95,14 +104,20 @@ spec:
name: {{ include "centaur.secretEnvName" . }}
key: {{ printf "%sDATABASE_URL" .Values.secretManager.envPrefix }}
- name: GITHUB_BOT_USERNAME
value: {{ required "githubbot.userName is required (the bot account's GitHub login)" .Values.githubbot.userName | quote }}
value: {{ required "githubbot.userName is required (App mention slug or PAT account login)" .Values.githubbot.userName | quote }}
{{- if .Values.githubbot.botActorLogin }}
- name: GITHUB_BOT_ACTOR_LOGIN
value: {{ .Values.githubbot.botActorLogin | quote }}
{{- end }}
- name: GITHUBBOT_REPOSITORY_ALLOWLIST
value: {{ required "githubbot.repositoryAllowlist is required when githubbot is enabled" .Values.githubbot.repositoryAllowlist | quote }}
# v2 PR self-management knobs.
- name: GITHUBBOT_AUTO_MERGE
value: {{ .Values.githubbot.autoMerge | quote }}
- name: GITHUBBOT_MERGE_METHOD
value: {{ .Values.githubbot.mergeMethod | quote }}
- name: GITHUBBOT_OWNERSHIP_LABEL
value: {{ required "githubbot.ownershipLabel is required when githubbot is enabled" .Values.githubbot.ownershipLabel | quote }}
- name: GITHUBBOT_REVIEW_MAX_ROUNDS_PER_EPOCH
value: {{ .Values.githubbot.reviewMaxRoundsPerEpoch | quote }}
- name: GITHUBBOT_REVIEW_MAX_TOTAL_ROUNDS_PER_EPOCH
Expand DownExpand Up@@ -172,16 +187,33 @@ spec:
{{ toYaml .Values.containerSecurityContext | nindent 12 }}
resources:
{{ toYaml .Values.githubbot.resources | nindent 12 }}
{{- if or .Values.githubbot.reviewPrompt .Values.githubbot.issuePrompt .Values.githubbot.managementPrompt }}
{{- if or .Values.githubbot.githubApp.enabled .Values.githubbot.reviewPrompt .Values.githubbot.issuePrompt .Values.githubbot.managementPrompt }}
volumeMounts:
{{- if .Values.githubbot.githubApp.enabled }}
- name: github-app-private-key
mountPath: {{ required "githubbot.githubApp.privateKeyMountPath is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.privateKeyMountPath | quote }}
readOnly: true
{{- end }}
{{- if or .Values.githubbot.reviewPrompt .Values.githubbot.issuePrompt .Values.githubbot.managementPrompt }}
- name: prompts
mountPath: /etc/githubbot/prompts
readOnly: true
{{- end }}
volumes:
{{- if .Values.githubbot.githubApp.enabled }}
- name: github-app-private-key
secret:
secretName: {{ required "githubbot.githubApp.existingSecretName is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.existingSecretName | quote }}
items:
- key: {{ required "githubbot.githubApp.privateKeySecretKey is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.privateKeySecretKey | quote }}
path: {{ required "githubbot.githubApp.privateKeySecretKey is required when GitHub App authentication is enabled" .Values.githubbot.githubApp.privateKeySecretKey | quote }}
{{- end }}
{{- if or .Values.githubbot.reviewPrompt .Values.githubbot.issuePrompt .Values.githubbot.managementPrompt }}
- name: prompts
configMap:
name: {{ include "centaur.componentName" (dict "root" . "component" "githubbot") }}-prompts
{{- end }}
{{- end }}
---
apiVersion: v1
kind: Service
Expand Down
30 changes: 22 additions & 8 deletions contrib/chart/values.yaml
Original file line numberDiff line numberDiff line change
Expand Up@@ -655,13 +655,12 @@ linearbot:
extraEnv: {}
resources: {}

# Chat SDK GitHub bot — GitHub teammate (PAT) ingress. Receives issue/PR comment
# webhooks on /api/webhooks/github (the @chat-adapter/github adapter), answers in
# the comment thread, and runs a review when the bot account is requested as a
# reviewer. Forwards sessions to the api-rs control plane (:8080). Disabled by
# default: requires the GITHUBBOT_TOKEN (PAT) and GITHUBBOT_WEBHOOK_SECRET secrets
# (see contrib/scripts/bootstrap-k8s-secrets.sh). userName must be the bot
# account's GitHub login so @-mention and review-request matching work.
# Chat SDK GitHub ingress. Receives issue/PR comment webhooks on
# /api/webhooks/github (the @chat-adapter/github adapter), answers in the
# comment thread, and forwards sessions to the api-rs control plane (:8080).
# Disabled by default: requires GITHUBBOT_WEBHOOK_SECRET plus either the
# githubApp block or the legacy GITHUBBOT_TOKEN secret. userName is the App
Comment thread
michaelmwu marked this conversation as resolved.
# mention slug (without [bot]) or teammate login so @-mention matching works.
githubbot:
enabled: false
# Singleton controller: per-PR admission and merge gates are process-serialized.
Expand All@@ -672,7 +671,22 @@ githubbot:
tag: latest
pullPolicy: Always
userName: ""
# v2 PR self-management (only acts on PRs assigned to the bot account).
# Optional exact login recorded on bot-authored events. App deployments use
# <slug>[bot]; when empty, githubbot derives it from userName in App mode.
botActorLogin: ""
# Prefer a GitHub App installation for production. When enabled, the PAT
# secret key is not referenced; the PEM is mounted read-only and Octokit
# transparently rotates short-lived installation tokens.
githubApp:
enabled: false
clientId: ""
installationId: ""
existingSecretName: ""
privateKeySecretKey: private-key.pem
privateKeyMountPath: /var/run/centaur/github-app
# v2 PR self-management acts on bot-authored PRs, PAT-account assignments, or
# subjects carrying this explicit App-compatible handoff label.
ownershipLabel: centaur-managed
# Auto-merge respects branch protection and is paused per-PR by the hold label
# / draft status.
autoMerge: true
Expand Down
26 changes: 16 additions & 10 deletions contrib/scripts/bootstrap-k8s-secrets.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -39,11 +39,14 @@ Optional Linear bot bootstrap (consumed when linearbot.enabled=true):

Optional GitHub ingress bootstrap (consumed when githubbot.enabled=true):
GITHUBBOT_TOKEN personal access token for the bot's GitHub
teammate account; required together with the
webhook secret (partial config fails fast). Kept
teammate account in PAT mode; when set, the
webhook secret is also required. Omit for App
mode. Kept
distinct from GITHUB_TOKEN (the repo-cache /
sandbox tool token) so the bot acts as its own user.
GITHUBBOT_WEBHOOK_SECRET signing secret from the GitHub repo/org webhook
GITHUBBOT_WEBHOOK_SECRET signing secret from the GitHub repo/org webhook;
seeds the shared ingress keys for either PAT or
App authentication
GITHUBBOT_API_KEY bearer the bot sends to api-rs; auto-generated
when absent

Expand DownExpand Up@@ -153,11 +156,10 @@ if [[ -n "${LINEAR_ACCESS_TOKEN:-}" || -n "${LINEARBOT_WEBHOOK_SECRET:-}" ]]; th
require_env LINEARBOT_WEBHOOK_SECRET
fi

# GitHub bot config is optional but must be complete: a PAT without the webhook
# secret (or vice versa) deploys a githubbot that boots and then rejects every
# delivery, which reads as silence.
if [[ -n "${GITHUBBOT_TOKEN:-}" || -n "${GITHUBBOT_WEBHOOK_SECRET:-}" ]]; then
require_env GITHUBBOT_TOKEN
# GitHub ingress shared secrets support PAT and App authentication. A PAT or an
# explicitly supplied api-rs bearer without a webhook secret is incomplete;
# the webhook secret alone is valid App-mode bootstrap input.
if [[ -n "${GITHUBBOT_TOKEN:-}" || -n "${GITHUBBOT_API_KEY:-}" ]]; then
require_env GITHUBBOT_WEBHOOK_SECRET
fi

Expand DownExpand Up@@ -286,10 +288,12 @@ if secret_exists centaur-infra-env; then
patch_data+=("\"LINEARBOT_API_KEY\":\"$(rand_hex | base64 | tr -d '\n')\"")
fi
fi
# GitHub bot credentials. The PAT + webhook secret are set whenever present so
# they can be rotated; the api-rs bearer is generated once and kept stable.
# GitHub ingress shared secrets are independent of controller authentication:
# App mode has no PAT. Rotate supplied values; generate the api-rs bearer once.
if [[ -n "${GITHUBBOT_TOKEN:-}" ]]; then
patch_data+=("\"GITHUBBOT_TOKEN\":\"$(printf '%s' "$GITHUBBOT_TOKEN" | base64 | tr -d '\n')\"")
fi
if [[ -n "${GITHUBBOT_WEBHOOK_SECRET:-}" ]]; then
patch_data+=("\"GITHUBBOT_WEBHOOK_SECRET\":\"$(printf '%s' "$GITHUBBOT_WEBHOOK_SECRET" | base64 | tr -d '\n')\"")
if [[ -n "${GITHUBBOT_API_KEY:-}" ]]; then
patch_data+=("\"GITHUBBOT_API_KEY\":\"$(printf '%s' "$GITHUBBOT_API_KEY" | base64 | tr -d '\n')\"")
Expand DownExpand Up@@ -366,6 +370,8 @@ else
fi
if [[ -n "${GITHUBBOT_TOKEN:-}" ]]; then
secret_args+=(--from-literal=GITHUBBOT_TOKEN="$GITHUBBOT_TOKEN")
fi
if [[ -n "${GITHUBBOT_WEBHOOK_SECRET:-}" ]]; then
secret_args+=(--from-literal=GITHUBBOT_WEBHOOK_SECRET="$GITHUBBOT_WEBHOOK_SECRET")
secret_args+=(--from-literal=GITHUBBOT_API_KEY="${GITHUBBOT_API_KEY:-$(rand_hex)}")
fi
Expand Down
Loading