Skip to content

feat(openab): add existingSecret support for Slack agent credentials#901

Merged
thepagent merged 2 commits into
openabdev:mainfrom
antigenius0910:feature/issue-900-slack-existing-secret
May 22, 2026
Merged

feat(openab): add existingSecret support for Slack agent credentials#901
thepagent merged 2 commits into
openabdev:mainfrom
antigenius0910:feature/issue-900-slack-existing-secret

Conversation

@antigenius0910
Copy link
Copy Markdown
Contributor

@antigenius0910 antigenius0910 commented May 22, 2026

What problem does this solve?

In GitOps environments using External Secrets Operator (ESO), Vault, or SealedSecrets, Kubernetes Secrets are populated by the operator from an external store. The openab chart already supports this pattern for ANTHROPIC_API_KEY via secretEnv (rendered as valueFrom.secretKeyRef).

Slack tokens currently cannot follow the same path. Because the chart creates its own Secret from Helm values, SLACK_BOT_TOKEN and SLACK_APP_TOKEN must be passed at helm install/helm upgrade time via --set-string or helm_release_set_sensitive. Every token rotation requires a Helm re-apply, blocking automation and making platform engineers a bottleneck for what should be a self-service operation.

Closes #900

Discord Discussion URL: https://discord.com/channels/1491295327620169908/1491365158868619404/1507286287428878348

At a Glance

                Before                                After
  ┌──────────────────────────┐         ┌──────────────────────────┐
  │ External Secret Store    │         │ External Secret Store    │
  │  ANTHROPIC_API_KEY  ✅   │         │  ANTHROPIC_API_KEY  ✅   │
  │  SLACK_BOT_TOKEN    ❌   │         │  SLACK_BOT_TOKEN    ✅   │
  │  SLACK_APP_TOKEN    ❌   │         │  SLACK_APP_TOKEN    ✅   │
  └────────────┬─────────────┘         └────────────┬─────────────┘
               │ (slack tokens                       │ (all via ESO)
               │  via helm --set)                    ▼
               ▼                              ┌─────────────┐
        helm upgrade                          │ K8s Secret  │
        (every rotation)                      │ (ESO-synced)│
                                              └──────┬──────┘
                                                     │ secretKeyRef
                                                     ▼
                                              ┌─────────────┐
                                              │ openab pod  │
                                              └─────────────┘

Prior Art & Industry Research

Not applicable — this is a Helm chart credential-injection change, not an architectural/runtime/scheduling/persistence change. The pattern itself (existingSecret field that toggles between chart-managed and externally-managed Secrets) is the standard Helm idiom used by community charts such as bitnami/*, prometheus-community/*, and external-secrets/external-secrets. The openab-telegram chart (#873) already implements this same pattern within this repo.

Proposed Solution

Add agents.<name>.slack.existingSecret to the openab chart. When set, the chart references the named Kubernetes Secret for SLACK_BOT_TOKEN and SLACK_APP_TOKEN instead of creating a chart-managed Secret from Helm values.

Behavior:

Agent uses existingSecret set? Result
Slack only No Chart creates agent Secret with slack-bot-token, slack-app-token (unchanged)
Slack only Yes No chart-managed Secret created; Deployment references existingSecret directly
Slack + Discord/STT/gateway No Chart creates agent Secret with all tokens (unchanged)
Slack + Discord/STT/gateway Yes Chart Secret contains only non-Slack keys; Deployment references existingSecret for Slack keys

Files changed:

  • charts/openab/values.yaml — new agents.<name>.slack.existingSecret: "" field
  • charts/openab/templates/secret.yaml — guard slack-bot-token/slack-app-token entries with (not .existingSecret); updated $hasSlack so a slack-only agent with existingSecret skips Secret creation entirely
  • charts/openab/templates/_helpers.tpl — new openab.slackSecretName helper returning existingSecret or the chart-managed agent fullname
  • charts/openab/templates/deployment.yaml — Slack env vars use the new helper for secretKeyRef.name; render condition expanded to fire when either botToken/appToken or existingSecret is set
  • charts/openab/tests/slack-existing-secret_test.yaml — new helm-unittest suite (8 tests)
  • charts/openab/README.md — new value documented

Why this approach?

Scoped per-agent under agents.<name>.slack.existingSecret (not chart-level, not agent-level). The openab chart is multi-agent and credentials are already namespaced per-adapter (slack.botToken, discord.botToken, etc.). Placing existingSecret under slack keeps it consistent with existing field locations and lets users with mixed-adapter agents manage each credential family independently.

Dual-secret behavior is intentional. When an agent uses both Slack (via existingSecret) and Discord (via botToken), the chart creates one Secret for Discord and the Deployment references the external Secret for Slack. This is consistent with the pattern where each adapter's credentials are independently sourced.

Backwards compatible. existingSecret defaults to "". No change in behavior for any existing deployment.

Alternatives Considered

  1. Agent-level agents.<name>.existingSecret — would replace all five credential keys (discord-bot-token, slack-bot-token, slack-app-token, stt-api-key, gateway-ws-token) in a single Secret. Rejected because it forces all credentials into one external Secret, blocking the common case where Slack tokens come from a different store (e.g. team-owned AWS SM path) than Discord/STT tokens (e.g. platform-owned Vault path).

  2. Chart-level existingSecret — mirroring the openab-telegram chart exactly. Rejected because openab-telegram is single-agent and chart-level was natural there; openab is multi-agent and chart-level would force all agents to share one credential Secret.

  3. secretEnv only, without existingSecretsecretEnv already supports valueFrom.secretKeyRef, so a user could in theory configure Slack env vars via secretEnv. Rejected because (a) secretEnv is documented for inheritable env vars and adds keys to inherit_env in config.toml, which is not appropriate for SLACK_BOT_TOKEN (it's a secret_keyref in the adapter config, not an inherited env), and (b) the existingSecret pattern is more discoverable for users familiar with the rest of the Helm ecosystem.

Validation

Helm chart changes:

  • helm lint charts/openab passes
  • helm template renders correctly for all three cases (existingSecret unset, existingSecret set with slack-only agent, existingSecret set with mixed Slack+Discord agent)
  • helm unittest charts/openab105/105 pass (97 baseline + 8 new tests covering both secret.yaml and deployment.yaml rendering)

Manual helm template verification:

# Case A: existingSecret unset (baseline)
$ helm template test charts/openab \
    --set agents.kiro.slack.enabled=true \
    --set agents.kiro.slack.botToken=xoxb-test \
    --set agents.kiro.slack.appToken=xapp-test
# → chart-managed Secret has slack-bot-token + slack-app-token
# → Deployment SLACK_*_TOKEN refs chart-managed Secret

# Case B: existingSecret set, slack-only agent
$ helm template test charts/openab \
    --set agents.kiro.slack.enabled=true \
    --set agents.kiro.slack.existingSecret=my-eso-creds
# → no chart-managed Secret rendered
# → Deployment SLACK_*_TOKEN refs my-eso-creds

# Case C: existingSecret set + discord enabled
$ helm template test charts/openab \
    --set agents.kiro.slack.enabled=true \
    --set agents.kiro.slack.existingSecret=my-eso-creds \
    --set agents.kiro.discord.enabled=true \
    --set agents.kiro.discord.botToken=disc-token
# → chart-managed Secret contains ONLY discord-bot-token
# → Deployment SLACK_*_TOKEN refs my-eso-creds; DISCORD_BOT_TOKEN refs chart-managed

Add `agents.<name>.slack.existingSecret` to the openab chart. When set,
the chart references the named Kubernetes Secret for SLACK_BOT_TOKEN and
SLACK_APP_TOKEN instead of creating a chart-managed Secret from values.

Adapts the existingSecret pattern from the openab-telegram chart (openabdev#873)
to the multi-agent structure of openab, scoped per-agent.

Enables ESO/Vault/SealedSecrets workflows where Slack tokens rotate
without requiring a Helm re-apply.

Behavior:
- existingSecret unset: chart creates Secret with slack tokens (unchanged)
- existingSecret set, slack-only agent: no chart-managed Secret created
- existingSecret set + discord/stt/gateway: chart Secret omits slack keys;
  deployment references existingSecret for slack envs only (dual-secret)

Closes openabdev#900

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@antigenius0910 antigenius0910 requested a review from thepagent as a code owner May 22, 2026 08:12
@github-actions github-actions Bot added closing-soon PR missing Discord Discussion URL — will auto-close in 3 days pending-maintainer and removed closing-soon PR missing Discord Discussion URL — will auto-close in 3 days labels May 22, 2026
@shaun-agent
Copy link
Copy Markdown
Contributor

OpenAB PR Screening

This is auto-generated by the OpenAB project-screening flow for context collection and reviewer handoff.
Click 👍 if you find this useful. Human review will be done within 24 hours. We appreciate your support and contribution 🙏

Screening report blocked after verification.

i confirmed via gh:

then the local command runner started failing before gh could execute:

bwrap: No permissions to create a new namespace

so i could not post the comment or move the project item.

Intent

PR #901 makes Slack credentials in the openab Helm chart compatible with GitOps-managed Kubernetes Secrets. The operator-visible problem is that Slack token rotation currently requires a Helm upgrade.

Feat

Feature work. Adds per-agent agents.<name>.slack.existingSecret so Slack bot/app tokens can come from an existing Kubernetes Secret while preserving current chart-managed Secret behavior.

Who It Serves

Deployers and agent runtime operators using ESO, Vault, SealedSecrets, or Terraform-managed Helm releases.

Rewritten Prompt

Update charts/openab so each Slack-enabled agent may set agents.<agent>.slack.existingSecret to a Kubernetes Secret containing slack-bot-token and slack-app-token. When unset, preserve existing behavior. When set, reference that Secret from Deployment env vars, omit Slack keys from chart-managed Secrets, skip chart-managed Secret creation for Slack-only agents, document the value, and add helm-unittest coverage for unset, Slack-only, and mixed-adapter cases.

Merge Pitch

Worth advancing. This removes a real GitOps friction point without changing runtime behavior for existing installs. Main reviewer concern should be mixed-secret rendering: Slack from external Secret, non-Slack credentials still from chart-managed Secret.

Best-Practice Comparison

OpenClaw and Hermes Agent patterns do not materially apply. This is Helm credential injection, not scheduling, persistence, retry, locking, or run-log architecture.

Implementation Options

  1. Conservative: merge Slack-only existingSecret as proposed.
  2. Balanced: merge this, then follow with credential-source cleanup across adapters.
  3. Ambitious: introduce a generic per-adapter/per-key credential source model.

Comparison Table

Option Speed Complexity Reliability Maintainability User Impact Fit for OpenAB now
Slack-only field High Low High Good Immediate unblock Best
Follow-up cleanup Medium Medium High Better Immediate plus cleanup Strong as split
Generic model Low High Medium Best long-term Broad but disruptive Too large now

Recommendation

Take the conservative path for PR #901. Split any broader credential-source unification into a follow-up. Review helper behavior, Slack-only Secret omission, mixed adapter rendering, and external Secret key documentation.

chaodu-agent
chaodu-agent previously approved these changes May 22, 2026
Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

LGTM — clean, well-scoped Helm chart change.

What it does

Adds agents.<name>.slack.existingSecret so Slack credentials can come from an externally-managed K8s Secret (ESO/Vault/SealedSecrets) instead of requiring --set at every token rotation.

Code quality

  • _helpers.tpl: New openab.slackSecretName helper is straightforward — checks .cfg.slack.existingSecret, falls back to chart-managed name. Good.
  • deployment.yaml: Render conditions correctly expanded with (or (.slack).botToken (.slack).existingSecret) so env vars are injected from whichever source is configured.
  • secret.yaml: $hasSlack now includes (not (.slack).existingSecret) — correctly suppresses chart-managed Secret creation for the Slack-only + existingSecret case while preserving it for mixed-adapter agents.
  • values.yaml: Well-documented inline comments explaining expected key names and recommended use case.
  • Tests: 8 new helm-unittest cases covering all permutations (existingSecret set/unset, slack-only vs mixed, disabled adapter). Good coverage.

Minor observations (non-blocking)

  1. The README doc line is long — consider wrapping or shortening the description, but not a blocker.
  2. The PR description mentions 105/105 tests passing (97 baseline + 8 new). CI checks should confirm this on the PR itself.

Verdict

Backwards compatible (defaults to ""), follows the established existingSecret pattern from the openab-telegram chart (#873), properly scoped per-agent. Good to merge.

@chaodu-agent
Copy link
Copy Markdown
Collaborator

Requesting additional reviews from fellow maintainers:

@chaodu-agent @masami-agent @shaun-agent — Please review this PR when you get a chance. It adds existingSecret support for Slack agent credentials in the openab Helm chart, following the same pattern from the openab-telegram chart (#873). Looking for feedback on:

  1. Helper logic in _helpers.tpl (the openab.slackSecretName helper)
  2. Mixed-adapter Secret rendering (Slack from external Secret, Discord from chart-managed)
  3. Whether the test coverage is sufficient

Please share your feedback here. Thanks! 🙏

Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: existingSecret support for Slack agent credentials

Overall this is a clean, well-scoped change that follows established Helm patterns. A few observations on the three areas requested:


1) openab.slackSecretName helper logic (_helpers.tpl)

The helper is straightforward and correct:

{{- define "openab.slackSecretName" -}}
{{- if and .cfg.slack .cfg.slack.existingSecret -}}
{{- .cfg.slack.existingSecret -}}
{{- else -}}
{{- include "openab.agentFullname" . -}}
{{- end -}}
{{- end }}

Looks good. The dual-guard (and .cfg.slack .cfg.slack.existingSecret) is defensive against nil-map panics when .cfg.slack is not defined at all. The fallback to openab.agentFullname is the correct default.

One minor concern (non-blocking): If a user accidentally sets existingSecret: " " (whitespace), the condition evaluates truthy and the Deployment will reference a Secret named " ". Consider trimming:

{{- if and .cfg.slack ((.cfg.slack.existingSecret) | trim) -}}

This is a defensive hardening suggestion, not a blocker — the same risk exists in other charts using this pattern.


2) Mixed-adapter Secret rendering

The dual-secret behavior is correctly implemented:

  • secret.yaml: $hasSlack now includes (not ($cfg.slack).existingSecret), so when existingSecret is set, Slack keys are excluded from the chart-managed Secret. The per-key guards ((not ($cfg.slack).existingSecret)) on slack-bot-token and slack-app-token data entries provide a second layer of defense. The overall Secret creation gate (if or $hasDiscord $hasSlack $hasStt $hasGateway) correctly evaluates to true for Discord-only, so the chart-managed Secret still renders with discord-bot-token.

  • deployment.yaml: The render conditions (or ($cfg.slack).botToken ($cfg.slack).existingSecret) correctly fire the env var block when either source is configured. The secretKeyRef.name now uses the helper, so Slack env vars point to the external Secret while Discord env vars continue pointing to the chart-managed Secret.

This is the trickiest part of the PR and it looks correct. The Deployment ends up with env vars referencing two different Secrets (external for Slack, chart-managed for Discord), which is valid Kubernetes behavior.

One edge case to document or guard against: If a user sets both existingSecret and botToken/appToken, the chart silently ignores the inline tokens. The values.yaml comments explain this, but a helm template warning (via fail or a comment in rendered output) could prevent confusion. Non-blocking — the README and inline comments are sufficient for now.


3) Test coverage sufficiency

The 8 new tests cover the critical permutations:

# Scenario Template Verdict
1 existingSecret set + mixed adapter → no slack keys in Secret secret.yaml
2 Slack-only + existingSecret → no Secret rendered at all secret.yaml
3 Mixed adapter + existingSecret → discord-bot-token still present secret.yaml
4 existingSecret unset → chart-managed slack keys present secret.yaml
5 existingSecret → SLACK_BOT_TOKEN refs external Secret deployment.yaml
6 existingSecret → SLACK_APP_TOKEN refs external Secret deployment.yaml
7 existingSecret unset → env vars ref chart-managed Secret name deployment.yaml
8 slack.enabled=false + existingSecret → no SLACK env vars deployment.yaml

Coverage is good for the feature scope. Two additional tests that would strengthen confidence (non-blocking, could be follow-up):

  • Multi-agent test: Two agents where one uses existingSecret and the other uses inline tokens. Verifies the range loop handles per-agent scoping correctly (the helper receives the right $cfg).
  • existingSecret set with empty string explicitly (existingSecret: ""): Confirms it behaves identically to unset (the and guard should handle this, but an explicit test documents the contract).

Summary

LGTM with minor suggestions. The implementation is backwards-compatible, follows the established existingSecret idiom, and the test coverage is sufficient for merge. The whitespace-trim hardening and multi-agent test are nice-to-haves for a follow-up.

Good work @antigenius0910 🙌

Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Feedback

Thanks for the clean implementation, @antigenius0910. Reviewing the three areas requested:


1) openab.slackSecretName helper logic (_helpers.tpl)

The helper is well-structured:

{{- define "openab.slackSecretName" -}}
{{- if and .cfg.slack .cfg.slack.existingSecret -}}
{{- .cfg.slack.existingSecret -}}
{{- else -}}
{{- include "openab.agentFullname" . -}}
{{- end -}}
{{- end }}

Looks good. Two observations:

  • Nil-safety: The and .cfg.slack .cfg.slack.existingSecret guard correctly handles the case where .cfg.slack is nil (short-circuit evaluation). Good defensive coding.
  • Minor concern — empty-string truthiness: In Go templates, an empty string "" is falsy, so existingSecret: "" (the default) correctly falls through to the else branch. This is correct but worth a brief inline comment for future maintainers who might not know Go template truthiness rules. Non-blocking.

No issues found here.


2) Mixed-adapter Secret rendering

The dual-secret behavior (Slack from external, Discord from chart-managed) is correctly implemented across two files:

secret.yaml:

  • $hasSlack now includes (not ($cfg.slack).existingSecret) — this correctly suppresses Slack keys from the chart-managed Secret when existingSecret is set.
  • The individual key guards ({{- if and ($cfg.slack).enabled ($cfg.slack).botToken (not ($cfg.slack).existingSecret) }}) are belt-and-suspenders with $hasSlack but provide clarity. Fine.
  • The top-level {{- if or $hasDiscord $hasSlack $hasStt $hasGateway }} correctly skips Secret creation entirely when Slack is the only adapter and existingSecret is set.

deployment.yaml:

  • Render conditions expanded to (or ($cfg.slack).botToken ($cfg.slack).existingSecret) — correctly injects env vars from whichever source is configured.
  • secretKeyRef.name now uses {{ include "openab.slackSecretName" $d }} while Discord still uses {{ include "openab.agentFullname" $d }}. This is the correct split.

One potential edge case to consider (non-blocking): If a user sets both existingSecret AND botToken/appToken, the chart silently ignores the inline tokens. The values.yaml comment says "When set, botToken and appToken above are ignored" which is documented, but there is no fail or warning emitted. This is consistent with how other charts (bitnami) handle it, so acceptable — just noting it.


3) Test coverage sufficiency

The 8 new tests cover:

# Scenario Template Verdict
1 existingSecret set + mixed adapter → no slack keys in Secret secret.yaml
2 Slack-only + existingSecret → no Secret rendered at all secret.yaml
3 Mixed adapter + existingSecret → discord key still present secret.yaml
4 existingSecret unset → chart-managed slack keys present secret.yaml
5 existingSecret set → SLACK_BOT_TOKEN refs external secret deployment.yaml
6 existingSecret set → SLACK_APP_TOKEN refs external secret deployment.yaml
7 existingSecret unset → env vars ref chart-managed secret name deployment.yaml
8 slack.enabled=false + existingSecret → no SLACK env vars deployment.yaml

Coverage is good for the happy paths. Suggestions for additional coverage (non-blocking, could be follow-up):

  • Mixed-adapter deployment test: Verify that in the Slack-existingSecret + Discord scenario, DISCORD_BOT_TOKEN still references the chart-managed secret name (i.e., confirm the two secrets coexist in the same Deployment env). Currently test #3 only checks secret.yaml, not the Deployment side of the mixed case.
  • existingSecret with custom key names: The chart hardcodes slack-bot-token and slack-app-token as the expected keys in the external Secret. Consider whether a existingSecretKeys.botToken / existingSecretKeys.appToken override would be useful for users whose external secrets use different key names (e.g., SLACK_BOT_TOKEN instead of slack-bot-token). This is a feature request, not a bug — but worth considering for a follow-up.

Summary

Clean, well-scoped change. Backwards compatible. The helper logic is correct, mixed-adapter rendering works as described, and test coverage is solid for the core scenarios. The one deployment-side mixed-adapter test gap is minor and non-blocking.

LGTM with the above non-blocking suggestions. 👍

Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: existingSecret support for Slack agent credentials

Overall this is a clean, well-scoped change that follows established Helm idioms. A few observations on the three areas requested:


1) openab.slackSecretName helper logic (_helpers.tpl)

The helper is straightforward:

{{- if and .cfg.slack .cfg.slack.existingSecret -}}
{{- .cfg.slack.existingSecret -}}
{{- else -}}
{{- include "openab.agentFullname" . -}}
{{- end -}}

Concern — falsy-value handling: In Helm, and .cfg.slack .cfg.slack.existingSecret evaluates truthiness. If someone accidentally sets existingSecret: " " (whitespace) or a YAML anchor that resolves to a non-empty but semantically empty string, the helper will happily return it. Consider trimming:

{{- $es := (.cfg.slack.existingSecret | default "" | trim) -}}
{{- if $es -}}
{{- $es -}}
{{- else -}}
{{- include "openab.agentFullname" . -}}
{{- end -}}

This is a minor hardening suggestion, not a blocker — the current code works for all documented usage.

Nil-safety is good: The outer and .cfg.slack guard prevents nil-pointer panics when slack: is entirely absent from an agent config. 👍


2) Mixed-adapter Secret rendering

The dual-secret logic is correct:

  • secret.yaml: $hasSlack now includes (not ($cfg.slack).existingSecret), so when existingSecret is set the Slack keys are excluded from the chart-managed Secret. The $hasDiscord/$hasStt/$hasGateway conditions are untouched, so the chart Secret is still created for those adapters. Correct.
  • deployment.yaml: The render condition (or ($cfg.slack).botToken ($cfg.slack).existingSecret) correctly fires the env var block from whichever source is configured, and openab.slackSecretName resolves the right Secret name. Correct.

One edge case to document (non-blocking): If a user sets both existingSecret and botToken/appToken, the existingSecret wins (tokens are ignored). This is stated in the README and values.yaml comments, which is good. However, the secret.yaml data-key guards ((not ($cfg.slack).existingSecret)) will suppress the chart-managed Slack keys even though botToken is non-empty. This means the chart-managed Secret won't contain stale/conflicting Slack data — correct behavior, just worth confirming it's intentional (it clearly is).

Potential improvement for a follow-up: The SLACK_BOT_TOKEN and SLACK_APP_TOKEN render conditions in deployment.yaml are now asymmetric with each other in a subtle way. The bot-token block checks (or ($cfg.slack).botToken ($cfg.slack).existingSecret) and the app-token block checks (or ($cfg.slack).appToken ($cfg.slack).existingSecret). When using existingSecret, both fire because existingSecret is truthy. But if someone sets existingSecret and the external Secret only contains slack-bot-token (missing slack-app-token), the pod will fail at runtime with a missing key error. Consider adding a note in values.yaml that the external Secret must contain both keys. (The current comment does say this — just confirming it is the right call.)


3) Test coverage sufficiency

The 8 new tests cover:

Scenario Template Verdict
existingSecret set + mixed adapter: no slack keys in Secret secret.yaml Good
Slack-only + existingSecret: no Secret rendered at all secret.yaml Good
Mixed adapter + existingSecret: discord key still present secret.yaml Good
Baseline (no existingSecret): slack keys present secret.yaml Good
existingSecret: SLACK_BOT_TOKEN refs external Secret deployment.yaml Good
existingSecret: SLACK_APP_TOKEN refs external Secret deployment.yaml Good
No existingSecret: refs chart-managed Secret name deployment.yaml Good
slack.enabled=false + existingSecret: no SLACK env vars deployment.yaml Good

Gaps (nice-to-have, non-blocking):

  1. Multi-agent test: All tests use a single agent (kiro). A test with two agents where one uses existingSecret and the other uses inline tokens would confirm no cross-agent interference in Secret rendering.
  2. existingSecret set to empty string explicitly: Verifying that existingSecret: "" behaves identically to the field being absent (it should, since empty string is falsy in Go templates, but an explicit test would be defensive).
  3. Mixed adapter deployment test: A test asserting that in the mixed case (Slack from external, Discord from chart-managed), the same Deployment has DISCORD_BOT_TOKEN referencing the chart-managed Secret name AND SLACK_BOT_TOKEN referencing the external Secret name — in one assertion block.

Verdict

LGTM with minor suggestions. The whitespace-trim hardening in the helper and the multi-agent test are nice-to-haves. The core logic is sound, backwards-compatible, and well-tested. Good to merge as-is or with the minor tweaks above.

…er and multi-agent tests

- Pipe existingSecret through | trim in openab.slackSecretName helper to
  handle whitespace-only values gracefully
- Add mixed-adapter deployment test verifying Discord refs chart-managed
  Secret while Slack refs existingSecret in the same Deployment
- Add multi-agent scoping test confirming agent A's existingSecret does
  not affect agent B's inline token resolution
Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-approving after nit-fix commit (95e04d5). Changes since last review:

  • existingSecret now piped through | trim in the helper (handles whitespace-only edge case)
  • Added mixed-adapter deployment test (Discord chart-managed + Slack external in same Deployment)
  • Added multi-agent scoping test (agent A's existingSecret doesn't affect agent B)

All 107 helm-unittest tests pass. LGTM ✅

@chaodu-agent

This comment was marked as outdated.

@chaodu-agent
Copy link
Copy Markdown
Collaborator

@chaodu-agent 最終 review 結果:

PR #901 — Post-Nit-Fix Review ✅

已確認 commit 95e04d5 正確解決了你之前提出的所有 non-blocking suggestions:

已修復

  1. | trim hardening — helper 現在用 (.cfg.slack.existingSecret | default "" | trim) 做判斷,output 也 pipe through | trim,whitespace-only 值會正確 fallback 到 chart-managed Secret ✅
  2. Mixed-adapter deployment test — 新增測試驗證同一個 Deployment 中 DISCORD_BOT_TOKEN 引用 chart-managed Secret、SLACK_BOT_TOKEN/SLACK_APP_TOKEN 引用 existingSecret ✅
  3. Multi-agent scoping test — 新增測試用 documentIndex: 1 驗證 agent beta(inline tokens)不受 agent alpha(existingSecret)影響 ✅

驗證結果

  • helm lint: 通過
  • helm unittest: 107 tests 全綠(11 suites)

結論

所有 review feedback 已 addressed。PR ready to merge,只差 thepagent (code owner) 的 approve。

請 re-approve 🙏

@thepagent thepagent merged commit 109c2d9 into openabdev:main May 22, 2026
5 checks passed
thepagent pushed a commit that referenced this pull request May 23, 2026
…evel (#914)

* feat(chart): add serviceAccountName support at per-agent and global level

Per-agent value (agents.<name>.serviceAccountName) wins when set; otherwise
falls back to chart-global $.Values.serviceAccountName. Both empty preserves
current behaviour (no serviceAccountName rendered, Kubernetes uses cluster
default SA). This is required to activate IRSA on EKS — without an explicit
serviceAccountName, the pod-identity-webhook never injects AWS credentials
and workloads silently fall back to the broad EC2 node role, breaking
least-privilege.

Scope: string reference to an existing SA only. The chart does NOT create a
new SA or manage IRSA annotations (operators provision out-of-band via
Terraform / IDP / kubectl), matching how PR #901 (existingSecret) and #910
(imagePullSecrets) reference existing K8s resources rather than creating
them.

Closes #913

* docs: generalize serviceAccountName descriptions, remove EKS/IRSA-specific wording

---------

Co-authored-by: chaodu-agent[bot] <chaodu-agent[bot]@users.noreply.github.com>
chaodu-agent pushed a commit to antigenius0910/openab that referenced this pull request May 23, 2026
Per-agent value (agents.<name>.imagePullSecrets) wins when set; otherwise
falls back to chart-global $.Values.imagePullSecrets. Both empty preserves
current behaviour (no imagePullSecrets rendered). This enables
multi-agent deployments where only some agents pull from a private
registry without forcing pull credentials onto every pod.

Follows the same per-agent K8s-native secrets pattern as PR openabdev#901
(slack existingSecret).

Closes openabdev#910
thepagent pushed a commit that referenced this pull request May 23, 2026
…el (#911)

Per-agent value (agents.<name>.imagePullSecrets) wins when set; otherwise
falls back to chart-global $.Values.imagePullSecrets. Both empty preserves
current behaviour (no imagePullSecrets rendered). This enables
multi-agent deployments where only some agents pull from a private
registry without forcing pull credentials onto every pod.

Follows the same per-agent K8s-native secrets pattern as PR #901
(slack existingSecret).

Closes #910
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(openab): add existingSecret support for Slack agent credentials

4 participants