diff --git a/packages/config/src/api/site_info.ts b/packages/config/src/api/site_info.ts index 2a481b51e0..a665aa09c3 100644 --- a/packages/config/src/api/site_info.ts +++ b/packages/config/src/api/site_info.ts @@ -4,6 +4,12 @@ import type { RequestInit } from 'node-fetch' import { getEnvelope } from '../env/envelope.js' import { throwUserError } from '../error.js' +import { + EXTENSION_API_BASE_URL, + EXTENSION_API_STAGING_BASE_URL, + NETLIFY_API_BASE_URL, + NETLIFY_API_STAGING_BASE_URL, +} from '../integrations.js' import { ERROR_CALL_TO_ACTION } from '../log/messages.js' import { IntegrationResponse } from '../types/api.js' import { ModeOption, TestOptions } from '../types/options.js' @@ -53,7 +59,16 @@ export const getSiteInfo = async function ({ const integrations = mode === 'buildbot' && !offline - ? await getIntegrations({ siteId, testOpts, offline, accountId, token, featureFlags, extensionApiBaseUrl }) + ? await getIntegrations({ + siteId, + testOpts, + offline, + accountId, + token, + featureFlags, + extensionApiBaseUrl, + mode, + }) : [] return { siteInfo, accounts: [], addons: [], integrations } @@ -63,7 +78,7 @@ export const getSiteInfo = async function ({ getSite(api, siteId, siteFeatureFlagPrefix), getAccounts(api), getAddons(api, siteId), - getIntegrations({ siteId, testOpts, offline, accountId, token, featureFlags, extensionApiBaseUrl }), + getIntegrations({ siteId, testOpts, offline, accountId, token, featureFlags, extensionApiBaseUrl, mode }), ] const [siteInfo, accounts, addons, integrations] = await Promise.all(promises) @@ -120,6 +135,7 @@ type GetIntegrationsOpts = { token?: string featureFlags?: Record<string, boolean> extensionApiBaseUrl: string + mode: ModeOption } const getIntegrations = async function ({ @@ -130,19 +146,36 @@ const getIntegrations = async function ({ token, featureFlags, extensionApiBaseUrl, + mode, }: GetIntegrationsOpts): Promise<IntegrationResponse[]> { if (!siteId || offline) { return [] } const sendBuildBotTokenToJigsaw = featureFlags?.send_build_bot_token_to_jigsaw - const { host, setBaseUrl } = testOpts + const { host: originalHost, setBaseUrl } = testOpts + + // TODO(kh): I am adding this purely for local staging development. + // We should remove this once we have fixed https://github.com/netlify/cli/blob/b5a5c7525edd28925c5c2e3e5f0f00c4261eaba5/src/lib/build.ts#L125 + let host = originalHost + + // If there is a host, we use it to fetch the integrations + // we check if the host is staging or production and set the host accordingly, + // sadly necessary because of https://github.com/netlify/cli/blob/b5a5c7525edd28925c5c2e3e5f0f00c4261eaba5/src/lib/build.ts#L125 + if (originalHost) { + if (originalHost?.includes(NETLIFY_API_STAGING_BASE_URL)) { + host = EXTENSION_API_STAGING_BASE_URL + } else if (originalHost?.includes(NETLIFY_API_BASE_URL)) { + host = EXTENSION_API_BASE_URL + } else { + host = `http://${originalHost}` + } + } + const baseUrl = new URL(host ?? extensionApiBaseUrl) // We only use this for testing if (host && setBaseUrl) { setBaseUrl(extensionApiBaseUrl) } - - const baseUrl = new URL(host ? `http://${host}` : extensionApiBaseUrl) // if accountId isn't present, use safe v1 endpoint const url = accountId ? `${baseUrl}team/${accountId}/integrations/installations/meta/${siteId}` @@ -151,8 +184,14 @@ const getIntegrations = async function ({ try { const requestOptions = {} as RequestInit + // This is used to identify where the request is coming from + requestOptions.headers = { + 'netlify-config-mode': mode, + } + if (sendBuildBotTokenToJigsaw && token) { requestOptions.headers = { + ...requestOptions.headers, 'netlify-sdk-build-bot-token': token, } } diff --git a/packages/config/src/integrations.ts b/packages/config/src/integrations.ts index 6f6aabed2e..529427b972 100644 --- a/packages/config/src/integrations.ts +++ b/packages/config/src/integrations.ts @@ -4,6 +4,7 @@ import { Integration } from './types/integrations.js' import { TestOptions } from './types/options.js' export const NETLIFY_API_STAGING_BASE_URL = 'api-staging.netlify.com' +export const NETLIFY_API_BASE_URL = 'api.netlify.com' export const EXTENSION_API_BASE_URL = 'https://api.netlifysdk.com' export const EXTENSION_API_STAGING_BASE_URL = 'https://api-staging.netlifysdk.com' diff --git a/packages/config/src/main.ts b/packages/config/src/main.ts index 4209e0944e..6954d88c22 100644 --- a/packages/config/src/main.ts +++ b/packages/config/src/main.ts @@ -55,8 +55,9 @@ export const resolveConfig = async function (opts) { } // TODO(kh): remove this mapping and get the extensionApiHost from the opts - const extensionApiBaseUrl = - host === NETLIFY_API_STAGING_BASE_URL ? EXTENSION_API_STAGING_BASE_URL : EXTENSION_API_BASE_URL + const extensionApiBaseUrl = host?.includes(NETLIFY_API_STAGING_BASE_URL) + ? EXTENSION_API_STAGING_BASE_URL + : EXTENSION_API_BASE_URL const { config: configOpt, diff --git a/packages/config/tests/api/tests.js b/packages/config/tests/api/tests.js index 9bb333b891..8c5415d1d5 100644 --- a/packages/config/tests/api/tests.js +++ b/packages/config/tests/api/tests.js @@ -425,7 +425,7 @@ test('Integrations are returned if accountId is present and mode is dev', async t.assert(config.integrations[0].has_build === true) }) -test('Integrations are returned and called with a netlify-sdk-build-bot-token', async (t) => { +test('Integrations are returned and called with a netlify-sdk-build-bot-token header', async (t) => { const { output, requests } = await new Fixture('./fixtures/base') .withFlags({ siteId: 'test', @@ -451,6 +451,32 @@ test('Integrations are returned and called with a netlify-sdk-build-bot-token', t.assert(config.integrations[0].has_build === true) }) +test('Integrations are returned and called with a netlify-config-mode header', async (t) => { + const { output, requests } = await new Fixture('./fixtures/base') + .withFlags({ + siteId: 'test', + mode: 'dev', + token: 'test', + accountId: 'account1', + featureFlags: { + send_build_bot_token_to_jigsaw: true, + }, + }) + .runConfigServer([SITE_INFO_DATA, TEAM_INSTALLATIONS_META_RESPONSE, FETCH_INTEGRATIONS_EMPTY_RESPONSE]) + + const config = JSON.parse(output) + const installationsHeaders = requests.find( + (request) => request.url === TEAM_INSTALLATIONS_META_RESPONSE.path, + )?.headers + + t.assert(installationsHeaders.includes('netlify-config-mode')) + 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-v2') + t.assert(config.integrations[0].has_build === true) +}) + test('Integrations are not returned if failed to fetch integrations', async (t) => { const { output } = await new Fixture('./fixtures/base') .withFlags({