From 7d7c5539f9897ced30eb28eea53dbe0bdefead72 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Wed, 20 Aug 2025 11:54:41 -0700 Subject: [PATCH 1/5] fix(deploy): make --create-site flag always work without interaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/commands/deploy/deploy.ts | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 21c2df76123..1fd308237c2 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -926,15 +926,19 @@ const createSiteWithFlags = async (options: DeployOptionValues, command: BaseCom log(message) } - const siteData = await sitesCreate( - { - name: siteName, - accountSlug: options.team, - }, - command, - ) + // Create site directly via API to bypass interactive prompts + const { api } = command.netlify + const body: { name?: string } = {} + if (siteName) { + body.name = siteName.trim() + } + + const siteData = await api.createSiteInTeam({ + accountSlug: options.team!, + body, + }) site.id = siteData.id - return siteData + return siteData as SiteInfo } const promptForSiteAction = async (options: DeployOptionValues, command: BaseCommand, site: $TSFixMe) => { From 21b242d25419c11ffd19ecd36585a0d7f625c455 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Wed, 20 Aug 2025 12:05:38 -0700 Subject: [PATCH 2/5] fix(deploy): fix "Create & configure" option in interactive mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The interactive deploy prompt was incorrectly checking for a '+' prefix that didn't exist in the choice text, causing "Create & configure a new project" to always fall through to the link flow instead of creating a new site. Fixed by using proper constants and exact equality check, consistent with the init command pattern. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/commands/deploy/deploy.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 1fd308237c2..8016585bc5e 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -953,16 +953,19 @@ const promptForSiteAction = async (options: DeployOptionValues, command: BaseCom log(`\nYou must pick a --team: ${availableTeams.map((team) => team.slug).join(', ')}`) } + const NEW_SITE = '+ Create & configure a new project' + const EXISTING_SITE = '⇄ Link this directory to an existing project' + const { initChoice } = await inquirer.prompt([ { type: 'list', name: 'initChoice', message: 'What would you like to do?', - choices: ['Link this directory to an existing project', 'Create & configure a new project'], + choices: [EXISTING_SITE, NEW_SITE], }, ]) - const siteData = initChoice.startsWith('+') ? await sitesCreate({}, command) : await link({}, command) + const siteData = initChoice === NEW_SITE ? await sitesCreate({}, command) : await link({}, command) site.id = siteData.id return siteData From 0d55c5d386166b692ca0658ca446a1b9fcf7e490 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Wed, 20 Aug 2025 12:18:26 -0700 Subject: [PATCH 3/5] fix(deploy): remove non-null assertion and improve error handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace non-null assertion operator with proper error handling to fix ESLint violation. Also apply Prettier formatting fixes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/commands/deploy/deploy.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 8016585bc5e..37e71b764ae 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -932,9 +932,13 @@ const createSiteWithFlags = async (options: DeployOptionValues, command: BaseCom if (siteName) { body.name = siteName.trim() } - + + if (!options.team) { + throw new Error('Team must be specified to create a site') + } + const siteData = await api.createSiteInTeam({ - accountSlug: options.team!, + accountSlug: options.team, body, }) site.id = siteData.id From 601068d17fdea42c61e96654f318e7230b09690a Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Wed, 20 Aug 2025 12:22:45 -0700 Subject: [PATCH 4/5] refactor(deploy): use inquirer choice objects for robust option handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace brittle string matching with inquirer's choice objects pattern, separating display text from programmatic values. This prevents future breakage when display text changes and follows established codebase patterns. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/commands/deploy/deploy.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 37e71b764ae..dbcd4f800d4 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -957,19 +957,25 @@ const promptForSiteAction = async (options: DeployOptionValues, command: BaseCom log(`\nYou must pick a --team: ${availableTeams.map((team) => team.slug).join(', ')}`) } - const NEW_SITE = '+ Create & configure a new project' - const EXISTING_SITE = '⇄ Link this directory to an existing project' - const { initChoice } = await inquirer.prompt([ { type: 'list', name: 'initChoice', message: 'What would you like to do?', - choices: [EXISTING_SITE, NEW_SITE], + choices: [ + { + name: '⇄ Link this directory to an existing project', + value: 'link', + }, + { + name: '+ Create & configure a new project', + value: 'create', + }, + ], }, ]) - const siteData = initChoice === NEW_SITE ? await sitesCreate({}, command) : await link({}, command) + const siteData = initChoice === 'create' ? await sitesCreate({}, command) : await link({}, command) site.id = siteData.id return siteData From eb6628333f38cadb746b408116c7ea47056c8fe6 Mon Sep 17 00:00:00 2001 From: Mathias Biilmann Date: Wed, 20 Aug 2025 12:32:17 -0700 Subject: [PATCH 5/5] fix(deploy): add proper error handling for --create-site name conflicts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle 422 status code when site name is already taken, providing clear error messages instead of generic "JSONHTTPError: Unprocessable Entity". This improves the user experience for non-interactive site creation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/commands/deploy/deploy.ts | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index dbcd4f800d4..bc04e3ad17d 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -937,12 +937,23 @@ const createSiteWithFlags = async (options: DeployOptionValues, command: BaseCom throw new Error('Team must be specified to create a site') } - const siteData = await api.createSiteInTeam({ - accountSlug: options.team, - body, - }) - site.id = siteData.id - return siteData as SiteInfo + try { + const siteData = await api.createSiteInTeam({ + accountSlug: options.team, + body, + }) + site.id = siteData.id + return siteData as SiteInfo + } catch (error_) { + if ((error_ as APIError).status === 422) { + return logAndThrowError( + siteName + ? `Site name "${siteName}" is already taken. Please try a different name.` + : 'Unable to create site with a random name. Please try again or specify a different name.', + ) + } + return logAndThrowError(`Failed to create site: ${(error_ as APIError).status}: ${(error_ as APIError).message}`) + } } const promptForSiteAction = async (options: DeployOptionValues, command: BaseCommand, site: $TSFixMe) => {