Skip to content

feat(project): create multiple projects in one command#1191

Open
betegon wants to merge 11 commits into
mainfrom
fix/project-create-multiple
Open

feat(project): create multiple projects in one command#1191
betegon wants to merge 11 commits into
mainfrom
fix/project-create-multiple

Conversation

@betegon

@betegon betegon commented Jul 3, 2026

Copy link
Copy Markdown
Member

Summary

sentry project create can create several projects in one command by accepting project names as variadic positional arguments. The trailing positional is the platform, or the platform can be supplied with --platform / -p.

This also tightens the input and output contracts found while reviewing the original CLI-1YY scenario: quoted display names and commas are preserved as one project name, unrelated API 400 responses remain ApiErrors, and multi-project JSON is emitted as one parseable array.

Usage

# Create one project (existing form remains supported)
sentry project create my-app node

# A quoted multi-word display name is one project
sentry project create "My App" node

# Create three projects with the same platform
sentry project create web api worker node

# Equivalent form with an explicit platform flag
sentry project create web api worker --platform node

# Resolve the organization explicitly; all names use the same org
sentry project create acme/web api worker node

# Commas are preserved as part of a single display name
sentry project create payments,eu node

# A batch is returned as one JSON array
sentry project create web api worker node --json

The distinction is based on shell arguments, not string contents:

  • "Web API" is one display name and becomes a slug such as web-api.
  • web api is two project names.
  • payments,eu remains one project name; commas do not split positionals.

What changed

  • Resolves the platform from the trailing positional while keeping --platform as an alternative.
  • Creates projects sequentially under one organization and shares auto-created team selection across the batch.
  • Preserves the historical JSON object for a single project; complete and partial batches use one JSON array.
  • Emits projects created before a later failure, then returns the original error, so retries do not hide partial mutations.
  • Uses Stricli customUsage so native help, sentry help, generated docs, and the bundled skill show the required platform syntax.
  • Removes comma splitting and the heuristic that reclassified any API 400 for a multi-word display name.

Test plan

  • pnpm exec vitest run test/commands/project/create.test.ts test/lib/command.test.ts test/lib/introspect.test.ts test/lib/help-positional.test.ts test/script/generate-skill-markdown.test.ts — 170 passed.
  • pnpm run typecheck
  • pnpm run lint
  • pnpm run check:errors
  • pnpm run check:fragments
  • pnpm run check:deps

The full unit run reached 8,413 passing tests. Its remaining failures are outside this diff: the API-schema and shell-completion failures reproduce on the original PR head, timezone-sensitive cases pass with TZ=UTC, and the untouched wizard auth test has a pre-existing async race.

Related Sentry issue: CLI-1YY

…names

Names are now variadic (like issue merge): `sentry project create web api
worker node` creates three projects; the trailing arg is the platform, or
use --platform. `create <name> <platform>` still works. When a single name
has spaces and the API 400s, the error points to the variadic form instead
of a cryptic HTTP 400. Fixes the cause of Sentry CLI-1YY.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://cli.sentry.dev/_preview/pr-1191/

Built to branch gh-pages at 2026-07-14 18:51 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Codecov Results 📊

✅ Patch coverage is 92.86%. Project has 5366 uncovered lines.
✅ Project coverage is 81.8%. Comparing base (base) to head (head).

Files with missing lines (2)
File Patch % Lines
src/commands/project/create.ts 92.00% ⚠️ 6 Missing and 7 partials
script/generate-skill-markdown.ts 100.00% ⚠️ 1 partials
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    81.77%    81.80%    +0.03%
==========================================
  Files          424       425        +1
  Lines        29452     29487       +35
  Branches     19190     19221       +31
==========================================
+ Hits         24085     24121       +36
- Misses        5367      5366        -1
- Partials      1999      2006        +7

Generated by Codecov Action

Match the sibling error-builders (buildPlatformError, isPlatformError)
which annotate their return types.

Co-authored-by: Cursor <cursoragent@cursor.com>
@betegon betegon marked this pull request as ready for review July 3, 2026 14:31
@github-actions github-actions Bot added the risk: medium PR risk score: medium label Jul 3, 2026
Comment thread src/commands/project/create.ts Outdated
Pair `project create` with the CLI's multi-value flag convention
(`--features a,b`, set-commits `--path a,b`, `auth login --scope a,b`):
each positional name may now also be comma-separated, so
`create web,api,worker node` == `create web api worker node`. Commas
are never valid in a slug, so this is unambiguous and prevents an agent
comma-habit (`a,b,c`) from silently creating one `a-b-c` project.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/commands/project/create.ts Outdated
betegon and others added 2 commits July 3, 2026 16:50
Positionals are space-separated variadic (also comma-tolerant); optional
flags are comma-separated. Splits the rule by argument type so agents pick
the right shape.

Co-authored-by: Cursor <cursoragent@cursor.com>
USAGE_HINT now reflects variadic names + platform ([<org>/]<name...>
<platform>). The crammed-name 400 message no longer asserts names "can't
span multiple words" (the 400 may be a length issue), instead framing
both the multi-project and single-project fixes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread src/commands/project/create.ts Outdated
resolvePlatformAndNames passed only args[0] to buildPlatformError, so a
bad platform with multiple names (`create proj1 proj2 bad`) hinted just
`proj1`. Echo the full name list per branch so the usage example matches
what was typed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions github-actions Bot added risk: high PR risk score: high and removed risk: medium PR risk score: medium labels Jul 3, 2026
Comment thread src/commands/project/create.ts Outdated
In multi-project create, the auto-create team slug is now pinned to the
first project for the whole batch. A real run already creates one team on
the first project and reuses it; dry-run previews now agree instead of
showing a divergent "would create team" per project in an empty org.

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3ea97b8. Configure here.

Comment thread src/commands/project/create.ts
Comment thread src/commands/project/create.ts
betegon and others added 3 commits July 3, 2026 17:42
createProjectWithAutoTeamFallback rethrew 400s unchanged, so a crammed
multi-word name that reached the org-scoped fallback (after a team-scoped
403) still surfaced the raw API error. Apply the same actionable guidance
there.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Extract projectExistsError() so the 409 "already exists" message + view
  hint live in one place (was duplicated across the team and org-scoped
  fallback paths).
- Pass a field to the multi-org ValidationError so error-reporting doesn't
  collapse it into the unfielded fingerprint.
- Use USAGE_HINT for the missing-name error instead of a stale hardcoded
  usage string.

Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve quoted display names, commas, and unrelated API 400 errors instead of inferring extra project names from content. Keep batch JSON parseable, surface partial successes, and align native/generated help with the actual platform syntax.
@betegon betegon changed the title fix(project): create multiple projects; clear error on space-crammed names feat(project): create multiple projects in one command Jul 14, 2026
Comment on lines 307 to 313
);
}
if (expError.status === 409) {
const slug = slugify(name);
throw new CliError(
`A project named '${name}' already exists in ${orgSlug}.\n\n` +
`View it: sentry project view ${orgSlug}/${slug}`
);
throw projectExistsError(orgSlug, name);
}
}
throw expError;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Bug: The fallback project creation function createProjectWithAutoTeamFallback does not use the new handleCreateApiError handler, leading to inconsistent error messages compared to the primary creation path.
Severity: LOW

Suggested Fix

Wrap the API call within createProjectWithAutoTeamFallback in a try...catch block that invokes handleCreateApiError. This ensures consistent and robust error handling for platform-related API errors across both the primary and fallback creation paths.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/commands/project/create.ts#L307-L313

Potential issue: The new `handleCreateApiError` function, which provides improved error
messages for API 400 errors, is utilized in the primary project creation path but not in
the `createProjectWithAutoTeamFallback` function. This fallback path is executed when
the initial team-based creation fails with a 403 error. This code asymmetry results in
inconsistent error handling. If a platform-related 400 error were to occur in this
fallback scenario, the user would receive a generic error message instead of the
intended actionable guidance. While client-side validation makes this specific error
unlikely, it represents an incomplete implementation.

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

Labels

risk: high PR risk score: high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant