From 40f8d3816e28e6ded6e4064d1960cd7e55c55cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Tue, 25 Nov 2025 15:21:42 +0000 Subject: [PATCH 1/3] feat: support skew protection token --- .claude/settings.local.json | 11 +++++++++ src/commands/deploy/deploy.ts | 23 +++++++++++++------ .../commands/deploy/deploy.test.ts | 11 +++++++-- 3 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000000..f966a03b1d8 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,11 @@ +{ + "permissions": { + "allow": [ + "Bash(npx vitest run:*)", + "Bash(npm run typecheck:*)", + "Bash(npm exec vitest:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 597ae23db12..3a5ad582ea9 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -680,15 +680,19 @@ const handleBuild = async ({ currentDir, defaultConfig, deployHandler, + deployId, options, packagePath, + skewProtectionToken, }: { cachedConfig: CachedConfig currentDir: string defaultConfig?: DefaultConfig | undefined deployHandler?: PatchedHandlerType | undefined + deployId?: string options: DeployOptionValues packagePath: string | undefined + skewProtectionToken?: string }) => { if (!options.build) { return {} @@ -703,6 +707,15 @@ const handleBuild = async ({ currentDir, deployHandler, }) + + if (deployId) { + resolvedOptions.deployId = deployId + } + + if (skewProtectionToken) { + resolvedOptions.skewProtectionToken = skewProtectionToken + } + const { configMutations, exitCode, newConfig, logs } = await runBuild(resolvedOptions) // Without this, the deploy command fails silently if (exitCode !== 0) { @@ -1112,13 +1125,7 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand) source_zip_filename?: string } const deployId = deployMetadata.id || '' - const deployUrl = deployMetadata.deploy_ssl_url || deployMetadata.deploy_url || '' - - command.netlify.cachedConfig.env.DEPLOY_ID = { sources: ['internal'], value: deployId } - command.netlify.cachedConfig.env.DEPLOY_URL = { sources: ['internal'], value: deployUrl } - - process.env.DEPLOY_ID = deployId - process.env.DEPLOY_URL = deployUrl + const skewProtectionToken = deployMetadata.skew_protection_token if ( options.uploadSourceZip && @@ -1157,6 +1164,8 @@ export const deploy = async (options: DeployOptionValues, command: BaseCommand) return {} }, + deployId, + skewProtectionToken, }) } catch (error) { // The build has failed, so let's cancel the deploy we created. diff --git a/tests/integration/commands/deploy/deploy.test.ts b/tests/integration/commands/deploy/deploy.test.ts index b454a74f9c3..4960dda2234 100644 --- a/tests/integration/commands/deploy/deploy.test.ts +++ b/tests/integration/commands/deploy/deploy.test.ts @@ -388,14 +388,16 @@ describe.skipIf(process.env.NETLIFY_TEST_DISABLE_LIVE === 'true').concurrent('co name: 'log-env', plugin: { async onPreBuild() { - const { DEPLOY_ID, DEPLOY_URL } = require('process').env + const { DEPLOY_ID, DEPLOY_URL, NETLIFY_SKEW_PROTECTION_TOKEN } = require('process').env console.log(`DEPLOY_ID_PREBUILD: ${DEPLOY_ID}`) console.log(`DEPLOY_URL_PREBUILD: ${DEPLOY_URL}`) + console.log(`NETLIFY_SKEW_PROTECTION_TOKEN_PREBUILD: ${NETLIFY_SKEW_PROTECTION_TOKEN}`) }, async onSuccess() { - const { DEPLOY_ID, DEPLOY_URL } = require('process').env + const { DEPLOY_ID, DEPLOY_URL, NETLIFY_SKEW_PROTECTION_TOKEN } = require('process').env console.log(`DEPLOY_ID: ${DEPLOY_ID}`) console.log(`DEPLOY_URL: ${DEPLOY_URL}`) + console.log(`NETLIFY_SKEW_PROTECTION_TOKEN: ${NETLIFY_SKEW_PROTECTION_TOKEN}`) }, }, }) @@ -424,8 +426,10 @@ describe.skipIf(process.env.NETLIFY_TEST_DISABLE_LIVE === 'true').concurrent('co t.expect(output).toContain('Netlify Build completed in') const [, deployIdPreBuild] = output.match(/DEPLOY_ID_PREBUILD: (\w+)/) ?? [] const [, deployURLPreBuild] = output.match(/DEPLOY_URL_PREBUILD: (.+)/) ?? [] + const [, skewProtectionTokenPreBuild] = output.match(/NETLIFY_SKEW_PROTECTION_TOKEN_PREBUILD: (.+)/) ?? [] const [, deployId] = output.match(/DEPLOY_ID: (\w+)/) ?? [] const [, deployURL] = output.match(/DEPLOY_URL: (.+)/) ?? [] + const [, skewProtectionToken] = output.match(/NETLIFY_SKEW_PROTECTION_TOKEN: (.+)/) ?? [] t.expect(deployIdPreBuild).toBeTruthy() t.expect(deployIdPreBuild).not.toEqual('0') @@ -433,6 +437,9 @@ describe.skipIf(process.env.NETLIFY_TEST_DISABLE_LIVE === 'true').concurrent('co t.expect(deployId).toEqual(deployIdPreBuild) t.expect(deployURL).toEqual(deployURLPreBuild) + t.expect(skewProtectionTokenPreBuild).toEqual(skewProtectionToken) + t.expect(skewProtectionToken).toBeTruthy() + await validateContent({ siteUrl: deployURL, path: '', content: rootContent }) await validateContent({ siteUrl: deployURL, path: '/edge-function', content: 'Hello from edge function' }) await validateContent({ siteUrl: deployURL, path: '/function', content: 'Hello from function' }) From 458c03ce4665c27c76470eec4dbf13be1b47c29a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Tue, 25 Nov 2025 15:22:29 +0000 Subject: [PATCH 2/3] chore: remove claude file --- .claude/settings.local.json | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index f966a03b1d8..00000000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(npx vitest run:*)", - "Bash(npm run typecheck:*)", - "Bash(npm exec vitest:*)" - ], - "deny": [], - "ask": [] - } -} From 980d9113b5e4e15ce71568125f5db3bd1549deba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20Bou=C3=A7as?= Date: Tue, 25 Nov 2025 15:39:55 +0000 Subject: [PATCH 3/3] refactor: move options to `getRunBuildOptions` --- src/commands/deploy/deploy.ts | 16 +++++----------- src/lib/build.ts | 6 ++++++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 3a5ad582ea9..3b79cacae42 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -700,22 +700,16 @@ const handleBuild = async ({ const [token] = await getToken() const resolvedOptions = await getRunBuildOptions({ cachedConfig, + currentDir, defaultConfig, + deployHandler, + deployId, + options, packagePath, + skewProtectionToken, token, - options, - currentDir, - deployHandler, }) - if (deployId) { - resolvedOptions.deployId = deployId - } - - if (skewProtectionToken) { - resolvedOptions.skewProtectionToken = skewProtectionToken - } - const { configMutations, exitCode, newConfig, logs } = await runBuild(resolvedOptions) // Without this, the deploy command fails silently if (exitCode !== 0) { diff --git a/src/lib/build.ts b/src/lib/build.ts index 899c5da8ddf..f15a8c538df 100644 --- a/src/lib/build.ts +++ b/src/lib/build.ts @@ -132,16 +132,20 @@ export const getRunBuildOptions = async ({ currentDir, defaultConfig, deployHandler, + deployId, options: { context, cwd, debug, dry, json, offline, silent }, packagePath, + skewProtectionToken, token, }: { cachedConfig: CachedConfig currentDir: string defaultConfig?: undefined | DefaultConfig deployHandler?: PatchedHandlerType + deployId?: string options: OptionValues packagePath?: string + skewProtectionToken?: string token?: null | string }): Promise => { const eventHandlers: { onEnd: EventHandler; onPostBuild?: EventHandler } = { @@ -170,6 +174,7 @@ export const getRunBuildOptions = async ({ return { cachedConfig, defaultConfig: defaultConfig ?? {}, + deployId, siteId: cachedConfig.siteInfo.id, accountId: cachedConfig.siteInfo.account_id, packagePath, @@ -191,6 +196,7 @@ export const getRunBuildOptions = async ({ // @ts-expect-error(serhalp) -- TODO(serhalp): Upstream the type fixes above into @netlify/build eventHandlers, edgeFunctionsBootstrapURL: await getBootstrapURL(), + skewProtectionToken, } }