Skip to content

Commit 8af9ab3

Browse files
committed
fix(apps): use app_builder_url from API response instead of constructing it
The backend now returns app_builder_url in upload and release responses, which reflects the correct host for orgs with custom domains (e.g. dd.datad0g.com). The previous hardcoded https://app.${site}/... produced wrong URLs for those orgs. Related: ddoghq/dd-source#1038
1 parent 5c86848 commit 8af9ab3

2 files changed

Lines changed: 55 additions & 6 deletions

File tree

packages/plugins/apps/src/upload.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ describe('Apps Plugin - upload', () => {
229229
version_id: 'v123',
230230
application_id: 'app123',
231231
app_builder_id: 'builder123',
232+
app_builder_url:
233+
'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview',
232234
} as any);
233235

234236
const { errors, warnings } = await uploadArchive(archive, context, logger);
@@ -253,11 +255,32 @@ describe('Apps Plugin - upload', () => {
253255
);
254256
});
255257

258+
test('Should use app_builder_url from upload response', async () => {
259+
doAuthenticatedRequestMock.mockResolvedValueOnce({
260+
version_id: 'v123',
261+
application_id: 'app123',
262+
app_builder_id: 'builder123',
263+
app_builder_url:
264+
'https://dd.datad0g.com/app-builder/apps/edit/builder123?viewMode=preview',
265+
} as any);
266+
267+
await uploadArchive(archive, context, logger);
268+
269+
expect(mockLogFn).toHaveBeenCalledWith(
270+
expect.stringContaining(
271+
'https://dd.datad0g.com/app-builder/apps/edit/builder123?viewMode=preview',
272+
),
273+
'info',
274+
);
275+
});
276+
256277
test('Should upload archive using the supplied request function', async () => {
257278
const doUploadAuthenticatedRequestMock = jest.fn().mockResolvedValue({
258279
version_id: 'v123',
259280
application_id: 'app123',
260281
app_builder_id: 'builder123',
282+
app_builder_url:
283+
'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview',
261284
} as any);
262285

263286
const { errors, warnings } = await uploadArchive(
@@ -286,6 +309,7 @@ describe('Apps Plugin - upload', () => {
286309
version_id: 'v123',
287310
application_id: 'app123',
288311
app_builder_id: 'builder123',
312+
app_builder_url: 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview',
289313
})
290314
.mockResolvedValueOnce({});
291315

@@ -307,6 +331,28 @@ describe('Apps Plugin - upload', () => {
307331
);
308332
});
309333

334+
test('Should use app_builder_url from release response', async () => {
335+
doAuthenticatedRequestMock
336+
.mockResolvedValueOnce({
337+
version_id: 'v123',
338+
application_id: 'app123',
339+
app_builder_id: 'builder123',
340+
app_builder_url:
341+
'https://dd.datad0g.com/app-builder/apps/edit/builder123?viewMode=preview',
342+
})
343+
.mockResolvedValueOnce({
344+
app_builder_url: 'https://dd.datad0g.com/app-builder/apps/builder123',
345+
});
346+
347+
await uploadArchive(archive, context, logger);
348+
349+
// Published URL from release response — no ?viewMode=preview, custom domain preserved
350+
expect(mockLogFn).toHaveBeenCalledWith(
351+
expect.stringContaining('https://dd.datad0g.com/app-builder/apps/builder123'),
352+
'info',
353+
);
354+
});
355+
310356
test.each(['false', '0', 'False', 'FALSE', 'off', 'no'])(
311357
'Should skip release/live call when DD_APPS_PUBLISH=%s',
312358
async (publishValue) => {
@@ -317,6 +363,7 @@ describe('Apps Plugin - upload', () => {
317363
version_id: 'v123',
318364
application_id: 'app123',
319365
app_builder_id: 'builder123',
366+
app_builder_url: 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview',
320367
});
321368

322369
const { errors } = await uploadArchive(archive, context, logger);
@@ -342,6 +389,7 @@ describe('Apps Plugin - upload', () => {
342389
version_id: 'v123',
343390
application_id: 'app123',
344391
app_builder_id: 'builder123',
392+
app_builder_url: 'https://app.datadoghq.com/app-builder/apps/edit/builder123?viewMode=preview',
345393
});
346394

347395
const { errors, warnings } = await uploadArchive(archive, context, logger);

packages/plugins/apps/src/upload.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,17 +121,15 @@ Would have uploaded ${summary}`,
121121

122122
log.debug(`Uploaded ${summary}\n`);
123123

124-
if (response.app_builder_id) {
125-
const appBuilderUrl = `https://app.${context.site}/app-builder/apps/${response.app_builder_id}`;
126-
127-
log.info(`Your application is available at:\n ${cyan(appBuilderUrl)}`);
124+
if (response.app_builder_url) {
125+
log.info(`Your application is available at:\n ${cyan(response.app_builder_url)}`);
128126
}
129127

130128
const shouldPublish = parseBoolEnv(getDDEnvValue('APPS_PUBLISH'), true);
131129

132130
if (response.version_id && shouldPublish) {
133131
const releaseUrl = getReleaseUrl(context.site, context.identifier);
134-
await doAuthenticatedRequest({
132+
const releaseResponse: any = await doAuthenticatedRequest({
135133
url: releaseUrl,
136134
method: 'PUT',
137135
type: 'json',
@@ -150,7 +148,10 @@ Would have uploaded ${summary}`,
150148
log.warn(message);
151149
},
152150
});
153-
log.info(`Published uploaded version ${bold(response.version_id)} to live.`);
151+
152+
log.info(
153+
`Published uploaded version ${bold(response.version_id)} to live.\n ${cyan(releaseResponse.app_builder_url)}`,
154+
);
154155
} else if (response.version_id && !shouldPublish) {
155156
log.info(`Uploaded version ${bold(response.version_id)} as a draft (publish skipped).`);
156157
}

0 commit comments

Comments
 (0)