@hs-x/cli 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/completion.js +1 -0
- package/dist/commands/completion.js.map +1 -1
- package/dist/commands/control-plane-read.js +1 -1
- package/dist/commands/control-plane-read.js.map +1 -1
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +182 -83
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/dev.d.ts +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +11 -6
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +6 -1
- package/dist/commands/help-command.js.map +1 -1
- package/dist/commands/project-lifecycle.d.ts.map +1 -1
- package/dist/commands/project-lifecycle.js +143 -46
- package/dist/commands/project-lifecycle.js.map +1 -1
- package/dist/commands/project.d.ts +1 -0
- package/dist/commands/project.d.ts.map +1 -1
- package/dist/commands/project.js +24 -10
- package/dist/commands/project.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/dev/browser-log-bridge.d.ts +12 -0
- package/dist/dev/browser-log-bridge.d.ts.map +1 -1
- package/dist/dev/browser-log-bridge.js +86 -3
- package/dist/dev/browser-log-bridge.js.map +1 -1
- package/dist/dev/frontend-log-relay.d.ts +3 -1
- package/dist/dev/frontend-log-relay.d.ts.map +1 -1
- package/dist/dev/frontend-log-relay.js +48 -3
- package/dist/dev/frontend-log-relay.js.map +1 -1
- package/dist/dev/session-manager.d.ts +2 -0
- package/dist/dev/session-manager.d.ts.map +1 -1
- package/dist/dev/session-manager.js +21 -6
- package/dist/dev/session-manager.js.map +1 -1
- package/dist/dev/stream-renderer.d.ts.map +1 -1
- package/dist/dev/stream-renderer.js +5 -6
- package/dist/dev/stream-renderer.js.map +1 -1
- package/dist/hubspot-auth.d.ts.map +1 -1
- package/dist/hubspot-auth.js +86 -3
- package/dist/hubspot-auth.js.map +1 -1
- package/dist/hubspot-developer-client.d.ts +1 -0
- package/dist/hubspot-developer-client.d.ts.map +1 -1
- package/dist/hubspot-developer-client.js +16 -1
- package/dist/hubspot-developer-client.js.map +1 -1
- package/dist/hubspot-project-lifecycle.d.ts +12 -0
- package/dist/hubspot-project-lifecycle.d.ts.map +1 -1
- package/dist/hubspot-project-lifecycle.js +28 -0
- package/dist/hubspot-project-lifecycle.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/deploy.js
CHANGED
|
@@ -10,6 +10,7 @@ import { cloudflareResourceName, generateHubSpotRuntimeProject, generateProjectA
|
|
|
10
10
|
import { HttpClientRequest, Schema, schemas, signDeploymentAttestationGrant } from '@hs-x/types';
|
|
11
11
|
import { validateProject } from '@hs-x/validator';
|
|
12
12
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
13
|
+
import { translate as translateHubSpotProject } from '@hubspot/project-parsing-lib/translate';
|
|
13
14
|
import { Effect, Option } from 'effect';
|
|
14
15
|
import { isLinked } from '../account-store.js';
|
|
15
16
|
import { exitWith } from '../cli-error.js';
|
|
@@ -27,7 +28,7 @@ import { resolveDeployTargets } from '../deploy-targets.js';
|
|
|
27
28
|
import { executeCliHttp } from '../effect-http.js';
|
|
28
29
|
import { DirectHubSpotAccountResolutionError, createDeployHubSpotDeveloperClient, resolveDirectHubSpotContext, } from '../hubspot-developer-client.js';
|
|
29
30
|
import { HubSpotProjectArchiveSourceError, fingerprintHubSpotArchiveSource, writeLocalHubSpotProjectArchive, } from '../hubspot-project-archive.js';
|
|
30
|
-
import { deployHubSpotProjectBuild, waitForHubSpotAutoDeploy, waitForHubSpotBuildStatus, } from '../hubspot-project-lifecycle.js';
|
|
31
|
+
import { deployHubSpotProjectBuild, readHubSpotSubbuildStatuses, waitForHubSpotAutoDeploy, waitForHubSpotBuildStatus, } from '../hubspot-project-lifecycle.js';
|
|
31
32
|
import { detectLocalProjectMode, readHubSpotProjectDescriptor, validateHubSpotProject, } from '../hubspot-project.js';
|
|
32
33
|
import { hydrateAncestorEnv } from '../load-env.js';
|
|
33
34
|
import { LocalProjectPickerCancelled, resolveLocalProject } from '../local-project-picker.js';
|
|
@@ -772,6 +773,15 @@ async function executeHubSpotDirectDeployCommand({ argv, root, json, }) {
|
|
|
772
773
|
force,
|
|
773
774
|
sourceFingerprint,
|
|
774
775
|
createClient: async () => context.createClient(),
|
|
776
|
+
...(!isLegacyProject(platformVersion)
|
|
777
|
+
? {
|
|
778
|
+
translateProject: () => context.runWithEnvironment((selectedAccount) => translateHubSpotProject({
|
|
779
|
+
projectSourceDir: join(root, descriptor.srcDir),
|
|
780
|
+
platformVersion,
|
|
781
|
+
accountId: Number(selectedAccount.id),
|
|
782
|
+
})),
|
|
783
|
+
}
|
|
784
|
+
: {}),
|
|
775
785
|
};
|
|
776
786
|
}
|
|
777
787
|
}
|
|
@@ -929,7 +939,6 @@ async function executeHubSpotDirectDeployCommand({ argv, root, json, }) {
|
|
|
929
939
|
});
|
|
930
940
|
}
|
|
931
941
|
try {
|
|
932
|
-
const step = machineOutput ? undefined : reporter.step('Uploading to HubSpot');
|
|
933
942
|
const uploaded = await executeHubSpotOnlyUpload({
|
|
934
943
|
argv,
|
|
935
944
|
root,
|
|
@@ -937,6 +946,7 @@ async function executeHubSpotDirectDeployCommand({ argv, root, json, }) {
|
|
|
937
946
|
persistBinding: false,
|
|
938
947
|
uploadOnly,
|
|
939
948
|
prepared: preparedUpload,
|
|
949
|
+
...(machineOutput ? {} : { progress: reporter }),
|
|
940
950
|
});
|
|
941
951
|
const buildState = readStatus(uploaded.buildStatus) ?? 'UNKNOWN';
|
|
942
952
|
const deployState = uploaded.deployStatus
|
|
@@ -944,7 +954,6 @@ async function executeHubSpotDirectDeployCommand({ argv, root, json, }) {
|
|
|
944
954
|
: undefined;
|
|
945
955
|
const deployUnverified = uploaded.autoDeployExpected && deployState === undefined;
|
|
946
956
|
const ok = buildState === 'SUCCESS' && !deployUnverified && (!deployState || deployState === 'SUCCESS');
|
|
947
|
-
step?.[ok ? 'ok' : 'fail'](`build #${uploaded.buildId} ${buildState}${deployState ? ` · deploy ${deployState}` : deployUnverified ? ' · deploy unverified' : ''}`);
|
|
948
957
|
const result = {
|
|
949
958
|
schema_version: 1,
|
|
950
959
|
ok,
|
|
@@ -970,7 +979,7 @@ async function executeHubSpotDirectDeployCommand({ argv, root, json, }) {
|
|
|
970
979
|
reporter.done(ok ? directDeployDoneMessage(uploaded) : 'HubSpot deploy failed', ok ? 0 : 1);
|
|
971
980
|
}
|
|
972
981
|
else {
|
|
973
|
-
streamHubSpotUploadOutcome(reporter, uploaded);
|
|
982
|
+
streamHubSpotUploadOutcome(reporter, uploaded, { componentMode: 'failures' });
|
|
974
983
|
if (deployUnverified) {
|
|
975
984
|
reporter.error('HSX_E_DEPLOY_HUBSPOT', 'HubSpot auto-deploy could not be verified before the timeout.', { hint: 'Check the project deploy status in HubSpot, then retry if it did not ship.' });
|
|
976
985
|
}
|
|
@@ -1455,31 +1464,22 @@ export async function deployCommand({ argv, root, json, }) {
|
|
|
1455
1464
|
// vs deploy-then-upload). A FAILED build resolves the step as a failure so
|
|
1456
1465
|
// the failing phase is visible in the transcript, not just the exit code.
|
|
1457
1466
|
const runHubSpotUploadPhase = async () => {
|
|
1458
|
-
const
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
}
|
|
1473
|
-
const buildState = readStatus(result.buildStatus) ?? 'UNKNOWN';
|
|
1474
|
-
const detail = `build #${result.buildId} ${buildState} (${elapsedSince(uploadStartedAt)})`;
|
|
1475
|
-
if (buildState === 'SUCCESS') {
|
|
1476
|
-
uploadStep?.ok(detail);
|
|
1477
|
-
}
|
|
1478
|
-
else {
|
|
1479
|
-
uploadStep?.fail(detail);
|
|
1480
|
-
}
|
|
1467
|
+
const result = await executeHubSpotOnlyUpload({
|
|
1468
|
+
argv,
|
|
1469
|
+
root,
|
|
1470
|
+
local: localHubspotUpload,
|
|
1471
|
+
uploadOnly: hubspotUploadOnly,
|
|
1472
|
+
...(progress
|
|
1473
|
+
? {
|
|
1474
|
+
progress: {
|
|
1475
|
+
step: (label) => progress.step(label),
|
|
1476
|
+
rows: (rows) => progress.reporter.rows(rows),
|
|
1477
|
+
},
|
|
1478
|
+
}
|
|
1479
|
+
: {}),
|
|
1480
|
+
});
|
|
1481
1481
|
if (echo)
|
|
1482
|
-
streamHubSpotUploadOutcome(echo, result);
|
|
1482
|
+
streamHubSpotUploadOutcome(echo, result, { componentMode: 'failures' });
|
|
1483
1483
|
return result;
|
|
1484
1484
|
};
|
|
1485
1485
|
if (uploadFirstOrigin && controlPlanePlan) {
|
|
@@ -2081,12 +2081,13 @@ function buildDeploySummaryRows(input) {
|
|
|
2081
2081
|
* diagnosable from the terminal, not the HubSpot UI (run-008 build #2 failed
|
|
2082
2082
|
* silently here).
|
|
2083
2083
|
*/
|
|
2084
|
-
function streamHubSpotUploadOutcome(reporter, upload) {
|
|
2084
|
+
function streamHubSpotUploadOutcome(reporter, upload, options = {}) {
|
|
2085
|
+
const componentMode = options.componentMode ?? 'all';
|
|
2085
2086
|
for (const subbuild of readSubbuildStatuses(upload.buildStatus)) {
|
|
2086
|
-
if (subbuild.status === 'SUCCESS') {
|
|
2087
|
+
if (subbuild.status === 'SUCCESS' && componentMode === 'all') {
|
|
2087
2088
|
reporter.info(` [ok] ${subbuild.name}${subbuild.type ? ` (${subbuild.type})` : ''}`);
|
|
2088
2089
|
}
|
|
2089
|
-
else {
|
|
2090
|
+
else if (subbuild.status !== 'SUCCESS' && componentMode !== 'none') {
|
|
2090
2091
|
reporter.error('HSX_E_DEPLOY_HUBSPOT_BUILD_COMPONENT', `${subbuild.name}${subbuild.type ? ` (${subbuild.type})` : ''}: ${subbuild.errorMessage ?? subbuild.status}`);
|
|
2091
2092
|
}
|
|
2092
2093
|
}
|
|
@@ -4288,15 +4289,35 @@ function runCloudflareCommand(command, options) {
|
|
|
4288
4289
|
},
|
|
4289
4290
|
})));
|
|
4290
4291
|
}
|
|
4291
|
-
async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = true, uploadOnly, prepared, }) {
|
|
4292
|
+
async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = true, uploadOnly, prepared, progress, }) {
|
|
4292
4293
|
// The HubSpot project name must match the name baked into the generated
|
|
4293
4294
|
// bundle (hsproject.json + app-hsmeta uid), not the on-disk directory name.
|
|
4294
4295
|
// Using basename(root) breaks when the project lives in a generic dir (e.g.
|
|
4295
4296
|
// `app/`): the upload targets a project named "app" while the bundle declares
|
|
4296
4297
|
// the real project id, and HubSpot rejects the mismatch with an opaque 400.
|
|
4297
4298
|
const projectName = prepared?.projectName ?? (await resolveHubSpotProjectName(argv, root));
|
|
4298
|
-
|
|
4299
|
+
let intermediateRepresentation = prepared?.intermediateRepresentation ??
|
|
4299
4300
|
(await readHubSpotProjectIntermediateRepresentation(root));
|
|
4301
|
+
if (prepared?.translateProject) {
|
|
4302
|
+
const translateStartedAt = Date.now();
|
|
4303
|
+
const translateStep = progress?.step('Translating HubSpot components');
|
|
4304
|
+
try {
|
|
4305
|
+
const translated = await prepared.translateProject();
|
|
4306
|
+
if (translated.skippedHsMetaFiles.length > 0 && !prepared.force) {
|
|
4307
|
+
throw new Error(`HubSpot skipped ${translated.skippedHsMetaFiles.length} component metadata file(s): ${translated.skippedHsMetaFiles.join(', ')}. Review them or re-run with --force.`);
|
|
4308
|
+
}
|
|
4309
|
+
intermediateRepresentation = translated.intermediateRepresentation;
|
|
4310
|
+
const nodes = isRecord(intermediateRepresentation)
|
|
4311
|
+
? intermediateRepresentation.intermediateNodesIndexedByUid
|
|
4312
|
+
: undefined;
|
|
4313
|
+
const componentCount = isRecord(nodes) ? Object.keys(nodes).length : 0;
|
|
4314
|
+
translateStep?.ok(`${componentCount} components · ${elapsedSince(translateStartedAt)}`);
|
|
4315
|
+
}
|
|
4316
|
+
catch (error) {
|
|
4317
|
+
translateStep?.fail(`${firstErrorLine(error)} · ${elapsedSince(translateStartedAt)}`);
|
|
4318
|
+
throw error;
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4300
4321
|
const appUid = prepared?.appUid ??
|
|
4301
4322
|
readAppUidFromIntermediateRepresentation(intermediateRepresentation) ??
|
|
4302
4323
|
(await readAppUidFromProjectSource(root));
|
|
@@ -4306,10 +4327,20 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4306
4327
|
const developerAccountId = prepared?.developerAccountId ??
|
|
4307
4328
|
resolveFlag(argv, '--developer-account-id') ??
|
|
4308
4329
|
process.env.HSX_HUBSPOT_DEVELOPER_ACCOUNT_ID;
|
|
4309
|
-
const
|
|
4310
|
-
|
|
4311
|
-
|
|
4312
|
-
|
|
4330
|
+
const packageStartedAt = Date.now();
|
|
4331
|
+
const packageStep = progress?.step('Packaging HubSpot project');
|
|
4332
|
+
let archivePath;
|
|
4333
|
+
try {
|
|
4334
|
+
archivePath = await writeLocalHubSpotProjectArchive(root, projectName, {
|
|
4335
|
+
sourceOnly: intermediateRepresentation !== undefined,
|
|
4336
|
+
...(prepared ? { expectedSourceFingerprint: prepared.sourceFingerprint } : {}),
|
|
4337
|
+
});
|
|
4338
|
+
packageStep?.ok(elapsedSince(packageStartedAt));
|
|
4339
|
+
}
|
|
4340
|
+
catch (error) {
|
|
4341
|
+
packageStep?.fail(`${firstErrorLine(error)} · ${elapsedSince(packageStartedAt)}`);
|
|
4342
|
+
throw error;
|
|
4343
|
+
}
|
|
4313
4344
|
const client = prepared
|
|
4314
4345
|
? await prepared.createClient()
|
|
4315
4346
|
: await createDeployHubSpotDeveloperClient({
|
|
@@ -4318,29 +4349,52 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4318
4349
|
allowedOperations: ['hubspot-project-upload'],
|
|
4319
4350
|
cwd: root,
|
|
4320
4351
|
});
|
|
4321
|
-
await client.projects.ensureProject({ projectName });
|
|
4322
4352
|
const hsproject = await readHubSpotProjectConfig(root);
|
|
4323
4353
|
const configuredPlatformVersion = typeof hsproject.platformVersion === 'string' ? hsproject.platformVersion : undefined;
|
|
4324
4354
|
const platformVersion = prepared?.platformVersion ??
|
|
4325
4355
|
resolveFlag(argv, '--platform-version') ??
|
|
4326
4356
|
configuredPlatformVersion ??
|
|
4327
4357
|
'2026.03';
|
|
4328
|
-
const upload = await client.projects.upload({
|
|
4329
|
-
projectName,
|
|
4330
|
-
archivePath,
|
|
4331
|
-
message: prepared?.buildMessage ?? resolveFlag(argv, '--message') ?? 'HS-X HubSpot-only deploy',
|
|
4332
|
-
platformVersion,
|
|
4333
|
-
intermediateRepresentation,
|
|
4334
|
-
skipAutoDeploy: uploadOnly,
|
|
4335
|
-
});
|
|
4336
4358
|
const timeoutMs = prepared?.buildTimeoutMs ?? Number(resolveFlag(argv, '--hubspot-build-timeout-ms') ?? '60000');
|
|
4337
|
-
const
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
|
|
4341
|
-
|
|
4342
|
-
|
|
4343
|
-
|
|
4359
|
+
const uploadStartedAt = Date.now();
|
|
4360
|
+
const uploadStep = progress?.step('Uploading project');
|
|
4361
|
+
let upload;
|
|
4362
|
+
try {
|
|
4363
|
+
await client.projects.ensureProject({ projectName });
|
|
4364
|
+
upload = await client.projects.upload({
|
|
4365
|
+
projectName,
|
|
4366
|
+
archivePath,
|
|
4367
|
+
message: prepared?.buildMessage ?? resolveFlag(argv, '--message') ?? 'HS-X HubSpot-only deploy',
|
|
4368
|
+
platformVersion,
|
|
4369
|
+
intermediateRepresentation,
|
|
4370
|
+
skipAutoDeploy: uploadOnly,
|
|
4371
|
+
});
|
|
4372
|
+
uploadStep?.ok(`build #${upload.buildId} · ${elapsedSince(uploadStartedAt)}`);
|
|
4373
|
+
}
|
|
4374
|
+
catch (error) {
|
|
4375
|
+
uploadStep?.fail(`${firstErrorLine(error)} · ${elapsedSince(uploadStartedAt)}`);
|
|
4376
|
+
throw error;
|
|
4377
|
+
}
|
|
4378
|
+
const buildStartedAt = Date.now();
|
|
4379
|
+
const buildStep = progress?.step(`Building project (build #${upload.buildId})`);
|
|
4380
|
+
const reportedComponents = new Map();
|
|
4381
|
+
let buildStatus;
|
|
4382
|
+
try {
|
|
4383
|
+
buildStatus = await waitForHubSpotBuildStatus({
|
|
4384
|
+
client,
|
|
4385
|
+
projectName,
|
|
4386
|
+
buildId: upload.buildId,
|
|
4387
|
+
timeoutMs,
|
|
4388
|
+
intervalMs: 1000,
|
|
4389
|
+
onStatus: (status) => streamHubSpotComponentProgress(progress, status, reportedComponents, 'build'),
|
|
4390
|
+
});
|
|
4391
|
+
}
|
|
4392
|
+
catch (error) {
|
|
4393
|
+
buildStep?.fail(`${firstErrorLine(error)} · ${elapsedSince(buildStartedAt)}`);
|
|
4394
|
+
throw error;
|
|
4395
|
+
}
|
|
4396
|
+
const buildState = readStatus(buildStatus) ?? 'UNKNOWN';
|
|
4397
|
+
buildStep?.[buildState === 'SUCCESS' ? 'ok' : 'fail'](`${buildState} · ${elapsedSince(buildStartedAt)}`);
|
|
4344
4398
|
const autoDeployEnabled = readBooleanProperty(buildStatus, 'isAutoDeployEnabled');
|
|
4345
4399
|
if (uploadOnly || readStatus(buildStatus) !== 'SUCCESS' || autoDeployEnabled) {
|
|
4346
4400
|
const appId = readStatus(buildStatus) === 'SUCCESS'
|
|
@@ -4358,15 +4412,32 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4358
4412
|
// Normal uploads can auto-deploy; uploadOnly sends skipAutoDeploy and is
|
|
4359
4413
|
// therefore a strict build-only result.
|
|
4360
4414
|
const autoDeployExpected = !uploadOnly && autoDeployEnabled === true && readStatus(buildStatus) === 'SUCCESS';
|
|
4361
|
-
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
|
|
4415
|
+
let autoDeployStatus;
|
|
4416
|
+
if (autoDeployExpected) {
|
|
4417
|
+
const deployStartedAt = Date.now();
|
|
4418
|
+
const deployStep = progress?.step(`Auto-deploying project (build #${upload.buildId})`);
|
|
4419
|
+
const reportedDeployComponents = new Map();
|
|
4420
|
+
try {
|
|
4421
|
+
const autoDeploy = await waitForHubSpotAutoDeploy({
|
|
4422
|
+
client,
|
|
4423
|
+
projectName,
|
|
4424
|
+
buildId: upload.buildId,
|
|
4425
|
+
buildStatus,
|
|
4426
|
+
timeoutMs,
|
|
4427
|
+
onStatus: (status) => streamHubSpotComponentProgress(progress, status, reportedDeployComponents, 'deploy'),
|
|
4428
|
+
});
|
|
4429
|
+
autoDeployStatus = autoDeploy.status;
|
|
4430
|
+
const state = readStatus(autoDeployStatus) ?? 'UNKNOWN';
|
|
4431
|
+
if (state === 'SUCCESS') {
|
|
4432
|
+
streamHubSpotComponentProgress(progress, buildStatus, reportedDeployComponents, 'deploy');
|
|
4433
|
+
}
|
|
4434
|
+
deployStep?.[state === 'SUCCESS' ? 'ok' : 'fail'](`deploy #${autoDeploy.deployId} ${state} · ${elapsedSince(deployStartedAt)}`);
|
|
4435
|
+
}
|
|
4436
|
+
catch (error) {
|
|
4437
|
+
deployStep?.fail(`${firstErrorLine(error)} · ${elapsedSince(deployStartedAt)}`);
|
|
4438
|
+
throw error;
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4370
4441
|
return {
|
|
4371
4442
|
projectName,
|
|
4372
4443
|
archivePath,
|
|
@@ -4382,15 +4453,31 @@ async function executeHubSpotOnlyUpload({ argv, root, local, persistBinding = tr
|
|
|
4382
4453
|
local,
|
|
4383
4454
|
};
|
|
4384
4455
|
}
|
|
4385
|
-
const
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4456
|
+
const deployStartedAt = Date.now();
|
|
4457
|
+
const deployStep = progress?.step(`Deploying project (build #${upload.buildId})`);
|
|
4458
|
+
const reportedDeployComponents = new Map();
|
|
4459
|
+
let deployed;
|
|
4460
|
+
try {
|
|
4461
|
+
deployed = await deployHubSpotProjectBuild({
|
|
4462
|
+
client,
|
|
4463
|
+
projectName,
|
|
4464
|
+
buildId: upload.buildId,
|
|
4465
|
+
force: prepared?.force ?? argv.includes('--force'),
|
|
4466
|
+
legacy: isLegacyProject(platformVersion),
|
|
4467
|
+
timeoutMs,
|
|
4468
|
+
onStatus: (status) => streamHubSpotComponentProgress(progress, status, reportedDeployComponents, 'deploy'),
|
|
4469
|
+
executeDeploy: (request) => withTransientDeployRetry(() => client.projects.deployBuild(request)),
|
|
4470
|
+
});
|
|
4471
|
+
const state = readStatus(deployed.status) ?? 'UNKNOWN';
|
|
4472
|
+
if (state === 'SUCCESS') {
|
|
4473
|
+
streamHubSpotComponentProgress(progress, buildStatus, reportedDeployComponents, 'deploy');
|
|
4474
|
+
}
|
|
4475
|
+
deployStep?.[state === 'SUCCESS' ? 'ok' : 'fail'](`deploy #${deployed.deployId} ${state} · ${elapsedSince(deployStartedAt)}`);
|
|
4476
|
+
}
|
|
4477
|
+
catch (error) {
|
|
4478
|
+
deployStep?.fail(`${firstErrorLine(error)} · ${elapsedSince(deployStartedAt)}`);
|
|
4479
|
+
throw error;
|
|
4480
|
+
}
|
|
4394
4481
|
const deployId = deployed.deployId;
|
|
4395
4482
|
const deployStatus = deployed.status;
|
|
4396
4483
|
const appId = await optionalHubSpotAppId(client, projectName, appUid);
|
|
@@ -4604,18 +4691,30 @@ async function resolveHubSpotAppAuthUrl(argv, root) {
|
|
|
4604
4691
|
function readStatus(value) {
|
|
4605
4692
|
return isRecord(value) && typeof value.status === 'string' ? value.status : undefined;
|
|
4606
4693
|
}
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4612
|
-
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4694
|
+
const readSubbuildStatuses = readHubSpotSubbuildStatuses;
|
|
4695
|
+
const HUBSPOT_COMPONENT_TERMINAL_STATES = new Set(['SUCCESS', 'FAILURE', 'ERROR', 'CANCELLED']);
|
|
4696
|
+
/** Emit each HubSpot component once, when it reaches a terminal build state. */
|
|
4697
|
+
function streamHubSpotComponentProgress(progress, buildStatus, reported, phase) {
|
|
4698
|
+
if (!progress)
|
|
4699
|
+
return;
|
|
4700
|
+
const rows = [];
|
|
4701
|
+
for (const component of readSubbuildStatuses(buildStatus)) {
|
|
4702
|
+
const state = component.status.toUpperCase();
|
|
4703
|
+
if (!HUBSPOT_COMPONENT_TERMINAL_STATES.has(state))
|
|
4704
|
+
continue;
|
|
4705
|
+
const key = `${component.name}\0${component.type ?? ''}`;
|
|
4706
|
+
if (reported.get(key) === state)
|
|
4707
|
+
continue;
|
|
4708
|
+
reported.set(key, state);
|
|
4709
|
+
rows.push({
|
|
4710
|
+
key: component.name,
|
|
4711
|
+
value: component.type ?? 'COMPONENT',
|
|
4712
|
+
status: state === 'SUCCESS' ? 'ok' : 'fail',
|
|
4713
|
+
detail: `${phase} ${state}`,
|
|
4714
|
+
...(component.errorMessage ? { hint: component.errorMessage } : {}),
|
|
4715
|
+
});
|
|
4716
|
+
}
|
|
4717
|
+
progress.rows(rows);
|
|
4619
4718
|
}
|
|
4620
4719
|
function hasFlag(argv, flag) {
|
|
4621
4720
|
return argv.includes(flag);
|