@capawesome/cli
Version:
The Capawesome Cloud Command Line Interface (CLI) to manage Live Updates and more.
113 lines (112 loc) • 4.72 kB
JavaScript
import { DEFAULT_CONSOLE_BASE_URL } from '../../../config/consts.js';
import appChannelsService from '../../../services/app-channels.js';
import appDeploymentsService from '../../../services/app-deployments.js';
import { withAuth } from '../../../utils/auth.js';
import { isInteractive } from '../../../utils/environment.js';
import { prompt, promptAppSelection, promptOrganizationSelection } from '../../../utils/prompt.js';
import { defineCommand, defineOptions } from '@robingenz/zli';
import consola from 'consola';
import { z } from 'zod';
export default defineCommand({
description: 'Update the rollout percentage of the active build in a channel.',
options: defineOptions(z.object({
appId: z
.uuid({
message: 'App ID must be a UUID.',
})
.optional()
.describe('App ID of the channel.'),
channel: z.string().optional().describe('Name of the channel to update rollout for.'),
percentage: z.coerce
.number()
.int({
message: 'Percentage must be an integer.',
})
.min(0, {
message: 'Percentage must be at least 0.',
})
.max(100, {
message: 'Percentage must be at most 100.',
})
.optional()
.describe('Rollout percentage (0-100).'),
})),
action: withAuth(async (options) => {
let { appId, channel, percentage } = options;
// Prompt for app ID if not provided
if (!appId) {
if (!isInteractive()) {
consola.error('You must provide an app ID when running in non-interactive environment.');
process.exit(1);
}
const organizationId = await promptOrganizationSelection();
appId = await promptAppSelection(organizationId);
}
// Prompt for channel name if not provided
if (!channel) {
if (!isInteractive()) {
consola.error('You must provide a channel when running in non-interactive environment.');
process.exit(1);
}
channel = await prompt('Enter the channel name to update rollout for:', {
type: 'text',
});
if (!channel) {
consola.error('You must enter a channel name to update rollout for.');
process.exit(1);
}
}
// Fetch channel by name
const appChannels = await appChannelsService.findAll({ appId, name: channel });
if (appChannels.length === 0) {
consola.error(`Channel not found.`);
process.exit(1);
}
const appChannelId = appChannels[0]?.id;
if (!appChannelId) {
consola.error('Channel ID is missing.');
process.exit(1);
}
// Fetch channel with deployment relation
const appChannel = await appChannelsService.findOneById({
appId,
id: appChannelId,
relations: 'appDeployment',
});
// Validate that the channel has an active build assigned
if (!appChannel.appDeployment) {
consola.error('Channel has no active build assigned.');
process.exit(1);
}
// Prompt for percentage if not provided
if (percentage === undefined) {
if (!isInteractive()) {
consola.error('You must provide --percentage when running in non-interactive environment.');
process.exit(1);
}
const percentageInput = await prompt('Enter the rollout percentage (0-100):', {
type: 'text',
});
if (!percentageInput) {
consola.error('You must enter a rollout percentage.');
process.exit(1);
}
percentage = parseInt(percentageInput, 10);
if (isNaN(percentage) || percentage < 0 || percentage > 100) {
consola.error('Percentage must be a number between 0 and 100.');
process.exit(1);
}
}
// Update deployment rollout percentage
consola.start('Updating rollout percentage...');
const response = await appDeploymentsService.update({
appId,
appDeploymentId: appChannel.appDeployment.id,
// Convert percentage from 0-100 to 0-1 for API
rolloutPercentage: percentage / 100,
});
consola.info(`Deployment ID: ${response.id}`);
consola.info(`Deployment URL: ${DEFAULT_CONSOLE_BASE_URL}/apps/${appId}/deployments/${response.id}`);
consola.success(`Rolled out to ${percentage}%.`);
}),
});