From 7ea3e7b70a42b4b911d8fbd966fe0d223ee0b5e6 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Tue, 10 Dec 2024 18:37:31 +0100 Subject: [PATCH 1/6] fix: catch and ignore .kill exceptions and don't force timeout kill in windows (#5932) --- packages/build/src/plugins/spawn.ts | 17 +++++++++++++++-- packages/edge-bundler/node/server/util.ts | 19 ++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/packages/build/src/plugins/spawn.ts b/packages/build/src/plugins/spawn.ts index 75073ad482..7e67a30a52 100644 --- a/packages/build/src/plugins/spawn.ts +++ b/packages/build/src/plugins/spawn.ts @@ -1,10 +1,11 @@ import { createRequire } from 'module' +import { platform } from 'os' import { fileURLToPath, pathToFileURL } from 'url' import { promisify } from 'util' import { trace } from '@opentelemetry/api' import { ExecaChildProcess, execaNode } from 'execa' -import { gte } from 'semver' +import { gte, satisfies } from 'semver' import { FeatureFlags } from '../core/feature_flags.js' import { addErrorInfo } from '../error/info.js' @@ -217,5 +218,17 @@ const stopPlugin = async function ({ }) childProcess.disconnect() } - childProcess.kill() + + // On Windows with Node 21+, there's a bug where attempting to kill a child process + // results in an EPERM error. Ignore the error in that case. + // See: https://github.com/nodejs/node/issues/51766 + // We also disable execa's `forceKillAfterTimeout` in this case + // which can cause unhandled rejection. + try { + childProcess.kill('SIGTERM', { + forceKillAfterTimeout: platform() === 'win32' && satisfies(process.version, '>=21') ? false : undefined, + }) + } catch { + // no-op + } } diff --git a/packages/edge-bundler/node/server/util.ts b/packages/edge-bundler/node/server/util.ts index 058018456a..e3c416c634 100644 --- a/packages/edge-bundler/node/server/util.ts +++ b/packages/edge-bundler/node/server/util.ts @@ -1,6 +1,9 @@ +import { platform } from 'os' + import { ExecaChildProcess } from 'execa' import fetch from 'node-fetch' import waitFor from 'p-wait-for' +import { satisfies } from 'semver' // 1 second const SERVER_KILL_TIMEOUT = 1e3 @@ -43,9 +46,19 @@ const killProcess = (ps: ExecaChildProcess) => { ps.on('close', resolve) ps.on('error', reject) - ps.kill('SIGTERM', { - forceKillAfterTimeout: SERVER_KILL_TIMEOUT, - }) + // On Windows with Node 21+, there's a bug where attempting to kill a child process + // results in an EPERM error. Ignore the error in that case. + // See: https://github.com/nodejs/node/issues/51766 + // We also disable execa's `forceKillAfterTimeout` in this case + // which can cause unhandled rejection. + try { + ps.kill('SIGTERM', { + forceKillAfterTimeout: + platform() === 'win32' && satisfies(process.version, '>=21') ? false : SERVER_KILL_TIMEOUT, + }) + } catch { + // no-op + } }) } From cc677e9c50a552a6a027e061be09671ab2352e03 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:10:33 +0000 Subject: [PATCH 2/6] fix(deps): update dependency @netlify/serverless-functions-api to ^1.31.1 (#5923) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- packages/zip-it-and-ship-it/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 179f159be8..8f20e6b754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6690,9 +6690,9 @@ "link": true }, "node_modules/@netlify/serverless-functions-api": { - "version": "1.31.0", - "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-1.31.0.tgz", - "integrity": "sha512-/ux3fefmw0yGmzRMOqhGrzbAuALtW8HY08bjE4yCk+y8CzB9r9mPd1ApSJe3KlYD+sqDvbQGrEXdifQ/LzUIDQ==", + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/@netlify/serverless-functions-api/-/serverless-functions-api-1.31.1.tgz", + "integrity": "sha512-SkNxzfCwctS5ETnCqJOJfZZ/jB0pTkbWEAsApHoL7HzUQGWoRM6wYf4baJAJVMTfZBQu534SbKuwRs7WDAs43A==", "license": "MIT", "dependencies": { "@netlify/node-cookies": "^0.1.0", @@ -27616,7 +27616,7 @@ "@babel/parser": "^7.22.5", "@babel/types": "7.25.6", "@netlify/binary-info": "^1.0.0", - "@netlify/serverless-functions-api": "^1.31.0", + "@netlify/serverless-functions-api": "^1.31.1", "@vercel/nft": "^0.27.1", "archiver": "^7.0.0", "common-path-prefix": "^3.0.0", diff --git a/packages/zip-it-and-ship-it/package.json b/packages/zip-it-and-ship-it/package.json index 8e2ef3d2de..86835b4190 100644 --- a/packages/zip-it-and-ship-it/package.json +++ b/packages/zip-it-and-ship-it/package.json @@ -44,7 +44,7 @@ "@babel/parser": "^7.22.5", "@babel/types": "7.25.6", "@netlify/binary-info": "^1.0.0", - "@netlify/serverless-functions-api": "^1.31.0", + "@netlify/serverless-functions-api": "^1.31.1", "@vercel/nft": "^0.27.1", "archiver": "^7.0.0", "common-path-prefix": "^3.0.0", From 3a2da9937eb859d52de9d0e1ef5ea8a0a76af35a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 10 Dec 2024 18:31:35 +0000 Subject: [PATCH 3/6] fix(deps): update dependency @netlify/open-api to ^2.35.0 (#5928) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 8 ++++---- packages/js-client/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8f20e6b754..599f6509d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6660,9 +6660,9 @@ } }, "node_modules/@netlify/open-api": { - "version": "2.34.0", - "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.34.0.tgz", - "integrity": "sha512-C4v7Od/vnGgZ1P4JK3Fn9uUi9HkTxeUqUtj4OLnGD+rGyaVrl4JY89xMCoVksijDtO8XylYFU59CSTnQNeNw7g==", + "version": "2.35.0", + "resolved": "https://registry.npmjs.org/@netlify/open-api/-/open-api-2.35.0.tgz", + "integrity": "sha512-c6LpV29CKMgq6/eViItE6L2ova9UldBO9tHRvvwpJfSBgCwWaFhmiepe07E3xIW4GfTCGoWE816mNzXB/2ceZg==", "license": "MIT", "engines": { "node": ">=14" @@ -27293,7 +27293,7 @@ "version": "13.1.21", "license": "MIT", "dependencies": { - "@netlify/open-api": "^2.34.0", + "@netlify/open-api": "^2.35.0", "lodash-es": "^4.17.21", "micro-api-client": "^3.3.0", "node-fetch": "^3.0.0", diff --git a/packages/js-client/package.json b/packages/js-client/package.json index 65c132544f..a2e876746f 100644 --- a/packages/js-client/package.json +++ b/packages/js-client/package.json @@ -41,7 +41,7 @@ "node client" ], "dependencies": { - "@netlify/open-api": "^2.34.0", + "@netlify/open-api": "^2.35.0", "lodash-es": "^4.17.21", "micro-api-client": "^3.3.0", "node-fetch": "^3.0.0", From ebfc770ba1a9ded15895fbc1d46caf2bf9ced34d Mon Sep 17 00:00:00 2001 From: Jake Champion Date: Tue, 10 Dec 2024 18:52:06 +0000 Subject: [PATCH 4/6] fix: ensure we pass an ArrayBuffer to blobStore.set and not a NodeJS Buffer (#5927) * fix: ensure we pass an ArrayBufferLike to blobStore.set and not a NodeJS Buffer * fix: use buffer.slice to create ArrayBuffer --------- Co-authored-by: Yujohn Nattrass --- packages/build/src/plugins_core/blobs_upload/index.ts | 3 ++- packages/build/src/plugins_core/dev_blobs_upload/index.ts | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/build/src/plugins_core/blobs_upload/index.ts b/packages/build/src/plugins_core/blobs_upload/index.ts index b7d76a52a7..7ee7596146 100644 --- a/packages/build/src/plugins_core/blobs_upload/index.ts +++ b/packages/build/src/plugins_core/blobs_upload/index.ts @@ -72,7 +72,8 @@ const coreStep: CoreStepFunction = async function ({ systemLog(`Uploading blob ${key}`) const { data, metadata } = await getFileWithMetadata(key, contentPath, metadataPath) - await blobStore.set(key, data, { metadata }) + const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.length) + await blobStore.set(key, arrayBuffer, { metadata }) }, { concurrency: 10 }, ) diff --git a/packages/build/src/plugins_core/dev_blobs_upload/index.ts b/packages/build/src/plugins_core/dev_blobs_upload/index.ts index 525a8066b2..2b7a645067 100644 --- a/packages/build/src/plugins_core/dev_blobs_upload/index.ts +++ b/packages/build/src/plugins_core/dev_blobs_upload/index.ts @@ -77,7 +77,8 @@ const coreStep: CoreStepFunction = async function ({ log(logs, `- Uploading blob ${key}`, { indent: true }) } const { data, metadata } = await getFileWithMetadata(key, contentPath, metadataPath) - await blobStore.set(key, data, { metadata }) + const arrayBuffer = data.buffer.slice(data.byteOffset, data.byteOffset + data.length) + await blobStore.set(key, arrayBuffer, { metadata }) }, { concurrency: 10 }, ) From 736676194b4d0c4ec66ced7c92efaabeec74d3d7 Mon Sep 17 00:00:00 2001 From: Sarah Etter Date: Tue, 10 Dec 2024 14:10:43 -0500 Subject: [PATCH 5/6] chore: remove released feature flag for extensions/ future state (#5926) * chore: remove released feature flag for future state v2 * chore: format * chore: tests * test: modify tests * fix: convert normalize case file to typescript to make the build not take 4 minutes * chore: change test name --- packages/config/src/api/site_info.ts | 47 ++---------- packages/config/src/{case.js => case.ts} | 14 +++- packages/config/tests/api/tests.js | 96 ++++++++++-------------- 3 files changed, 55 insertions(+), 102 deletions(-) rename packages/config/src/{case.js => case.ts} (68%) diff --git a/packages/config/src/api/site_info.ts b/packages/config/src/api/site_info.ts index 699219768d..4ac6db793e 100644 --- a/packages/config/src/api/site_info.ts +++ b/packages/config/src/api/site_info.ts @@ -35,53 +35,18 @@ export const getSiteInfo = async function ({ context, offline = false, testOpts = {}, - featureFlags = {}, siteFeatureFlagPrefix, }: GetSiteInfoOpts) { const { env: testEnv = false } = testOpts - const useV2Endpoint = !!accountId && featureFlags.cli_integration_installations_meta - - if (useV2Endpoint) { - if (api === undefined || mode === 'buildbot' || testEnv) { - const siteInfo: { id?: string; account_id?: string } = {} - - if (siteId !== undefined) siteInfo.id = siteId - if (accountId !== undefined) siteInfo.account_id = accountId - - const integrations = - mode === 'buildbot' && !offline - ? await getIntegrations({ siteId, testOpts, offline, useV2Endpoint, accountId }) - : [] - - return { siteInfo, accounts: [], addons: [], integrations } - } - - const promises = [ - getSite(api, siteId, siteFeatureFlagPrefix), - getAccounts(api), - getAddons(api, siteId), - getIntegrations({ siteId, testOpts, offline, useV2Endpoint, accountId }), - ] - - const [siteInfo, accounts, addons, integrations] = await Promise.all(promises) - - if (siteInfo.use_envelope) { - const envelope = await getEnvelope({ api, accountId: siteInfo.account_slug, siteId, context }) - - siteInfo.build_settings.env = envelope - } - - return { siteInfo, accounts, addons, integrations } - } - if (api === undefined || mode === 'buildbot' || testEnv) { const siteInfo: { id?: string; account_id?: string } = {} if (siteId !== undefined) siteInfo.id = siteId if (accountId !== undefined) siteInfo.account_id = accountId - const integrations = mode === 'buildbot' && !offline ? await getIntegrations({ siteId, testOpts, offline }) : [] + const integrations = + mode === 'buildbot' && !offline ? await getIntegrations({ siteId, testOpts, offline, accountId }) : [] return { siteInfo, accounts: [], addons: [], integrations } } @@ -90,7 +55,7 @@ export const getSiteInfo = async function ({ getSite(api, siteId, siteFeatureFlagPrefix), getAccounts(api), getAddons(api, siteId), - getIntegrations({ siteId, testOpts, offline }), + getIntegrations({ siteId, testOpts, offline, accountId }), ] const [siteInfo, accounts, addons, integrations] = await Promise.all(promises) @@ -144,7 +109,6 @@ type GetIntegrationsOpts = { accountId?: string testOpts: TestOptions offline: boolean - useV2Endpoint?: boolean } const getIntegrations = async function ({ @@ -152,7 +116,6 @@ const getIntegrations = async function ({ accountId, testOpts, offline, - useV2Endpoint, }: GetIntegrationsOpts): Promise { if (!siteId || offline) { return [] @@ -162,8 +125,8 @@ const getIntegrations = async function ({ const baseUrl = new URL(host ? `http://${host}` : `https://api.netlifysdk.com`) - // use future state feature flag - const url = useV2Endpoint + // if accountId isn't present, use safe v1 endpoint + const url = accountId ? `${baseUrl}team/${accountId}/integrations/installations/meta/${siteId}` : `${baseUrl}site/${siteId}/integrations/safe` diff --git a/packages/config/src/case.js b/packages/config/src/case.ts similarity index 68% rename from packages/config/src/case.js rename to packages/config/src/case.ts index e8755ed876..0bbdad2180 100644 --- a/packages/config/src/case.js +++ b/packages/config/src/case.ts @@ -1,10 +1,18 @@ // Some properties can be optionally capitalized. We normalize them to lowercase -export const normalizeConfigCase = function ({ Build, build = Build, ...config }) { +export const normalizeConfigCase = function ({ + Build, + build = Build, + ...config +}: { + Build: Record + build: Record + [key: string]: unknown +}): Record { const buildA = normalizeBuildCase(build) return { ...config, build: buildA } } -const normalizeBuildCase = function ({ +const normalizeBuildCase = ({ Base, base = Base, Command, @@ -22,7 +30,7 @@ const normalizeBuildCase = function ({ Publish, publish = Publish, ...build -} = {}) { +}: Record = {}): Record => { return { ...build, base, diff --git a/packages/config/tests/api/tests.js b/packages/config/tests/api/tests.js index 8910aea2a8..897c9cc9ce 100644 --- a/packages/config/tests/api/tests.js +++ b/packages/config/tests/api/tests.js @@ -20,7 +20,7 @@ const SITE_INTEGRATIONS_RESPONSE = { response: [ { slug: 'test', - version: 'so-cool', + version: 'so-cool-v1', has_build: true, }, ], @@ -31,7 +31,7 @@ const TEAM_INSTALLATIONS_META_RESPONSE = { response: [ { slug: 'test', - version: 'so-cool', + version: 'so-cool-v2', has_build: true, }, ], @@ -42,6 +42,11 @@ const SITE_INTEGRATIONS_EMPTY_RESPONSE = { response: [], } +const TEAM_INSTALLATIONS_META_EMPTY_RESPONSE = { + path: '/team/account1/integrations/installations/meta/test', + response: [], +} + const SITE_INFO_BUILD_SETTINGS = { path: SITE_INFO_PATH, response: { @@ -222,7 +227,7 @@ test('Build settings are not used in CI', async (t) => { t.snapshot(normalizeOutput(output)) }) -test('Integrations are returned if feature flag is true', async (t) => { +test('Integrations are returned from getSiteInfo from v1 safe API when there is not accountID', async (t) => { const { output } = await new Fixture('./fixtures/base') .withFlags({ token: 'test', @@ -235,7 +240,7 @@ test('Integrations are returned if feature flag is true', async (t) => { t.assert(config.integrations) t.assert(config.integrations.length === 1) t.assert(config.integrations[0].slug === 'test') - t.assert(config.integrations[0].version === 'so-cool') + t.assert(config.integrations[0].version === 'so-cool-v1') t.assert(config.integrations[0].has_build === true) }) @@ -244,8 +249,9 @@ test('Integration specified in config is also returned if integration is availab .withFlags({ token: 'test', siteId: 'test', + accountId: 'account1', }) - .runConfigServer([SITE_INFO_DATA, SITE_INTEGRATIONS_RESPONSE, FETCH_INTEGRATIONS_RESPONSE]) + .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_RESPONSE]) const config = JSON.parse(output) @@ -262,8 +268,9 @@ test('Integration specified in config is not returned if integration is not avai .withFlags({ token: 'test', siteId: 'test', + accountId: 'account1', }) - .runConfigServer([SITE_INFO_DATA, SITE_INTEGRATIONS_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) + .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) const config = JSON.parse(output) @@ -278,8 +285,9 @@ test('In integration dev mode, integration specified in config is returned even token: 'test', siteId: 'test', context: 'dev', + accountId: 'account1', }) - .runConfigServer([SITE_INFO_DATA, SITE_INTEGRATIONS_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) + .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) const config = JSON.parse(output) @@ -297,8 +305,9 @@ test('In integration dev mode, integration specified in config is returned even token: 'test', siteId: 'test', context: 'dev', + accountId: 'account1', }) - .runConfigServer([SITE_INFO_DATA, SITE_INTEGRATIONS_EMPTY_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) + .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_EMPTY_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) const config = JSON.parse(output) @@ -309,8 +318,8 @@ test('In integration dev mode, integration specified in config is returned even t.assert(config.integrations[0].version === undefined) }) -test('In integration dev mode, integration specified in config is returned and build is forced by config', async (t) => { - const { output } = await new Fixture('./fixtures/dev_integration_with_force_build') +test('In integration dev mode, integration specified in config is returned even if integration is not enabled on site and accountId not present', async (t) => { + const { output } = await new Fixture('./fixtures/dev_integration') .withFlags({ token: 'test', siteId: 'test', @@ -323,76 +332,52 @@ test('In integration dev mode, integration specified in config is returned and b t.assert(config.integrations) t.assert(config.integrations.length === 1) t.assert(config.integrations[0].slug === 'abc-integration') - t.assert(config.integrations[0].has_build === true) + t.assert(config.integrations[0].has_build === false) t.assert(config.integrations[0].version === undefined) }) -test('Integrations are not returned if offline', async (t) => { - const { output } = await new Fixture('./fixtures/base') +test('In integration dev mode, integration specified in config is returned and build is forced by config', async (t) => { + const { output } = await new Fixture('./fixtures/dev_integration_with_force_build') .withFlags({ - offline: true, + token: 'test', siteId: 'test', - mode: 'buildbot', + context: 'dev', + accountId: 'account1', }) - .runConfigServer([SITE_INTEGRATIONS_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) + .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_EMPTY_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) const config = JSON.parse(output) t.assert(config.integrations) - t.assert(config.integrations.length === 0) + t.assert(config.integrations.length === 1) + t.assert(config.integrations[0].slug === 'abc-integration') + t.assert(config.integrations[0].has_build === true) + t.assert(config.integrations[0].version === undefined) }) -test('Integrations and account id are returned if feature flag is false and mode is buildbot', async (t) => { +test('Integrations are not returned if offline', async (t) => { const { output } = await new Fixture('./fixtures/base') .withFlags({ + offline: true, siteId: 'test', mode: 'buildbot', accountId: 'account1', - token: 'test', }) - .runConfigServer([SITE_INFO_DATA, SITE_INTEGRATIONS_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) + .runConfigServer([TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) const config = JSON.parse(output) t.assert(config.integrations) - t.is(config.integrations.length, 1) - t.is(config.integrations[0].slug, 'test') - t.is(config.integrations[0].version, 'so-cool') - t.is(config.integrations[0].has_build, true) - - // account id is also available - t.assert(config.siteInfo) - t.is(config.siteInfo.account_id, 'account1') -}) - -test('Integrations are returned if feature flag is false and mode is dev', async (t) => { - const { output } = await new Fixture('./fixtures/base') - .withFlags({ - siteId: 'test', - mode: 'dev', - token: 'test', - }) - .runConfigServer([SITE_INFO_DATA, SITE_INTEGRATIONS_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) - - const config = JSON.parse(output) - - t.assert(config.integrations) - t.assert(config.integrations.length === 1) - t.assert(config.integrations[0].slug === 'test') - t.assert(config.integrations[0].version === 'so-cool') - t.assert(config.integrations[0].has_build === true) + t.assert(config.integrations.length === 0) }) -test('Integrations and account id are returned if flag is true for site and mode is buildbot', async (t) => { +test('Integrations and account id are returned if mode is buildbot', async (t) => { const { output } = await new Fixture('./fixtures/base') .withFlags({ siteId: 'test', mode: 'buildbot', - token: 'test', accountId: 'account1', - featureFlags: { - cli_integration_installations_meta: true, - }, + token: 'test', }) .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) @@ -401,7 +386,7 @@ test('Integrations and account id are returned if flag is true for site and mode t.assert(config.integrations) t.is(config.integrations.length, 1) t.is(config.integrations[0].slug, 'test') - t.is(config.integrations[0].version, 'so-cool') + t.is(config.integrations[0].version, 'so-cool-v2') t.is(config.integrations[0].has_build, true) // account id is also available @@ -409,16 +394,13 @@ test('Integrations and account id are returned if flag is true for site and mode t.is(config.siteInfo.account_id, 'account1') }) -test('Integrations are returned if flag is true for site and mode is dev', async (t) => { +test('Integrations are returned if accountId is present and mode is dev', async (t) => { const { output } = await new Fixture('./fixtures/base') .withFlags({ siteId: 'test', mode: 'dev', token: 'test', accountId: 'account1', - featureFlags: { - cli_integration_installations_meta: true, - }, }) .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) @@ -427,7 +409,7 @@ test('Integrations are returned if flag is true for site and mode is dev', async t.assert(config.integrations) t.assert(config.integrations.length === 1) t.assert(config.integrations[0].slug === 'test') - t.assert(config.integrations[0].version === 'so-cool') + t.assert(config.integrations[0].version === 'so-cool-v2') t.assert(config.integrations[0].has_build === true) }) From 689a8dd5b26d6370b7e53005dca39b2b8efb9768 Mon Sep 17 00:00:00 2001 From: Mateusz Bocian Date: Tue, 10 Dec 2024 15:01:05 -0500 Subject: [PATCH 6/6] fix: detect `bun.lock` files in addition to `bun.lockb` files (#5918) --- packages/build-info/src/runtime/bun.test.ts | 9 +++++++++ packages/build-info/src/runtime/bun.ts | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/build-info/src/runtime/bun.test.ts b/packages/build-info/src/runtime/bun.test.ts index 65e7d4e789..07f4e102a8 100644 --- a/packages/build-info/src/runtime/bun.test.ts +++ b/packages/build-info/src/runtime/bun.test.ts @@ -17,6 +17,15 @@ test('detects node when bunfig.toml is present', async ({ fs }) => { expect(detected[0].name).toBe('Bun') }) +test('detects node when bun.lock is present', async ({ fs }) => { + const cwd = mockFileSystem({ + 'bun.lock': '', + }) + + const detected = await new Project(fs, cwd).detectRuntime() + expect(detected[0].name).toBe('Bun') +}) + test('detects node when bun.lockb is present', async ({ fs }) => { const cwd = mockFileSystem({ 'bun.lockb': '', diff --git a/packages/build-info/src/runtime/bun.ts b/packages/build-info/src/runtime/bun.ts index 8b11e6f667..3112d4c7a3 100644 --- a/packages/build-info/src/runtime/bun.ts +++ b/packages/build-info/src/runtime/bun.ts @@ -3,5 +3,5 @@ import { LangRuntime } from './runtime.js' export class Bun extends LangRuntime { id = 'bun' name = 'Bun' - configFiles = ['bun.lockb', 'bunfig.toml'] + configFiles = ['bun.lock', 'bun.lockb', 'bunfig.toml'] }