Skip to content
Open
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
7 changes: 6 additions & 1 deletion src/commands/base-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,10 @@ export default class BaseCommand extends Command {
siteData = result
}

if (siteData.id) {
actionCommand.siteId = siteData.id
}

const globalConfig = await getGlobalConfigStore()

// ==================================================
Expand Down Expand Up @@ -769,10 +773,11 @@ export default class BaseCommand extends Command {
root: buildDir,
configPath,
get id() {
return state.get('siteId')
return actionCommand.siteId || state.get('siteId')
},
set id(id) {
state.set('siteId', id)
actionCommand.siteId = id
Comment on lines +776 to +780
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.

⚠️ Potential issue | 🟠 Major

Don't let netlify.site.id return an unresolved site name.

Line 772 now prefers actionCommand.siteId, but that field is seeded from both --site and --site-id. In this file, only flags.site goes through the later getSiteByName() fallback, so --site-id my-site-name can still make netlify.site.id return "my-site-name" instead of the canonical site ID. That means the new alias will still fail anywhere downstream expects an actual ID.

Suggested fix
-    let siteData = siteInfo
-    if (!siteData.url && flags.site) {
-      const result = await getSiteByName(api, flags.site)
+    let siteData = siteInfo
+    const siteSelector =
+      typeof flags.siteId === 'string' ? flags.siteId : typeof flags.site === 'string' ? flags.site : undefined
+    if (!siteData.url && siteSelector) {
+      const result = await getSiteByName(api, siteSelector)
       if (result == null) {
-        return logAndThrowError(`Project with name "${flags.site}" not found`)
+        return logAndThrowError(`Project with name "${siteSelector}" not found`)
       }
       siteData = result
+      actionCommand.siteId = result.id
     }
         get id() {
-          return actionCommand.siteId || state.get('siteId')
+          return siteData?.id || actionCommand.siteId || state.get('siteId')
         },
πŸ€– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/commands/base-command.ts` around lines 772 - 776, The getter for
netlify.site.id currently returns actionCommand.siteId first, which can contain
an unresolved site name seeded from --site or --site-id; change the logic so the
canonical ID from state.get('siteId') is preferred (state.get('siteId') ||
actionCommand.siteId) or ensure any assignment to actionCommand.siteId (from
flags.site or flags['site-id']) is normalized by calling getSiteByName(...) and
storing the resolved site.id before returning; update the getter and the code
path that sets actionCommand.siteId (or the setter id) so actionCommand.siteId
never holds an unresolved site name.

},
},
// Site information retrieved using the API (api.getSite())
Expand Down
5 changes: 5 additions & 0 deletions src/commands/env/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const createEnvCommand = (program: BaseCommand) => {
)
.option('--json', 'Output environment variables as JSON')
.option('--site <name-or-id>', 'A project name or ID to target')
.addOption(new Option('--site-id <name-or-id>').hideHelp(true))
Comment thread
coderabbitai[bot] marked this conversation as resolved.
.addOption(
new Option('-s, --scope <scope>', 'Specify a scope')
.choices(['builds', 'functions', 'post-processing', 'runtime', 'any'])
Expand Down Expand Up @@ -47,6 +48,7 @@ export const createEnvCommand = (program: BaseCommand) => {
)
.option('--json', 'Output environment variables as JSON')
.option('-s, --site <name-or-id>', 'A project name or ID to target')
.addOption(new Option('--site-id <name-or-id>').hideHelp(true))
.description('Import and set environment variables from .env file')
.action(async (fileName: string, options: OptionValues, command: BaseCommand) => {
const { envImport } = await import('./env-import.js')
Expand All @@ -63,6 +65,7 @@ export const createEnvCommand = (program: BaseCommand) => {
)
.option('--json', 'Output environment variables as JSON')
.option('--site <name-or-id>', 'A project name or ID to target')
.addOption(new Option('--site-id <name-or-id>').hideHelp(true))
.addOption(new Option('--plain', 'Output environment variables as plaintext').conflicts('json'))
.addOption(
new Option('-s, --scope <scope>', 'Specify a scope')
Expand Down Expand Up @@ -94,6 +97,7 @@ export const createEnvCommand = (program: BaseCommand) => {
)
.option('--json', 'Output environment variables as JSON')
.option('--site <name-or-id>', 'A project name or ID to target')
.addOption(new Option('--site-id <name-or-id>').hideHelp(true))
.addOption(
new Option('-s, --scope <scope...>', 'Specify a scope (default: all scopes)').choices([
'builds',
Expand Down Expand Up @@ -131,6 +135,7 @@ export const createEnvCommand = (program: BaseCommand) => {
)
.option('--json', 'Output environment variables as JSON')
.option('-s, --site <name-or-id>', 'A project name or ID to target')
.addOption(new Option('--site-id <name-or-id>').hideHelp(true))
.addExamples([
'netlify env:unset VAR_NAME # unset in all contexts',
'netlify env:unset VAR_NAME --context production',
Expand Down
Loading