Skip to content

Commit fa310a9

Browse files
jorgemoyaclaude
andcommitted
LTRAC-446: ref(cli) - Replace channel picker with --update-site-url flag
Drop the channel-picker UX added to `project link` / `project create` and the persisted `channelId` in project.json. The auto-update is now driven by a single `--update-site-url <channelId>` flag (or `CATALYST_UPDATE_SITE_URL` env) on `catalyst deploy`: when passed, the deployed URL is PUT to that channel's site after the bundle goes live. Also drop the GET-then-skip-when-equal optimization so the command unconditionally PUTs the deployment URL when the flag is supplied — the caller opted in explicitly, so always make the call. The implementation collapses to: keep `updateChannelSiteUrl`, drop `fetchChannels` and `fetchChannelSite`, and keep the soft-fail (warn + re-auth hint) so a 401/403 doesn't sour an otherwise-successful deploy. Refs LTRAC-446 Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 65435dc commit fa310a9

8 files changed

Lines changed: 33 additions & 611 deletions

File tree

packages/catalyst/src/cli/commands/deploy.spec.ts

Lines changed: 11 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,9 @@ describe('--prebuilt flag', () => {
562562
});
563563
});
564564

565-
describe('channel site URL auto-update', () => {
565+
describe('--update-site-url', () => {
566566
const channelId = 7;
567567

568-
afterEach(() => {
569-
const config = getProjectConfig();
570-
571-
config.delete('channelId');
572-
});
573-
574568
function deployArgs(extra: string[] = []) {
575569
return [
576570
'node',
@@ -589,14 +583,16 @@ describe('channel site URL auto-update', () => {
589583
];
590584
}
591585

592-
test('updates channel site URL after a successful deploy', async () => {
586+
test('PUTs the deployment URL to the given channel', async () => {
593587
let putBody: unknown;
588+
let receivedChannelId: string | undefined;
594589

595590
server.use(
596591
http.put(
597592
'https://:apiHost/stores/:storeHash/v3/channels/:channelId/site',
598-
async ({ request }) => {
593+
async ({ request, params }) => {
599594
putBody = await request.json();
595+
receivedChannelId = String(params.channelId);
600596

601597
return HttpResponse.json({
602598
data: { id: 1, url: 'https://example.com', channel_id: channelId },
@@ -605,90 +601,43 @@ describe('channel site URL auto-update', () => {
605601
),
606602
);
607603

608-
await program.parseAsync(deployArgs(['--channel-id', String(channelId)]));
604+
await program.parseAsync(deployArgs(['--update-site-url', String(channelId)]));
609605

606+
expect(receivedChannelId).toBe(String(channelId));
610607
expect(putBody).toEqual({ url: 'https://example.com' });
611608
expect(consola.success).toHaveBeenCalledWith(
612609
`Updated channel ${channelId} site URL to https://example.com.`,
613610
);
614611
});
615612

616-
test('reads channel ID from project.json when --channel-id is not passed', async () => {
617-
const config = getProjectConfig();
618-
619-
config.set('channelId', channelId);
620-
621-
await program.parseAsync(deployArgs());
622-
623-
expect(consola.success).toHaveBeenCalledWith(
624-
`Updated channel ${channelId} site URL to https://example.com.`,
625-
);
626-
});
627-
628-
test('skips PUT when current site URL already matches deployment URL', async () => {
613+
test('does not call the channel site API when the flag is omitted', async () => {
629614
let putCalled = false;
630615

631616
server.use(
632-
http.get('https://:apiHost/stores/:storeHash/v3/channels/:channelId/site', () =>
633-
HttpResponse.json({
634-
data: { id: 1, url: 'https://example.com', channel_id: channelId },
635-
}),
636-
),
637617
http.put('https://:apiHost/stores/:storeHash/v3/channels/:channelId/site', () => {
638618
putCalled = true;
639619

640620
return HttpResponse.json({}, { status: 200 });
641621
}),
642622
);
643623

644-
await program.parseAsync(deployArgs(['--channel-id', String(channelId)]));
645-
646-
expect(putCalled).toBe(false);
647-
expect(consola.info).toHaveBeenCalledWith(
648-
`Channel ${channelId} site URL already up to date (https://example.com).`,
649-
);
650-
});
651-
652-
test('--no-update-channel skips the update entirely', async () => {
653-
let getCalled = false;
654-
655-
server.use(
656-
http.get('https://:apiHost/stores/:storeHash/v3/channels/:channelId/site', () => {
657-
getCalled = true;
658-
659-
return HttpResponse.json({}, { status: 404 });
660-
}),
661-
);
662-
663-
await program.parseAsync(
664-
deployArgs(['--channel-id', String(channelId), '--no-update-channel']),
665-
);
666-
667-
expect(getCalled).toBe(false);
668-
expect(consola.success).not.toHaveBeenCalledWith(expect.stringContaining('Updated channel'));
669-
});
670-
671-
test('warns and continues when no channel ID is configured', async () => {
672624
await program.parseAsync(deployArgs());
673625

674-
expect(consola.warn).toHaveBeenCalledWith(expect.stringContaining('no channel ID configured'));
626+
expect(putCalled).toBe(false);
675627
expect(consola.success).not.toHaveBeenCalledWith(expect.stringContaining('Updated channel'));
676628
});
677629

678630
test('soft-fails with a warning when the update API returns an error', async () => {
679631
server.use(
680-
http.get('https://:apiHost/stores/:storeHash/v3/channels/:channelId/site', () =>
681-
HttpResponse.json({}, { status: 404 }),
682-
),
683632
http.put('https://:apiHost/stores/:storeHash/v3/channels/:channelId/site', () =>
684633
HttpResponse.json({}, { status: 401 }),
685634
),
686635
);
687636

688-
await program.parseAsync(deployArgs(['--channel-id', String(channelId)]));
637+
await program.parseAsync(deployArgs(['--update-site-url', String(channelId)]));
689638

690639
expect(consola.warn).toHaveBeenCalledWith(
691-
expect.stringContaining('Failed to update channel site URL automatically'),
640+
expect.stringContaining('Failed to update channel site URL'),
692641
);
693642
expect(consola.info).toHaveBeenCalledWith(expect.stringContaining('catalyst auth login'));
694643
});

packages/catalyst/src/cli/commands/deploy.ts

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { join } from 'node:path';
66
import yoctoSpinner from 'yocto-spinner';
77
import { z } from 'zod';
88

9-
import { fetchChannelSite, updateChannelSiteUrl } from '../lib/channels';
9+
import { updateChannelSiteUrl } from '../lib/channels';
1010
import { getDeploymentErrorMessage } from '../lib/deployment-errors';
1111
import { consola } from '../lib/logger';
1212
import { getProjectConfig } from '../lib/project-config';
@@ -412,13 +412,12 @@ Example:
412412
)
413413
.addOption(
414414
new Option(
415-
'--channel-id <id>',
416-
'BigCommerce channel ID to update with the deployment URL. Read from .bigcommerce/project.json when not provided.',
415+
'--update-site-url <channelId>',
416+
"BigCommerce channel ID whose site URL should be updated with this deployment's URL. When omitted, no channel is updated.",
417417
)
418-
.env('CATALYST_CHANNEL_ID')
418+
.env('CATALYST_UPDATE_SITE_URL')
419419
.argParser((value: string) => Number(value)),
420420
)
421-
.option('--no-update-channel', 'Skip updating the BigCommerce channel site URL after deploy.')
422421
.addOption(
423422
new Option(
424423
'--secret <value>',
@@ -504,17 +503,9 @@ Example:
504503
options.apiHost,
505504
);
506505

507-
if (!options.updateChannel) {
508-
return;
509-
}
510-
511-
const channelId: number | undefined = options.channelId ?? config.get('channelId');
506+
const channelId: number | undefined = options.updateSiteUrl;
512507

513508
if (!channelId) {
514-
consola.warn(
515-
'Skipping channel site URL update: no channel ID configured. Run `catalyst project link` or pass --channel-id.',
516-
);
517-
518509
return;
519510
}
520511

@@ -525,23 +516,11 @@ Example:
525516
}
526517

527518
try {
528-
const current = await fetchChannelSite(channelId, storeHash, accessToken, options.apiHost);
529-
530-
if (current?.url === deploymentUrl) {
531-
consola.info(`Channel ${channelId} site URL already up to date (${deploymentUrl}).`);
532-
} else {
533-
await updateChannelSiteUrl(
534-
channelId,
535-
deploymentUrl,
536-
storeHash,
537-
accessToken,
538-
options.apiHost,
539-
);
540-
consola.success(`Updated channel ${channelId} site URL to ${deploymentUrl}.`);
541-
}
519+
await updateChannelSiteUrl(channelId, deploymentUrl, storeHash, accessToken, options.apiHost);
520+
consola.success(`Updated channel ${channelId} site URL to ${deploymentUrl}.`);
542521
} catch (error) {
543522
consola.warn(
544-
`Failed to update channel site URL automatically: ${error instanceof Error ? error.message : String(error)}`,
523+
`Failed to update channel site URL: ${error instanceof Error ? error.message : String(error)}`,
545524
);
546525
consola.info(
547526
'Update it manually in the control panel, or re-run after `catalyst auth login` if the token is missing the store_channel_settings scope.',

0 commit comments

Comments
 (0)