Skip to content
Merged
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
8 changes: 6 additions & 2 deletions packages/plugins/apps/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,14 @@ describe('Apps Plugin - getPlugins', () => {

test('Should upload assets with vite bundler', async () => {
const intakeHost = 'https://api.example.com';
const scope = nock(intakeHost).post(`/${APPS_API_PATH}/app-id/upload`).reply(200, {
const uploadScope = nock(intakeHost).post(`/${APPS_API_PATH}/app-id/upload`).reply(200, {
version_id: 'v123',
application_id: 'app123',
app_builder_id: 'builder123',
});
const releaseScope = nock(intakeHost)
.put(`/${APPS_API_PATH}/app-id/release/live`)
.reply(200, {});

const { errors } = await runBundlers(
{ apps: { identifier: 'app-id', name: 'test-app', dryRun: false } },
Expand All @@ -232,6 +235,7 @@ describe('Apps Plugin - getPlugins', () => {
);

expect(errors).toHaveLength(0);
expect(scope.isDone()).toBe(true);
expect(uploadScope.isDone()).toBe(true);
expect(releaseScope.isDone()).toBe(true);
});
});
10 changes: 2 additions & 8 deletions packages/plugins/apps/src/upload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,13 +258,7 @@ describe('Apps Plugin - upload', () => {
);
});

test('Should make PUT request to release version when APPS_VERSION_NAME is set', async () => {
getDDEnvValueMock.mockImplementation((key) => {
if (key === 'APPS_VERSION_NAME') {
return 'my-version';
}
return undefined;
});
test('Should make PUT request to release version after successful upload', async () => {
doRequestMock
.mockResolvedValueOnce({
version_id: 'v123',
Expand All @@ -287,7 +281,7 @@ describe('Apps Plugin - upload', () => {
onRetry: expect.any(Function),
});
expect(mockLogFn).toHaveBeenCalledWith(
expect.stringContaining('Released version'),
expect.stringContaining('Your application is available at'),
'info',
);
});
Expand Down
13 changes: 4 additions & 9 deletions packages/plugins/apps/src/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,14 @@ Would have uploaded ${summary}`,
const appUrl = `https://api.${context.site}/api/unstable/app-builder-code/apps/serve/${application_id}/v/${version_id}/index.html`;
const appBuilderUrl = `https://app.${context.site}/app-builder/apps/${app_builder_id}`;

log.info(
`Your application is available at:\n${bold('Standalone :')}\n ${cyan(appUrl)}\n\n${bold('AppBuilder :')}\n ${cyan(appBuilderUrl)}`,
);
}

const versionName = getDDEnvValue('APPS_VERSION_NAME')?.trim();
if (versionName) {
const releaseUrl = getReleaseUrl(context.site, context.identifier);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor custom intake when publishing releases

When DATADOG_APPS_INTAKE_URL/DD_APPS_INTAKE_URL is set, getIntakeUrl sends the upload to that full custom URL, but the new unconditional publish still computes https://api.${site} here. In that documented override scenario, a successful upload to a staging/custom intake is followed by a release against the default Datadog site, which can fail the build or publish the app with the same identifier in the wrong environment; derive the release target from the override or make it separately overridable.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intentionally ignoring for now

await doRequest({
auth: { apiKey: context.apiKey, appKey: context.appKey },
url: releaseUrl,
method: 'PUT',
type: 'json',
getData: async () => ({
data: Readable.from(JSON.stringify({ version_id: versionName })),
data: Readable.from(JSON.stringify({ version_id: response.version_id })),
headers: {
'Content-Type': 'application/json',
...defaultHeaders,
Expand All @@ -164,7 +157,9 @@ Would have uploaded ${summary}`,
log.warn(message);
},
});
log.info(`Released version ${bold(versionName)} to live.`);
log.info(
`Your application is available at:\n${bold('Standalone :')}\n ${cyan(appUrl)}\n\n${bold('AppBuilder :')}\n ${cyan(appBuilderUrl)}`,
);
}
} catch (error: unknown) {
const err = error instanceof Error ? error : new Error(String(error));
Expand Down
18 changes: 18 additions & 0 deletions packages/tests/src/e2e/appsPlugin/appsPlugin.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ type UploadRequest = {
// Mock the apps upload endpoint and persist per-bundler upload data to disk.
// We write to a temp directory because Playwright workers are separate processes —
// only the worker that actually builds captures the nock request.
nock('https://api.datadoghq.com')
.put(new RegExp(`/api/unstable/app-builder-code/apps/.*/release/live`))
.reply(function handleReleaseMock(uri, body) {
const applicationId = uri.split('/apps/')[1]?.split('/release')[0] ?? '';
const parsed = typeof body === 'string' ? JSON.parse(body) : body;
return [
200,
{
application_id: applicationId,
release: {
environment: 'live',
version_id: parsed.version_id ?? '',
},
},
];
})
.persist();

nock('https://api.datadoghq.com')
.post(new RegExp(`/api/unstable/app-builder-code/apps/.*/upload`))
.reply(function handleUploadMock(uri, body) {
Expand Down
Loading