Skip to content
Open
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
5 changes: 5 additions & 0 deletions .changeset/project-list-deployed-url.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@bigcommerce/catalyst": minor
---

Show every deployed URL for each project in `catalyst project list` output (the canonical hostname plus any vanity hostnames) so users can recover the hosted storefront URLs without having to redeploy.
24 changes: 16 additions & 8 deletions packages/catalyst/src/cli/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ const DeploymentStatusSchema = z.object({
progress: z.number(),
})
.nullable(),
deployment_url: z.string().nullable(),
// Deprecated by ignition; prefer `deployment_hostnames`. Kept here so
// older ignition builds (that haven't shipped the rename yet) still
// parse cleanly during the transition window.
deployment_url: z.string().nullable().optional(),
deployment_hostnames: z.array(z.string()).optional(),
error: z
.object({
code: z.number(),
Expand Down Expand Up @@ -285,7 +289,7 @@ export const getDeploymentStatus = async (

const decoder = new TextDecoder();
let done = false;
let deploymentUrl: string | undefined;
let deploymentHostname: string | undefined;

while (!done) {
// eslint-disable-next-line no-await-in-loop
Expand Down Expand Up @@ -321,8 +325,12 @@ export const getDeploymentStatus = async (
spinner.text = STEPS[data.event.step];
}

if (data.deployment_url) {
deploymentUrl = data.deployment_url;
// Prefer the new plural field; fall back to the deprecated singular
// for older ignition builds during the transition window.
if (data.deployment_hostnames && data.deployment_hostnames.length > 0) {
deploymentHostname = data.deployment_hostnames[0];
} else if (data.deployment_url) {
deploymentHostname = data.deployment_url;
}
});
}
Expand All @@ -332,10 +340,10 @@ export const getDeploymentStatus = async (

spinner.success('Deployment completed successfully.');

if (deploymentUrl) {
const url = deploymentUrl.startsWith('https://') ? deploymentUrl : `https://${deploymentUrl}`;

consola.success(`View your deployment at: ${colorize('blue', url)}`);
if (deploymentHostname) {
consola.success(
`View your deployment at: ${colorize('blue', `https://${deploymentHostname}`)}`,
);
}
};

Expand Down
7 changes: 7 additions & 0 deletions packages/catalyst/src/cli/commands/project.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,14 @@ describe('project list', () => {
expect(consola.start).toHaveBeenCalledWith('Fetching projects...');
expect(consola.success).toHaveBeenCalledWith('Projects fetched.');
expect(consola.log).toHaveBeenCalledWith('Project One (a23f5785-fd99-4a94-9fb3-945551623923)');
expect(consola.log).toHaveBeenCalledWith(
expect.stringContaining('https://project-one.catalyst-sandbox.store'),
);
expect(consola.log).toHaveBeenCalledWith(
expect.stringContaining('https://vanity.project-one.example.com'),
);
expect(consola.log).toHaveBeenCalledWith('Project Two (b23f5785-fd99-4a94-9fb3-945551623924)');
expect(consola.log).toHaveBeenCalledWith(' (not deployed)');
expect(exitMock).toHaveBeenCalledWith(0);
});

Expand Down
11 changes: 11 additions & 0 deletions packages/catalyst/src/cli/commands/project.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Command, Option } from 'commander';
import { colorize } from 'consola/utils';

import { consola } from '../lib/logger';
import { createProject, fetchProjects } from '../lib/project';
Expand Down Expand Up @@ -53,6 +54,16 @@ Example:

projects.forEach((p) => {
consola.log(`${p.name} (${p.uuid})`);

if (p.deployment_hostnames.length === 0) {
consola.log(' (not deployed)');
} else {
p.deployment_hostnames.forEach((hostname) => {
consola.log(` ${colorize('blue', `https://${hostname}`)}`);
});
}

consola.log('');
});

process.exit(0);
Expand Down
2 changes: 2 additions & 0 deletions packages/catalyst/src/cli/lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ const fetchProjectsSchema = z.object({
z.object({
uuid: z.string(),
name: z.string(),
deployment_hostnames: z.array(z.string()),
}),
),
});

export interface ProjectListItem {
uuid: string;
name: string;
deployment_hostnames: string[];
}

export async function fetchProjects(
Expand Down
21 changes: 16 additions & 5 deletions packages/catalyst/tests/mocks/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,19 @@ export const handlers = [
http.get('https://:apiHost/stores/:storeHash/v3/infrastructure/projects', () =>
HttpResponse.json({
data: [
{ uuid: 'a23f5785-fd99-4a94-9fb3-945551623923', name: 'Project One' },
{ uuid: 'b23f5785-fd99-4a94-9fb3-945551623924', name: 'Project Two' },
{
uuid: 'a23f5785-fd99-4a94-9fb3-945551623923',
name: 'Project One',
deployment_hostnames: [
'project-one.catalyst-sandbox.store',
'vanity.project-one.example.com',
],
},
{
uuid: 'b23f5785-fd99-4a94-9fb3-945551623924',
name: 'Project Two',
deployment_hostnames: [],
},
],
}),
),
Expand All @@ -44,22 +55,22 @@ export const handlers = [
controller.enqueue(
encoder.encode(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`data: {"deployment_status":"in_progress","deployment_uuid":"${params.deploymentUuid}","event":{"step":"processing","progress":75},"deployment_url":null}`,
`data: {"deployment_status":"in_progress","deployment_uuid":"${params.deploymentUuid}","event":{"step":"processing","progress":75},"deployment_url":null,"deployment_hostnames":[]}`,
),
);
setTimeout(() => {
controller.enqueue(
encoder.encode(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`data: {"deployment_status":"in_progress","deployment_uuid":"${params.deploymentUuid}","event":{"step":"finalizing","progress":99},"deployment_url":null}`,
`data: {"deployment_status":"in_progress","deployment_uuid":"${params.deploymentUuid}","event":{"step":"finalizing","progress":99},"deployment_url":null,"deployment_hostnames":[]}`,
),
);
}, 10);
setTimeout(() => {
controller.enqueue(
encoder.encode(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`data: {"deployment_status":"completed","deployment_uuid":"${params.deploymentUuid}","event":null,"deployment_url":"https://example.com"}`,
`data: {"deployment_status":"completed","deployment_uuid":"${params.deploymentUuid}","event":null,"deployment_url":"example.com","deployment_hostnames":["example.com"]}`,
),
);
controller.close();
Expand Down
Loading