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
4 changes: 2 additions & 2 deletions command-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@
"alias": [],
"command": "agent:publish:authoring-bundle",
"flagAliases": [],
"flagChars": ["n", "o"],
"flags": ["api-name", "api-version", "flags-dir", "json", "skip-retrieve", "target-org"],
"flagChars": ["n", "o", "v"],
"flags": ["api-name", "api-version", "concise", "flags-dir", "json", "skip-retrieve", "target-org", "verbose"],
"plugin": "@salesforce/plugin-agent"
},
{
Expand Down
16 changes: 16 additions & 0 deletions messages/agent.publish.authoring-bundle.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ This command uses the API name of the authoring bundle.

<%= config.bin %> <%= command.id %> --api-name MyAuthoringbundle --target-org my-dev-org

- Publish with verbose output to see all retrieved and deployed metadata components:

<%= config.bin %> <%= command.id %> --api-name MyAuthoringbundle --verbose

- Publish with concise output showing only essential information:

<%= config.bin %> <%= command.id %> --api-name MyAuthoringbundle --concise

# flags.api-name.summary

API name of the authoring bundle you want to publish; if not specified, the command provides a list that you can choose from.
Expand All @@ -32,6 +40,14 @@ API name of the authoring bundle to publish

Don't retrieve the metadata associated with the agent to your DX project.

# flags.verbose.summary

Display detailed output showing all metadata components retrieved and deployed during the publish process.

# flags.concise.summary

Display minimal output with only essential information about the publish operation.

# error.missingRequiredFlags

Required flag(s) missing: %s.
Expand Down
25 changes: 25 additions & 0 deletions schemas/agent-publish-authoring__bundle.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@
"items": {
"type": "string"
}
},
"retrievedComponents": {
"type": "array",
"items": {
"type": "string"
}
},
"deployedComponents": {
"type": "array",
"items": {
"type": "string"
}
},
"summary": {
"type": "object",
"properties": {
"retrieved": {
"type": "number"
},
"deployed": {
"type": "number"
}
},
"required": ["retrieved", "deployed"],
"additionalProperties": false
}
},
"required": ["success"],
Expand Down
62 changes: 62 additions & 0 deletions src/commands/agent/publish/authoring-bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export type AgentPublishAuthoringBundleResult = {
success: boolean;
botDeveloperName?: string;
errors?: string[];
retrievedComponents?: string[];
deployedComponents?: string[];
summary?: {
retrieved: number;
deployed: number;
};
};

export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishAuthoringBundleResult> {
Expand All @@ -48,6 +54,15 @@ export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishA
'skip-retrieve': Flags.boolean({
summary: messages.getMessage('flags.skip-retrieve.summary'),
}),
verbose: Flags.boolean({
summary: messages.getMessage('flags.verbose.summary'),
char: 'v',
exclusive: ['concise'],
}),
concise: Flags.boolean({
summary: messages.getMessage('flags.concise.summary'),
exclusive: ['verbose'],
}),
};

private static readonly FLAGGABLE_PROMPTS = {
Expand Down Expand Up @@ -79,6 +94,11 @@ export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishA
flags['api-name'] ??
(await promptForAgentFiles(this.project!, AgentPublishAuthoringBundle.FLAGGABLE_PROMPTS['api-name']));

// Track retrieved and deployed components
const retrievedComponents: string[] = [];
const deployedComponents: string[] = [];
const outputMode = flags.verbose ? 'verbose' : flags.concise ? 'concise' : 'normal';

// Create multi-stage output
const mso = new MultiStageOutput<{ agentName: string }>({
stages: ['Validate Bundle', 'Publish Agent', 'Retrieve Metadata', 'Deploy Metadata'],
Expand Down Expand Up @@ -137,11 +157,42 @@ export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishA
mso.error();
throw SfError.create({ name: 'Retrieve Failed', message: errorMessage });
}

// Capture retrieved components
const fileProperties = ensureArray(result.retrieveResult.response.fileProperties ?? []);
fileProperties.forEach((fp) => {
const componentName = `${fp.type}${fp.fullName ? `:${fp.fullName}` : ''}`;
retrievedComponents.push(componentName);
});

// Display retrieved components based on output mode
if (outputMode === 'verbose' && !this.jsonEnabled()) {
this.log(`${EOL}Retrieved metadata components:`);
retrievedComponents.forEach((comp) => this.log(` • ${comp}`));
} else if (outputMode === 'normal' && !this.jsonEnabled()) {
this.log(`${EOL}Retrieved ${retrievedComponents.length} metadata component(s)`);
}

return Promise.resolve();
});

Lifecycle.getInstance().on('scopedPostDeploy', (result: ScopedPostDeploy) => {
if (result.deployResult.response.status === RequestStatus.Succeeded) {
// Capture deployed components
const deployedFiles = ensureArray(result.deployResult.response.details?.componentSuccesses ?? []);
deployedFiles.forEach((comp) => {
const componentName = `${String(comp.componentType)}${comp.fullName ? `:${String(comp.fullName)}` : ''}`;
deployedComponents.push(componentName);
});

// Display deployed components based on output mode
if (outputMode === 'verbose' && !this.jsonEnabled()) {
this.log(`${EOL}Deployed metadata components:`);
deployedComponents.forEach((comp) => this.log(` • ${comp}`));
} else if (outputMode === 'normal' && !this.jsonEnabled()) {
this.log(`${EOL}Deployed ${deployedComponents.length} metadata component(s)`);
}

mso.stop();
} else {
const deployResponse = result.deployResult.response;
Expand All @@ -159,9 +210,20 @@ export default class AgentPublishAuthoringBundle extends SfCommand<AgentPublishA
const result = await agent.publish(flags['skip-retrieve']);
mso.stop();

// Display final summary for normal mode
if (outputMode === 'normal' && !this.jsonEnabled() && !flags.concise) {
this.log(`${EOL}✓ Agent '${result.developerName}' published successfully`);
}

return {
success: true,
botDeveloperName: result.developerName,
retrievedComponents: flags.verbose ? retrievedComponents : undefined,
deployedComponents: flags.verbose ? deployedComponents : undefined,
summary: {
retrieved: retrievedComponents.length,
deployed: deployedComponents.length,
},
};
}
}
47 changes: 47 additions & 0 deletions test/nuts/z2.agent.publish.nut.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,4 +218,51 @@ describe('agent publish authoring-bundle NUTs', function () {
expect(output).to.include('Deploy Metadata');
expect(output).to.include(`Agent Name: ${bundleApiName}`);
});

it('should display detailed component listing with --verbose flag', async function () {
this.timeout(30 * 60 * 1000);
this.retries(1);

const result = execCmd<AgentPublishAuthoringBundleResult>(
`agent publish authoring-bundle --api-name ${bundleApiName} --target-org ${getUsername()} --verbose`,
{ ensureExitCode: 0 }
);

const output = result.shellOutput.stdout;
expect(output).to.include('Retrieved metadata components:');
expect(output).to.include('Deployed metadata components:');
expect(output).to.match(/•\s+\w/);
});

it('should include retrievedComponents and deployedComponents in JSON output with --verbose flag', async function () {
this.timeout(30 * 60 * 1000);
this.retries(1);

const result = execCmd<AgentPublishAuthoringBundleResult>(
`agent publish authoring-bundle --api-name ${bundleApiName} --target-org ${getUsername()} --verbose --json`,
{ ensureExitCode: 0 }
).jsonOutput?.result;

expect(result).to.be.ok;
expect(result?.success).to.be.true;
expect(result?.retrievedComponents).to.be.an('array');
expect(result?.deployedComponents).to.be.an('array');
expect(result?.retrievedComponents?.length).to.be.greaterThan(0);
expect(result?.deployedComponents?.length).to.be.greaterThan(0);
});

it('should suppress component counts and success message with --concise flag', async function () {
this.timeout(30 * 60 * 1000);
this.retries(1);

const result = execCmd<AgentPublishAuthoringBundleResult>(
`agent publish authoring-bundle --api-name ${bundleApiName} --target-org ${getUsername()} --concise`,
{ ensureExitCode: 0 }
);

const output = result.shellOutput.stdout;
expect(output).to.not.match(/Retrieved \d+ metadata component/);
expect(output).to.not.match(/Deployed \d+ metadata component/);
expect(output).to.not.include('published successfully');
});
});
Loading