Skip to content

Conversation

@pec1985
Copy link
Contributor

@pec1985 pec1985 commented Feb 9, 2026

Summary

Closes #896

  • Extends deployment.domains in agentuity.json to accept either a flat string[] (backward compatible) or a Record<string, string[]> mapping branch names to domain arrays
  • At deploy time, resolves the branch map to a flat array based on the current git branch
  • Adds --branch flag to agentuity project add domain for targeting specific branches

Example Configuration

{
  "deployment": {
    "domains": {
      "*": ["app.example.com", "www.example.com"],
      "staging": ["staging.example.com"],
      "dev": ["dev.example.com"]
    }
  }
}

Where * matches default branches (main/master) or is used when no branch is detected.

Changes

File Change
packages/server/src/api/project/deploy.ts DeploymentConfig.domains accepts z.union([array, record]) + exported DomainsConfig type
packages/cli/src/domain.ts Added resolveDomains() utility + DEFAULT_BRANCHES constant
packages/cli/src/cmd/cloud/deploy.ts Resolves branch-keyed domains early in handler (before fork/child split)
packages/cli/src/cmd/project/add/domain.ts Added --branch flag, extracted validateDNS() helper, auto-migrates flat array → * key

Resolution Logic

  1. Exact branch match → use those domains
  2. Current branch is main/master → fall back to * key
  3. No branch detected → fall back to * key
  4. No match → empty array (no custom domains)

Backward Compatibility

  • Flat string[] format works identically to before — zero behavior change
  • Server API contract unchanged — always receives a resolved flat string[]
  • agentuity project add domain foo.com (without --branch) still uses flat array format

Summary by CodeRabbit

  • New Features

    • Branch-specific domain configuration and an optional branch flag when managing domains.
    • Default-branch wildcard mapping for simpler domain setup across main/master.
  • Improvements

    • Centralized DNS validation with smarter prompting; skips validation when not applicable.
    • Deployment and CLI flows now normalize domains into a consistent flat format for reliable validation and reporting.
  • Tests

    • Added tests covering branch-keyed and flat-domain resolution scenarios.

@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

Adds branch-keyed domain support and resolution: introduces DEFAULT_BRANCHES and resolveDomains, persists domains as flat arrays or branch->array maps, applies early resolution in deploy flow, centralizes DNS validation, updates server schema/types, and adds tests for resolution behavior.

Changes

Cohort / File(s) Summary
Domain utilities
packages/cli/src/domain.ts
Adds DEFAULT_BRANCHES and resolveDomains to normalize a flat string[] or a branch-keyed Record<string,string[]> (including *) into a flat string[] for a given branch; preserves backward compatibility.
Deploy flow
packages/cli/src/cmd/cloud/deploy.ts
Resolves branch-keyed domains early into a flat array; replaces fragile nullable/union checks with robust array checks; skips DNS validation/prompt when resolved domains are empty; logs matched/no-match results.
Project add domain command
packages/cli/src/cmd/project/add/domain.ts
Adds centralized validateDNS helper; introduces branch-keyed domain storage and migration of existing flat arrays into *; updates handler and CLI schema to accept an optional branch option. (Public domainSubcommand signature extended to support branch option.)
Server API types
packages/server/src/api/project/deploy.ts
Changes DeploymentConfig.domains to `string[]
Tests
packages/cli/test/domain.test.ts
Adds tests for resolveDomains covering flat arrays, exact-branch matches, * wildcard fallback, default-branch handling, precedence, empty arrays, single-key maps, and verifies DEFAULT_BRANCHES.
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR fully implements all requirements from issue #896: branch-keyed domain mapping with backward compatibility, automatic migration, proper resolution logic with wildcard/default branch handling, and CLI support via --branch flag.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing branch-to-domain mapping: schema updates, new domain resolution utilities, deployment flow modifications, CLI enhancements, and comprehensive tests. No unrelated changes detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Feb 9, 2026

📦 Canary Packages Published

version: 1.0.4-919d16f

Packages
Package Version URL
@agentuity/frontend 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-frontend-1.0.4-919d16f.tgz
@agentuity/drizzle 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-drizzle-1.0.4-919d16f.tgz
@agentuity/opencode 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-opencode-1.0.4-919d16f.tgz
@agentuity/evals 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-evals-1.0.4-919d16f.tgz
@agentuity/workbench 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-workbench-1.0.4-919d16f.tgz
@agentuity/auth 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-auth-1.0.4-919d16f.tgz
@agentuity/react 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-react-1.0.4-919d16f.tgz
@agentuity/server 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-server-1.0.4-919d16f.tgz
@agentuity/postgres 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-postgres-1.0.4-919d16f.tgz
@agentuity/schema 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-schema-1.0.4-919d16f.tgz
@agentuity/runtime 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-runtime-1.0.4-919d16f.tgz
@agentuity/cli 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-cli-1.0.4-919d16f.tgz
@agentuity/core 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-core-1.0.4-919d16f.tgz
@agentuity/claude-code 1.0.4-919d16f https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-claude-code-1.0.4-919d16f.tgz
Install

Add to your package.json:

{
  "dependencies": {
    "@agentuity/frontend": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-frontend-1.0.4-919d16f.tgz",
    "@agentuity/drizzle": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-drizzle-1.0.4-919d16f.tgz",
    "@agentuity/opencode": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-opencode-1.0.4-919d16f.tgz",
    "@agentuity/evals": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-evals-1.0.4-919d16f.tgz",
    "@agentuity/workbench": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-workbench-1.0.4-919d16f.tgz",
    "@agentuity/auth": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-auth-1.0.4-919d16f.tgz",
    "@agentuity/react": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-react-1.0.4-919d16f.tgz",
    "@agentuity/server": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-server-1.0.4-919d16f.tgz",
    "@agentuity/postgres": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-postgres-1.0.4-919d16f.tgz",
    "@agentuity/schema": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-schema-1.0.4-919d16f.tgz",
    "@agentuity/runtime": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-runtime-1.0.4-919d16f.tgz",
    "@agentuity/cli": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-cli-1.0.4-919d16f.tgz",
    "@agentuity/core": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-core-1.0.4-919d16f.tgz",
    "@agentuity/claude-code": "https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-claude-code-1.0.4-919d16f.tgz"
  }
}

Or install directly:

bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-frontend-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-drizzle-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-opencode-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-evals-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-workbench-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-auth-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-react-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-server-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-postgres-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-schema-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-runtime-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-cli-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-core-1.0.4-919d16f.tgz
bun add https://agentuity-sdk-objects.t3.storageapi.dev/npm/1.0.4-919d16f/agentuity-claude-code-1.0.4-919d16f.tgz

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/cmd/project/add/domain.ts (1)

219-234: ⚠️ Potential issue | 🟠 Major

Data loss risk when adding domain without --branch to a branch-keyed config.

If project.deployment.domains is already a branch-keyed record (e.g., from prior --branch usage), this code treats it as an empty array, then overwrites the config at lines 243-252 with a flat array—losing all existing branch-keyed domains.

Scenario:

  1. Run project add domain staging.com --branch stagingdomains: { staging: ['staging.com'] }
  2. Run project add domain prod.com (no --branch) → existingDomains = [], then saves domains: ['prod.com']
  3. Branch configuration for staging is lost

Consider either:

  1. Erroring when domains is already a record and --branch is not specified
  2. Auto-adding to the '*' key when domains is a record
🐛 Suggested fix: Error or auto-migrate when domains is a record
 	// Original flat array mode
-	const existingDomains = Array.isArray(project.deployment?.domains)
-		? project.deployment.domains
-		: [];
+	// Check if domains is already branch-keyed - require --branch flag in that case
+	if (
+		project.deployment?.domains &&
+		!Array.isArray(project.deployment.domains)
+	) {
+		logger.fatal(
+			'Project uses branch-keyed domains. Use --branch to specify which branch to add this domain to (e.g., --branch "*" for default)',
+			ErrorCode.VALIDATION_FAILED
+		);
+	}
+
+	const existingDomains = Array.isArray(project.deployment?.domains)
+		? project.deployment.domains
+		: [];
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58ec943 and 4fcc160.

📒 Files selected for processing (4)
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/domain.ts
  • packages/server/src/api/project/deploy.ts
🧰 Additional context used
📓 Path-based instructions (6)
packages/server/src/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

packages/server/src/**/*.ts: All code must be written in TypeScript
Use zod for runtime validation of schemas and data

Files:

  • packages/server/src/api/project/deploy.ts
packages/server/src/api/**/*.ts

📄 CodeRabbit inference engine (packages/server/AGENTS.md)

Organize API clients by feature domain in src/api/ subdirectories (apikey, db, eval, org, project, queue, region, sandbox, session, thread, user)

Files:

  • packages/server/src/api/project/deploy.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for code formatting with tabs (width 3), single quotes, and semicolons

Files:

  • packages/server/src/api/project/deploy.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/server/src/api/project/deploy.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/server/src/api/project/deploy.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
🧠 Learnings (4)
📚 Learning: 2025-12-19T14:19:33.765Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 259
File: packages/cli/src/cmd/build/vite/registry-generator.ts:306-312
Timestamp: 2025-12-19T14:19:33.765Z
Learning: Route files under src/api should use the .ts extension only (no .tsx) and regex patterns for such paths should anchor to \.ts$ (e.g., /\/.ts$/). Agent files may support both .ts and .tsx, but route files in the Agentuity SDK codebase are restricted to .ts. This guideline applies to all similar route files under src/api across the repository.

Applied to files:

  • packages/server/src/api/project/deploy.ts
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/server/src/api/project/deploy.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
📚 Learning: 2025-12-30T00:13:37.849Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 355
File: packages/server/src/api/sandbox/util.ts:2-6
Timestamp: 2025-12-30T00:13:37.849Z
Learning: In the packages/server tree, treat code as runtime-agnostic between Node.js and Bun. Ensure TypeScript files (e.g., util.ts) import and use APIs in a way that works under both runtimes. It is acceptable to rely on Bun’s Node.js compatibility for built-ins accessed via the node: namespace (e.g., node:events, node:stream, node:buffer). During reviews, prefer patterns and imports that remain compatible with Bun's environment, and flag any hard dependencies on runtime-specific globals or non-portable Node APIs.

Applied to files:

  • packages/server/src/api/project/deploy.ts
📚 Learning: 2026-01-13T04:32:02.691Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 565
File: packages/cli/src/cmd/cloud/region-lookup.ts:14-26
Timestamp: 2026-01-13T04:32:02.691Z
Learning: Enforce sandbox identifier prefixes in new code within the CLI cloud region lookup: new sandboxes must use the sbx_ prefix. The snbx_ prefix may appear in legacy code or examples, but do not use snbx_ for new sandboxes. When reviewing changes in packages/cli/src/cmd/cloud/, ensure any created sandbox identifiers use sbx_ and remove or migrate any snbx_ usages in newly added code.

Applied to files:

  • packages/cli/src/cmd/cloud/deploy.ts
🧬 Code graph analysis (2)
packages/server/src/api/project/deploy.ts (3)
packages/server/src/index.ts (1)
  • z (30-30)
packages/schema/src/index.ts (1)
  • infer (182-182)
packages/cli/src/types.ts (1)
  • DeploymentConfig (10-10)
packages/cli/src/cmd/cloud/deploy.ts (2)
packages/cli/src/cmd/git/link.ts (1)
  • detectGitInfo (23-58)
packages/cli/src/domain.ts (1)
  • resolveDomains (57-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Template Integration Tests
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Build
  • GitHub Check: Pack & Upload
🔇 Additional comments (6)
packages/server/src/api/project/deploy.ts (1)

25-40: LGTM! Well-structured schema extension for branch-keyed domains.

The union type correctly allows both backward-compatible flat arrays and the new branch-keyed record format. The DomainsConfig type export using z.infer properly exposes the type for consumers. The description clearly documents the * wildcard key convention.

packages/cli/src/domain.ts (1)

38-84: LGTM! Clean implementation of branch-aware domain resolution.

The resolution logic correctly implements the PR requirements:

  1. Exact branch match
  2. Default branches (main/master) fall back to *
  3. No branch detected falls back to *
  4. No match returns empty array

One minor note: the JSDoc at lines 50-51 says "fall back to the '*' key" which might imply all non-matching branches fall back. The actual behavior is more nuanced (only default branches or no-branch scenarios fall back). Consider clarifying this for future maintainers, though the implementation is correct.

packages/cli/src/cmd/cloud/deploy.ts (2)

258-278: LGTM! Clean early resolution of branch-keyed domains.

The implementation correctly:

  • Only resolves when domains is a record (not already an array)
  • Uses the --branch flag or auto-detected git branch
  • Creates a new project object to avoid mutation
  • Provides clear debug logging for troubleshooting

558-584: LGTM! Domain validation step properly handles resolved domains.

The conditional step creation correctly skips validation when domains is empty or not properly resolved. The defensive Array.isArray check inside the callback is redundant given the outer condition, but adds safety without harm.

packages/cli/src/cmd/project/add/domain.ts (2)

12-79: LGTM! Well-structured DNS validation helper.

The validateDNS function properly:

  • Handles empty DNS service responses
  • Distinguishes between errors and misconfigured DNS
  • Provides clear user guidance with CNAME record details
  • Handles headless (non-TTY) environments appropriately
  • Offers interactive confirmation in TTY mode

163-217: LGTM! Branch-keyed mode implementation with proper migration.

The migration logic at lines 167-171 correctly handles:

  • Existing flat array with items → migrates to { '*': [...] }
  • Empty array → empty map
  • Existing record → uses as-is

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

…on (#896)

Allow the `deployment.domains` property in agentuity.json to accept
either a flat string array (backward compatible) or a branch-keyed
record mapping branch names to domain arrays.

At deploy time, domains are resolved to a flat array based on the
current git branch. The '*' key matches default branches (main/master)
or is used when no branch is detected.

- Update DeploymentConfig schema to accept union of array | record
- Add resolveDomains() utility for branch-based domain resolution
- Resolve domains early in deploy handler (before fork/child split)
- Add --branch flag to 'project add domain' command
- Auto-migrate existing flat array to '*' key when --branch is first used
@pec1985 pec1985 force-pushed the feat/branch-keyed-domains branch from 4fcc160 to ffd0a01 Compare February 9, 2026 14:58
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/cli/src/cmd/project/add/domain.ts (1)

219-238: ⚠️ Potential issue | 🟠 Major

Potential data loss when existing config uses branch-keyed domains.

If a project already has branch-keyed domains (a Record<string, string[]>) and the user runs agentuity project add domain foo.com without --branch, this code treats project.deployment?.domains as an empty array (line 220-222) and overwrites the entire branch-keyed map with a flat array (lines 243-252).

Consider either:

  1. Detecting an existing branch-keyed config and prompting the user to specify --branch, or
  2. Migrating to/merging with the * key similar to what the branch-keyed mode does
💡 Suggested fix: detect and handle existing branch-keyed config
+		// Check if existing config is branch-keyed (requires --branch to modify)
+		if (
+			project.deployment?.domains &&
+			!Array.isArray(project.deployment.domains) &&
+			typeof project.deployment.domains === 'object'
+		) {
+			logger.fatal(
+				'This project uses branch-keyed domain configuration. Use --branch to specify which branch to add the domain to.',
+				ErrorCode.VALIDATION_FAILED
+			);
+		}
+
 		// Original flat array mode
 		const existingDomains = Array.isArray(project.deployment?.domains)
 			? project.deployment.domains
 			: [];
🧹 Nitpick comments (1)
packages/cli/src/cmd/cloud/deploy.ts (1)

558-584: Redundant array check inside the DNS validation step.

The check at lines 566-570 (resolvedDomains && Array.isArray(resolvedDomains) && resolvedDomains.length) is redundant because the outer condition at lines 558-560 already ensures project.deployment.domains is a non-empty array before this step runs. Consider simplifying:

♻️ Suggested simplification
 								label: `Validate Custom ${tui.plural((project.deployment.domains as string[]).length, 'Domain', 'Domains')}`,
 								run: async () => {
-									const resolvedDomains = project.deployment?.domains;
-									if (
-										resolvedDomains &&
-										Array.isArray(resolvedDomains) &&
-										resolvedDomains.length
-									) {
+									const resolvedDomains = project.deployment!.domains as string[];
+									if (resolvedDomains.length) {
 										try {
 											await domain.promptForDNS(
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4fcc160 and ffd0a01.

📒 Files selected for processing (5)
  • packages/cli/src/cmd/cloud/deploy.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/domain.ts
  • packages/cli/test/domain.test.ts
  • packages/server/src/api/project/deploy.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/server/src/api/project/deploy.ts
🧰 Additional context used
📓 Path-based instructions (5)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/test/domain.test.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for code formatting with tabs (width 3), single quotes, and semicolons

Files:

  • packages/cli/test/domain.test.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/cli/test/domain.test.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
packages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/test/domain.test.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
packages/*/test/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/*/test/**/*.{ts,tsx}: Place test files in test/ folder, never in src/ or __tests__/
Import from ../src/ in test files
Use @agentuity/test-utils for mocks in tests

Files:

  • packages/cli/test/domain.test.ts
🧠 Learnings (2)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/test/domain.test.ts
  • packages/cli/src/domain.ts
  • packages/cli/src/cmd/project/add/domain.ts
  • packages/cli/src/cmd/cloud/deploy.ts
📚 Learning: 2026-01-13T04:32:02.691Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 565
File: packages/cli/src/cmd/cloud/region-lookup.ts:14-26
Timestamp: 2026-01-13T04:32:02.691Z
Learning: Enforce sandbox identifier prefixes in new code within the CLI cloud region lookup: new sandboxes must use the sbx_ prefix. The snbx_ prefix may appear in legacy code or examples, but do not use snbx_ for new sandboxes. When reviewing changes in packages/cli/src/cmd/cloud/, ensure any created sandbox identifiers use sbx_ and remove or migrate any snbx_ usages in newly added code.

Applied to files:

  • packages/cli/src/cmd/cloud/deploy.ts
🧬 Code graph analysis (3)
packages/cli/test/domain.test.ts (1)
packages/cli/src/domain.ts (2)
  • resolveDomains (57-84)
  • DEFAULT_BRANCHES (41-41)
packages/cli/src/cmd/project/add/domain.ts (6)
apps/testing/nextjs-app/agentuity/.agentuity/app.js (1)
  • projectId (131310-131310)
packages/cli/src/domain.ts (4)
  • checkCustomDomainForDNS (150-230)
  • isSuccess (102-104)
  • isError (94-96)
  • isMisconfigured (86-88)
packages/cli/src/index.ts (1)
  • ErrorCode (21-21)
packages/cli/src/tui.ts (1)
  • prompt (1790-1811)
packages/server/src/index.ts (1)
  • z (30-30)
packages/cli/src/config.ts (1)
  • updateProjectConfig (670-702)
packages/cli/src/cmd/cloud/deploy.ts (2)
packages/cli/src/cmd/git/link.ts (1)
  • detectGitInfo (23-58)
packages/cli/src/domain.ts (1)
  • resolveDomains (57-84)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: SDK Integration Test Suite
🔇 Additional comments (8)
packages/cli/src/domain.ts (2)

38-41: LGTM!

The DEFAULT_BRANCHES constant is well-documented and appropriately covers the common default branch names used in most Git workflows.


57-84: LGTM!

The resolveDomains function correctly implements the resolution logic as specified in the PR objectives:

  1. Backward compatible with flat arrays
  2. Exact branch match takes precedence
  3. Falls back to * for default branches (main/master) or when no branch is detected
  4. Returns empty array when no match is found

The non-null assertions are safe because key existence is verified with the in operator before access.

packages/cli/src/cmd/cloud/deploy.ts (1)

258-278: LGTM!

The early resolution of branch-keyed domains ensures consistent handling throughout the deployment flow. The approach correctly:

  • Detects when domains is a branch-keyed map (not an array)
  • Uses opts.branch override or auto-detected git branch
  • Updates the project object immutably with resolved flat array
  • Provides helpful debug logging for both matched and unmatched scenarios
packages/cli/src/cmd/project/add/domain.ts (3)

12-79: LGTM!

The validateDNS helper nicely centralizes DNS validation logic. Key strengths:

  • Defensive check for empty DNS service results
  • Clear error messages with guidance on --skip-validation
  • Proper distinction between headless and interactive modes
  • Safe non-null assertion after length check (since logger.fatal never returns)

101-108: LGTM!

Good additions to the CLI examples demonstrating both specific branch usage and the * wildcard for default/main branches. The schema description is clear.

Also applies to: 119-124


163-217: LGTM!

The branch-keyed mode implementation correctly:

  • Auto-migrates existing flat arrays to the * key when --branch is first used
  • Checks for duplicate domains within the target branch
  • Validates DNS unless --skip-validation is set
  • Updates the config with the new branch-keyed structure
packages/cli/test/domain.test.ts (2)

2-2: LGTM!

Import correctly updated to include the new exports being tested.


81-189: Excellent test coverage!

The test suite comprehensively covers all resolution scenarios:

  • Backward compatibility with flat arrays
  • Exact branch matching with precedence over wildcards
  • Wildcard * matching for default branches and null branch
  • No-match scenarios returning empty arrays
  • Edge cases with empty values and single keys
  • Verification of DEFAULT_BRANCHES constant

The tests align well with the implementation logic and PR objectives.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/cli/src/cmd/project/add/domain.ts`:
- Around line 192-199: When selectedBranch === NEW_BRANCH_OPTION, the value
returned from prompt.text (newBranch) can be an empty string which makes
branchKey falsy and later causes the code to fall back to flat-array mode,
corrupting branch-keyed config; fix by validating/trimming the prompt result
before assigning to branchKey (e.g. call prompt.text, trim the result, and if
it's empty re-prompt or throw a validation error) so branchKey is only set to a
non-empty string; ensure this logic surrounds the prompt.text call and affects
NEW_BRANCH_OPTION handling for selectedBranch.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ffd0a01 and 919d16f.

📒 Files selected for processing (1)
  • packages/cli/src/cmd/project/add/domain.ts
🧰 Additional context used
📓 Path-based instructions (5)
packages/cli/**/*.ts

📄 CodeRabbit inference engine (packages/cli/AGENTS.md)

Use Bun.file(f).exists() instead of existsSync(f) for file existence checks

Files:

  • packages/cli/src/cmd/project/add/domain.ts
**/*.{ts,tsx,js,jsx,json,md}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier with tabs (width 3), single quotes, and semicolons for code formatting

Files:

  • packages/cli/src/cmd/project/add/domain.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with ESNext target and bundler moduleResolution

Files:

  • packages/cli/src/cmd/project/add/domain.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use StructuredError from @agentuity/core for error handling

Files:

  • packages/cli/src/cmd/project/add/domain.ts
packages/cli/**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use commander.js framework for CLI implementation in the cli package

Files:

  • packages/cli/src/cmd/project/add/domain.ts
🧠 Learnings (1)
📚 Learning: 2025-12-21T00:31:41.858Z
Learnt from: jhaynie
Repo: agentuity/sdk PR: 274
File: packages/cli/src/cmd/build/vite/server-bundler.ts:12-41
Timestamp: 2025-12-21T00:31:41.858Z
Learning: In Bun runtime, BuildMessage and ResolveMessage are global types and are not exported from the bun module. Do not import { BuildMessage } from 'bun' or similar; these types are available globally and should be used without import. This applies to all TypeScript files that target the Bun runtime within the repository.

Applied to files:

  • packages/cli/src/cmd/project/add/domain.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Framework Integration Tests (TanStack & Next.js)
  • GitHub Check: Playwright E2E Smoke Test
  • GitHub Check: Queue CLI Tests
  • GitHub Check: Cloud Deployment Tests
  • GitHub Check: Package Installation & Usage Test
  • GitHub Check: SDK Integration Test Suite
  • GitHub Check: Standalone Agent Test
  • GitHub Check: Template Integration Tests
  • GitHub Check: Sandbox CLI Tests
  • GitHub Check: Build
  • GitHub Check: Pack & Upload
🔇 Additional comments (4)
packages/cli/src/cmd/project/add/domain.ts (4)

12-79: LGTM!

The validateDNS helper correctly centralizes DNS validation logic with proper handling for:

  • Empty results from the DNS service
  • Error responses
  • Misconfigured DNS with guidance
  • Interactive vs. headless mode differentiation

The non-null assertion at line 37 is safe since logger.fatal exits the process.


101-124: LGTM!

Good additions for branch support in the CLI schema - clear examples and well-documented option.


206-258: LGTM!

The branch-keyed mode logic correctly handles:

  • Migration of existing flat arrays to the * key
  • Duplicate domain detection per branch
  • DNS validation integration
  • Config update with merged map

The non-null assertion at line 256 is safe since we just assigned the value at line 235.


260-304: LGTM!

The flat array mode maintains backward compatibility and the logic is straightforward. The defensive check Array.isArray(...) ? ... : [] at line 261-263 is appropriate as a fallback.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +192 to +199
if (selectedBranch === NEW_BRANCH_OPTION) {
const newBranch = await prompt.text({
message: 'Enter branch name (use * for default/main branch):',
});
branchKey = newBranch;
} else {
branchKey = selectedBranch;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Empty branch name input can corrupt branch-keyed configuration.

If the user enters an empty string when prompted for a new branch name, branchKey becomes "" (falsy). The subsequent if (branchKey) check at line 206 will be false, causing the code to fall through to flat array mode. This will overwrite the existing branch-keyed Record with a flat array, corrupting the configuration.

🐛 Proposed fix: validate branch name is not empty
 			if (selectedBranch === NEW_BRANCH_OPTION) {
 				const newBranch = await prompt.text({
 					message: 'Enter branch name (use * for default/main branch):',
+					validate: (value) => {
+						if (!value || !value.trim()) {
+							return 'Branch name cannot be empty';
+						}
+						return true;
+					},
 				});
-				branchKey = newBranch;
+				branchKey = newBranch.trim();
 			} else {
 				branchKey = selectedBranch;
 			}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (selectedBranch === NEW_BRANCH_OPTION) {
const newBranch = await prompt.text({
message: 'Enter branch name (use * for default/main branch):',
});
branchKey = newBranch;
} else {
branchKey = selectedBranch;
}
if (selectedBranch === NEW_BRANCH_OPTION) {
const newBranch = await prompt.text({
message: 'Enter branch name (use * for default/main branch):',
validate: (value) => {
if (!value || !value.trim()) {
return 'Branch name cannot be empty';
}
return true;
},
});
branchKey = newBranch.trim();
} else {
branchKey = selectedBranch;
}
🤖 Prompt for AI Agents
In `@packages/cli/src/cmd/project/add/domain.ts` around lines 192 - 199, When
selectedBranch === NEW_BRANCH_OPTION, the value returned from prompt.text
(newBranch) can be an empty string which makes branchKey falsy and later causes
the code to fall back to flat-array mode, corrupting branch-keyed config; fix by
validating/trimming the prompt result before assigning to branchKey (e.g. call
prompt.text, trim the result, and if it's empty re-prompt or throw a validation
error) so branchKey is only set to a non-empty string; ensure this logic
surrounds the prompt.text call and affects NEW_BRANCH_OPTION handling for
selectedBranch.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support branch-to-domain mapping in deployment configuration

1 participant