added directly mode on some commands (#31)
This commit is contained in:
+143
-2
@@ -2,6 +2,54 @@
|
|||||||
|
|
||||||
**pwcli** is a CLI for Photowall platform that provides commands for deployment, AWS operations, workflow automation, and more.
|
**pwcli** is a CLI for Photowall platform that provides commands for deployment, AWS operations, workflow automation, and more.
|
||||||
|
|
||||||
|
## Quick Command Reference
|
||||||
|
|
||||||
|
```
|
||||||
|
pwcli
|
||||||
|
├── ai (ai)
|
||||||
|
│ └── promptcontextlibrary (pcl) ..................... ai pcl
|
||||||
|
│
|
||||||
|
├── aws (a)
|
||||||
|
│ ├── ecs (e)
|
||||||
|
│ │ └── sshtestserver (sts) ....................... a e sts
|
||||||
|
│ ├── logs (l) ....................................... a l
|
||||||
|
│ ├── parameterstore (ps)
|
||||||
|
│ │ ├── bulk-create (bc) .......................... a ps bc
|
||||||
|
│ │ ├── create (c) ................................ a ps c
|
||||||
|
│ │ ├── list (l) .................................. a ps l
|
||||||
|
│ │ └── update (u) ................................ a ps u
|
||||||
|
│ ├── pipeline (pl)
|
||||||
|
│ │ └── status (s) ................................ a pl s
|
||||||
|
│ └── s3 (s3)
|
||||||
|
│ ├── clear_prints (cp) ......................... a s3 cp
|
||||||
|
│ ├── print_on_station (pos) .................... a s3 pos
|
||||||
|
│ └── sync_images (si) .......................... a s3 si
|
||||||
|
│
|
||||||
|
├── deployment (d)
|
||||||
|
│ └── testservers (ts)
|
||||||
|
│ ├── create (c) ................................ d ts c
|
||||||
|
│ ├── delete (d) ................................ d ts d
|
||||||
|
│ ├── status (s) ................................ d ts s
|
||||||
|
│ └── update (u) ................................ d ts u
|
||||||
|
│
|
||||||
|
├── mandrill (m)
|
||||||
|
│ └── fix_template (ft) .............................. m ft
|
||||||
|
│
|
||||||
|
├── setup (s)
|
||||||
|
│ └── settings (se) .................................. s se
|
||||||
|
│
|
||||||
|
├── test (t)
|
||||||
|
│ └── routes (r) ..................................... t r
|
||||||
|
│
|
||||||
|
├── update (up) ........................................ up
|
||||||
|
│
|
||||||
|
└── workflow (wf)
|
||||||
|
├── git (g)
|
||||||
|
│ ├── clean_local_branches (clb) ................ wf g clb
|
||||||
|
│ └── clean_old_branches (cb) ................... wf g cb
|
||||||
|
└── setupissue (si) ................................ wf si
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Run `pwcli` to start the interactive menu, or use command shortcuts directly:
|
Run `pwcli` to start the interactive menu, or use command shortcuts directly:
|
||||||
@@ -81,12 +129,23 @@ Deployment and test server management
|
|||||||
- **create** (alias: `c`) - Create new testserver on AWS
|
- **create** (alias: `c`) - Create new testserver on AWS
|
||||||
- **delete** (alias: `d`) - Choose a testserver to delete
|
- **delete** (alias: `d`) - Choose a testserver to delete
|
||||||
- **status** (alias: `s`) - Show status for available testservers
|
- **status** (alias: `s`) - Show status for available testservers
|
||||||
|
- Flags:
|
||||||
|
- `--json` - Output status information in JSON format (non-interactive)
|
||||||
- **update** (alias: `u`) - Update stack with different branch
|
- **update** (alias: `u`) - Update stack with different branch
|
||||||
|
- Flags:
|
||||||
|
- `--branch <branch>` - Specify GitHub branch to deploy
|
||||||
|
- `--stack <stack>` - Specify test stack (formats: `photowall-test-01`, `test-01`, or `01`)
|
||||||
|
- `--skip-confirm` - Skip confirmation prompt when using parameters
|
||||||
|
- `--json` - Output result in JSON format with success flag and message
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
- `pwcli d ts s` - View testserver status
|
- `pwcli d ts s` - View testserver status (interactive)
|
||||||
|
- `pwcli d ts s --json` - View testserver status as JSON
|
||||||
- `pwcli d ts c` - Create new testserver
|
- `pwcli d ts c` - Create new testserver
|
||||||
- `pwcli d ts u` - Update existing testserver
|
- `pwcli d ts u` - Update existing testserver (interactive)
|
||||||
|
- `pwcli d ts u --branch feature/123 --stack test-01` - Update test-01 with feature/123 branch (with confirmation)
|
||||||
|
- `pwcli d ts u --branch feature/123 --stack test-01 --skip-confirm` - Update without confirmation
|
||||||
|
- `pwcli d ts u --branch feature/123 --stack 01 --skip-confirm --json` - Update and output JSON result
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -168,5 +227,87 @@ Settings are stored in `~/.pwcli_settings`
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Non-Interactive Mode & JSON Output
|
||||||
|
|
||||||
|
Several commands support non-interactive mode with JSON output, making them perfect for CI/CD pipelines and automation scripts.
|
||||||
|
|
||||||
|
### Testserver Status with JSON Output
|
||||||
|
|
||||||
|
Get testserver status information in JSON format:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pwcli d ts s --json
|
||||||
|
```
|
||||||
|
|
||||||
|
**JSON Output Format:**
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "photowall-test-01",
|
||||||
|
"status": "UPDATE_COMPLETE",
|
||||||
|
"branch": "feature/123-my-feature",
|
||||||
|
"issueNumber": "123",
|
||||||
|
"issueStatus": "✅ open",
|
||||||
|
"issueUpdated": "2025-11-06T10:30:00Z",
|
||||||
|
"created": "2025-10-15T08:00:00Z",
|
||||||
|
"updated": "2025-11-05T14:20:00Z",
|
||||||
|
"url": "https://test-01.photowall-test.com/us"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testserver Update - Non-Interactive
|
||||||
|
|
||||||
|
Update a testserver without interactive prompts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pwcli d ts u --branch feature/123 --stack test-01 --skip-confirm --json
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"message": "Successfully updated photowall-test-01 with branch feature/123 and started pipeline",
|
||||||
|
"stack": "photowall-test-01",
|
||||||
|
"branch": "feature/123",
|
||||||
|
"pipeline": "photowall-test-01Pipeline"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Error Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": false,
|
||||||
|
"message": "Not a valid branch on photowall repo: invalid-branch"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Automation Examples
|
||||||
|
|
||||||
|
**In a CI/CD Pipeline:**
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# Deploy to testserver and check result
|
||||||
|
result=$(pwcli d ts u --branch $CI_BRANCH --stack test-01 --skip-confirm --json)
|
||||||
|
success=$(echo $result | jq -r '.success')
|
||||||
|
|
||||||
|
if [ "$success" == "true" ]; then
|
||||||
|
echo "Deployment successful!"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Deployment failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check testserver availability:**
|
||||||
|
```bash
|
||||||
|
# Get all testservers and find an available one
|
||||||
|
pwcli d ts s --json | jq '.[] | select(.status == "UPDATE_COMPLETE") | .name'
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
For more information, visit the repository or run commands interactively with `pwcli`
|
For more information, visit the repository or run commands interactively with `pwcli`
|
||||||
|
|
||||||
|
|||||||
@@ -14,3 +14,27 @@ needed for the photowall organisation.
|
|||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
When running `pwcli` command in the terminal is will open a interactive view but all commands are accessable through shortcuts. So if you want to run status on development testservers its possible to run `pwcli d ts s` for d = development, ts = test servers, s = status. Shortcuts are listed in the interactive view.
|
When running `pwcli` command in the terminal is will open a interactive view but all commands are accessable through shortcuts. So if you want to run status on development testservers its possible to run `pwcli d ts s` for d = development, ts = test servers, s = status. Shortcuts are listed in the interactive view.
|
||||||
|
|
||||||
|
## Interactive Mode
|
||||||
|
|
||||||
|
Run commands interactively with prompts and menus:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pwcli # Open interactive menu
|
||||||
|
pwcli d ts u # Update testserver with interactive prompts
|
||||||
|
pwcli d ts s # View testserver status in table format
|
||||||
|
```
|
||||||
|
|
||||||
|
## Non-Interactive Mode
|
||||||
|
|
||||||
|
Many commands support non-interactive mode with parameters and JSON output, perfect for CI/CD and automation:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View testserver status as JSON
|
||||||
|
pwcli d ts s --json
|
||||||
|
|
||||||
|
# Update testserver without interactive prompts
|
||||||
|
pwcli d ts u --branch feature/123 --stack test-01 --skip-confirm --json
|
||||||
|
```
|
||||||
|
|
||||||
|
For detailed documentation including all flags, parameters, and JSON output formats, see [docs/help.md](docs/help.md).
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ module.exports = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for --json flag
|
||||||
|
const jsonOutput = toolbox.parameters.options.json;
|
||||||
|
|
||||||
const testStacks = await getTestStacksInfo(toolbox);
|
const testStacks = await getTestStacksInfo(toolbox);
|
||||||
const status = (status: string) => {
|
const status = (status: string) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -189,6 +192,33 @@ module.exports = {
|
|||||||
return aNumber - bNumber;
|
return aNumber - bNumber;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If JSON output is requested, output and return early
|
||||||
|
if (jsonOutput) {
|
||||||
|
const jsonData = testStacks.map((stack) => {
|
||||||
|
const regex = /^(\d+)/;
|
||||||
|
const match = stack.branch.match(regex);
|
||||||
|
const branchIssueNumber = match ? match[1] : null;
|
||||||
|
const issueStatus = issueStatuses.find(
|
||||||
|
(issueStatus) => issueStatus.issue === branchIssueNumber,
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: stack.name,
|
||||||
|
status: stack.status,
|
||||||
|
branch: stack.branch,
|
||||||
|
issueNumber: branchIssueNumber,
|
||||||
|
issueStatus: issueStatus ? issueStatus.status : getStatusIcon('null'),
|
||||||
|
issueUpdated: issueStatus ? issueStatus.issueUpdated : null,
|
||||||
|
created: stack.created,
|
||||||
|
updated: stack.updated,
|
||||||
|
url: stackUrl(stack.name),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(JSON.stringify(jsonData, null, 2));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (const stack of testStacks) {
|
for (const stack of testStacks) {
|
||||||
const regex = /^(\d+)/;
|
const regex = /^(\d+)/;
|
||||||
const match = stack.branch.match(regex);
|
const match = stack.branch.match(regex);
|
||||||
|
|||||||
@@ -80,9 +80,30 @@ module.exports = {
|
|||||||
run: async (toolbox: GluegunMenuToolbox) => {
|
run: async (toolbox: GluegunMenuToolbox) => {
|
||||||
const { system, strings, print } = toolbox;
|
const { system, strings, print } = toolbox;
|
||||||
|
|
||||||
|
// Check for parameters
|
||||||
|
const jsonOutput = toolbox.parameters.options.json;
|
||||||
|
const branchParam = toolbox.parameters.options.branch;
|
||||||
|
const stackParam =
|
||||||
|
toolbox.parameters.options.stack || toolbox.parameters.options.server;
|
||||||
|
const skipConfirm = toolbox.parameters.options['skip-confirm'];
|
||||||
|
|
||||||
// Load settings
|
// Load settings
|
||||||
const config = await getSettings(toolbox);
|
const config = await getSettings(toolbox);
|
||||||
if (!config || !config.photowall_repo || config.photowall_repo === '') {
|
if (!config || !config.photowall_repo || config.photowall_repo === '') {
|
||||||
|
if (jsonOutput) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message:
|
||||||
|
'The update command requires that you set an absolute path to your local photowall repository.',
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
print.error(`
|
print.error(`
|
||||||
|
|
||||||
The create command requires that you set an absolute path to your local photowall repository.
|
The create command requires that you set an absolute path to your local photowall repository.
|
||||||
@@ -93,6 +114,41 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let branchName = null;
|
let branchName = null;
|
||||||
|
|
||||||
|
// If branch is provided as parameter, validate it
|
||||||
|
if (branchParam) {
|
||||||
|
const octokit = new Octokit({ auth: config.gh_token });
|
||||||
|
try {
|
||||||
|
const response = await octokit.request(
|
||||||
|
'GET /repos/{owner}/{repo}/branches/{branch}',
|
||||||
|
{
|
||||||
|
owner: 'photowall',
|
||||||
|
repo: 'photowall',
|
||||||
|
branch: branchParam,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (response.status === 200) {
|
||||||
|
branchName = branchParam;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (jsonOutput) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: `Not a valid branch on photowall repo: ${branchParam}`,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print.error(`Not a valid branch on photowall repo: ${branchParam}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Interactive mode - ask for branch
|
||||||
while (!branchName) {
|
while (!branchName) {
|
||||||
branchName = await getBranchName(
|
branchName = await getBranchName(
|
||||||
toolbox,
|
toolbox,
|
||||||
@@ -100,8 +156,45 @@ module.exports = {
|
|||||||
config.photowall_repo,
|
config.photowall_repo,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const testStacks = await getTestStacksInfo(toolbox);
|
const testStacks = await getTestStacksInfo(toolbox);
|
||||||
|
let stackName = null;
|
||||||
|
|
||||||
|
// If stack is provided as parameter, validate it
|
||||||
|
if (stackParam) {
|
||||||
|
const foundStack = testStacks.find((stack) => {
|
||||||
|
return (
|
||||||
|
stack.name === stackParam ||
|
||||||
|
stack.name === `photowall-${stackParam}` ||
|
||||||
|
stack.name.replace('photowall-', '') === stackParam
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (foundStack) {
|
||||||
|
stackName = foundStack.name;
|
||||||
|
} else {
|
||||||
|
if (jsonOutput) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: `Stack not found: ${stackParam}`,
|
||||||
|
availableStacks: testStacks.map((s) => s.name),
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print.error(`Stack not found: ${stackParam}`);
|
||||||
|
print.info('Available stacks:');
|
||||||
|
testStacks.forEach((s) => print.info(` - ${s.name}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Interactive mode - ask for stack
|
||||||
const options = testStacks.map((item) => {
|
const options = testStacks.map((item) => {
|
||||||
return item.name;
|
return item.name;
|
||||||
});
|
});
|
||||||
@@ -114,19 +207,29 @@ module.exports = {
|
|||||||
choices: options,
|
choices: options,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
stackName = await prompt.run();
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stackName = await prompt.run();
|
|
||||||
const stacksuffix = stackName.replace('photowall-', '');
|
const stacksuffix = stackName.replace('photowall-', '');
|
||||||
|
|
||||||
const shouldRun = await getConfirmation(branchName, stackName);
|
// Skip confirmation if parameters are provided or skip-confirm flag is set
|
||||||
|
const shouldRun =
|
||||||
|
branchParam && stackParam
|
||||||
|
? skipConfirm
|
||||||
|
? true
|
||||||
|
: await getConfirmation(branchName, stackName)
|
||||||
|
: await getConfirmation(branchName, stackName);
|
||||||
|
|
||||||
if (shouldRun) {
|
if (shouldRun) {
|
||||||
const cmd = `make update-stack STACK_ENVIRONMENT_NAME=${stacksuffix} GITHUB_BRANCH=${branchName}`;
|
const cmd = `make update-stack STACK_ENVIRONMENT_NAME=${stacksuffix} GITHUB_BRANCH=${branchName}`;
|
||||||
|
if (!jsonOutput) {
|
||||||
print.fancy(
|
print.fancy(
|
||||||
`Running [${chalk.yellow(
|
`Running [${chalk.yellow(
|
||||||
cmd,
|
cmd,
|
||||||
)}] in folder [${`${config.photowall_repo}/cloudformation/`}]`,
|
)}] in folder [${`${config.photowall_repo}/cloudformation/`}]`,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
const child = spawn(
|
const child = spawn(
|
||||||
'make',
|
'make',
|
||||||
[
|
[
|
||||||
@@ -140,10 +243,14 @@ module.exports = {
|
|||||||
);
|
);
|
||||||
child.stdout.setEncoding('utf8');
|
child.stdout.setEncoding('utf8');
|
||||||
child.stdout.on('data', (data) => {
|
child.stdout.on('data', (data) => {
|
||||||
|
if (!jsonOutput) {
|
||||||
process.stdout.write(data);
|
process.stdout.write(data);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
child.stderr.on('data', (data) => {
|
child.stderr.on('data', (data) => {
|
||||||
|
if (!jsonOutput) {
|
||||||
process.stderr.write(data);
|
process.stderr.write(data);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
child.on('close', (code) => {
|
child.on('close', (code) => {
|
||||||
@@ -156,13 +263,17 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Check the status
|
// Check the status
|
||||||
const spinner = print.spin(`Waiting for stack to update`);
|
const spinner = jsonOutput
|
||||||
|
? null
|
||||||
|
: print.spin(`Waiting for stack to update`);
|
||||||
let currentStackStatus = '';
|
let currentStackStatus = '';
|
||||||
while (currentStackStatus !== 'UPDATE_COMPLETE') {
|
while (currentStackStatus !== 'UPDATE_COMPLETE') {
|
||||||
const stackCmd = `aws cloudformation describe-stacks --stack-name photowall-${stacksuffix}`;
|
const stackCmd = `aws cloudformation describe-stacks --stack-name photowall-${stacksuffix}`;
|
||||||
const response = await system.run(stackCmd, { trim: true });
|
const response = await system.run(stackCmd, { trim: true });
|
||||||
const stackData = JSON.parse(response);
|
const stackData = JSON.parse(response);
|
||||||
currentStackStatus = stackData.Stacks[0].StackStatus;
|
currentStackStatus = stackData.Stacks[0].StackStatus;
|
||||||
|
|
||||||
|
if (!jsonOutput) {
|
||||||
let statusOutput = '';
|
let statusOutput = '';
|
||||||
switch (currentStackStatus) {
|
switch (currentStackStatus) {
|
||||||
case 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS':
|
case 'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS':
|
||||||
@@ -182,23 +293,80 @@ module.exports = {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
spinner.text = statusOutput;
|
spinner.text = statusOutput;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentStackStatus !== 'UPDATE_COMPLETE') {
|
if (currentStackStatus !== 'UPDATE_COMPLETE') {
|
||||||
await sleep(1000);
|
await sleep(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!jsonOutput) {
|
||||||
spinner.text = `Will start the pipeline now [${chalk.yellow(
|
spinner.text = `Will start the pipeline now [${chalk.yellow(
|
||||||
`photowall-${stacksuffix}Pipeline`,
|
`photowall-${stacksuffix}Pipeline`,
|
||||||
)}]`;
|
)}]`;
|
||||||
|
}
|
||||||
|
|
||||||
const runPipelineCmd = `aws codepipeline start-pipeline-execution --name photowall-${stacksuffix}Pipeline`;
|
const runPipelineCmd = `aws codepipeline start-pipeline-execution --name photowall-${stacksuffix}Pipeline`;
|
||||||
await system.run(runPipelineCmd);
|
await system.run(runPipelineCmd);
|
||||||
await sleep(2000);
|
await sleep(2000);
|
||||||
|
|
||||||
|
if (jsonOutput) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
success: true,
|
||||||
|
message: `Successfully updated ${stackName} with branch ${branchName} and started pipeline`,
|
||||||
|
stack: stackName,
|
||||||
|
branch: branchName,
|
||||||
|
pipeline: `photowall-${stacksuffix}Pipeline`,
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
spinner.stop();
|
spinner.stop();
|
||||||
print.fancy('Pipeline started, bye! 🚀');
|
print.fancy('Pipeline started, bye! 🚀');
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// User cancelled
|
||||||
|
if (jsonOutput) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: 'Update cancelled by user',
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
print.info('Update cancelled');
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (jsonOutput) {
|
||||||
|
console.log(
|
||||||
|
JSON.stringify(
|
||||||
|
{
|
||||||
|
success: false,
|
||||||
|
message: `Error during update: ${e.message || e}`,
|
||||||
|
error: e.message || String(e),
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
2,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
console.log(`e`, e);
|
console.log(`e`, e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip menu if using parameters or JSON output
|
||||||
|
if (jsonOutput || (branchParam && stackParam)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (toolbox.fromMenu()) {
|
if (toolbox.fromMenu()) {
|
||||||
await toolbox.menu.showMenu(
|
await toolbox.menu.showMenu(
|
||||||
|
|||||||
Reference in New Issue
Block a user