Skip to content

Commit 72a8e9a

Browse files
authored
feat: collect 'em low-hanging-fruits (#85)
fixes #65 ### Profiles and help UX - Added dedicated `c8 help profiles` output (including `profile` alias handling) in `src/commands/help.ts`. - Expanded command-help discoverability in shell completion suggestions in `src/commands/completion.ts`. - Updated profile/help documentation in `README.md` and `EXAMPLES.md`. - Added/updated help test coverage in `tests/unit/help.test.ts`. ### Profile/auth fix - Fixed cloud Modeler mapping so `audience` stays optional unless explicitly configured (instead of being forced) in `src/config.ts`. - Added regression coverage in `tests/unit/config.test.ts`. ### Search behavior and test stability - Improved process-definition search determinism (sorting by version/key) and strengthened case-insensitive behavior/pagination in `src/commands/search.ts`. - Stabilized integration polling/filter behavior in `tests/integration/search.test.ts` to avoid eventual-consistency flakiness. ### Plugin management improvements - Implemented source-aware plugin upgrade/downgrade behavior with clearer actionable hints in `src/commands/plugins.ts`. - Enhanced plugin listing/version visibility and added lifecycle/version test coverage in: - `tests/integration/plugin-lifecycle.test.ts` - `tests/unit/plugins-version.test.ts` - Added plugin-help documentation in `PLUGIN-HELP.md`.
1 parent 771a590 commit 72a8e9a

File tree

13 files changed

+752
-39
lines changed

13 files changed

+752
-39
lines changed

EXAMPLES.md

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -666,13 +666,38 @@ c8ctl supports two types of profiles:
666666
1. **c8ctl profiles**: Directly managed by c8ctl commands
667667
2. **Modeler profiles**: Automatically imported from Camunda Modeler (read-only)
668668

669+
### Show Profile Help
670+
671+
```bash
672+
# Show all profile-related commands and flags
673+
c8 help profiles
674+
```
675+
669676
### Add c8ctl Profile
670677

678+
`c8 add profile <name>` usage rules:
679+
680+
- **Always required**: profile `<name>`
681+
- **Required for OAuth-secured clusters**: `--clientId`, `--clientSecret`
682+
- **Optional with defaults**:
683+
- `--baseUrl` (default: `http://localhost:8080/v2`)
684+
- `--defaultTenantId` (runtime default tenant: `<default>`)
685+
- **Optional without c8ctl defaults**: `--audience`, `--oAuthUrl`
686+
671687
```bash
672-
# Add profile with basic auth (localhost)
688+
# Minimal local profile (uses default --baseUrl)
689+
c8 add profile local
690+
691+
# Local profile with explicit URL
673692
c8 add profile local --baseUrl=http://localhost:8080
674693

675-
# Add profile with OAuth
694+
# Minimal OAuth profile (required OAuth switches)
695+
c8 add profile prod \
696+
--baseUrl=https://camunda.example.com \
697+
--clientId=your-client-id \
698+
--clientSecret=your-client-secret
699+
700+
# OAuth profile with explicit audience/token endpoint
676701
c8 add profile prod \
677702
--baseUrl=https://camunda.example.com \
678703
--clientId=your-client-id \
@@ -812,14 +837,14 @@ c8 unload plugin my-custom-plugin
812837
### List Plugins
813838

814839
```bash
815-
# Show all installed c8ctl plugins with sync status
840+
# Show all installed c8ctl plugins with version and sync status
816841
c8 list plugins
817842

818843
# Example output:
819-
# Name | Status | Source | Installed At
820-
# ------------------+-------------+---------------------------+----------------------
821-
# my-custom-plugin | ✓ Installed | my-custom-plugin | 1/30/2026, 6:00:00 PM
822-
# local-dev-plugin | ⚠ Not installed | file:///path/to/plugin | 1/30/2026, 5:00:00 PM
844+
# Name | Version | Status | Source | Installed At
845+
# ------------------+---------+-----------------+---------------------------+----------------------
846+
# my-custom-plugin | 1.2.0 | ✓ Installed | my-custom-plugin | 1/30/2026, 6:00:00 PM
847+
# local-dev-plugin | Unknown | ⚠ Not installed | file:///path/to/plugin | 1/30/2026, 5:00:00 PM
823848

824849
# If any plugins are out of sync, you'll see a hint to run sync
825850
```
@@ -852,6 +877,33 @@ c8 sync plugins
852877
# ✓ All plugins synced successfully!
853878
```
854879

880+
### Downgrade Plugin
881+
882+
```bash
883+
# Downgrade a plugin by version
884+
c8 downgrade plugin my-custom-plugin 1.0.0
885+
886+
# Downgrade is source-aware:
887+
# - npm source: installs my-custom-plugin@1.0.0
888+
# - git/URL source: installs <source>#1.0.0
889+
# - file:// source: version downgrade is not supported
890+
```
891+
892+
### Upgrade Plugin
893+
894+
```bash
895+
# Upgrade a plugin to latest
896+
c8 upgrade plugin my-custom-plugin
897+
898+
# Upgrade a plugin to a specific version
899+
c8 upgrade plugin my-custom-plugin 1.2.3
900+
901+
# Versioned upgrade is source-aware:
902+
# - npm source: installs my-custom-plugin@1.2.3
903+
# - git/URL source: installs <source>#1.2.3
904+
# - file:// source: version upgrade is not supported
905+
```
906+
855907
**Plugin Development:**
856908

857909
Plugins must be regular Node.js modules with a `c8ctl-plugin.js` or `c8ctl-plugin.ts` file in the root directory. The plugin file must export a `commands` object. The `c8ctl` runtime object provides environment information:

PLUGIN-HELP.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,22 @@ Plugin Commands:
151151
status Check cluster status
152152
```
153153

154+
### Source-Aware Upgrade and Downgrade
155+
156+
Plugin version changes (`upgrade` / `downgrade`) use the registry `source` value and therefore behave differently based on source type:
157+
158+
- **npm package source**
159+
- `c8ctl upgrade plugin <name> <version>` installs `<name>@<version>`
160+
- `c8ctl downgrade plugin <name> <version>` installs `<name>@<version>`
161+
- **URL/git source**
162+
- `c8ctl upgrade plugin <name> <version>` installs `<source>#<version>`
163+
- `c8ctl downgrade plugin <name> <version>` installs `<source>#<version>`
164+
- **file source (`file://`)**
165+
- Version-based upgrade/downgrade is not supported
166+
- Use `c8ctl load plugin --from <file-url>` after checking out the desired local plugin version
167+
168+
For `c8ctl upgrade plugin <name>` without a version, c8ctl reinstalls the registered source as-is
169+
154170
## Implementation Details
155171

156172
### Plugin Loader

README.md

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ c8ctl help fail # Shows fail command with all flags
8787
c8ctl help activate # Shows activate command with all flags
8888
c8ctl help publish # Shows publish command with all flags
8989
c8ctl help correlate # Shows correlate command with all flags
90+
c8ctl help profiles # Shows profile management help
91+
c8ctl help plugin # Shows plugin management help
9092

9193
# Show version
9294
c8ctl --version
@@ -237,6 +239,12 @@ c8ctl supports two types of profiles:
237239
1. **c8ctl profiles**: Managed directly by c8ctl
238240
2. **Camunda Modeler profiles**: Automatically imported from Camunda Modeler (with `modeler:` prefix)
239241

242+
For profile-related commands and flags, run:
243+
244+
```bash
245+
c8ctl help profiles
246+
```
247+
240248
```bash
241249
# Add a c8ctl profile
242250
c8 add profile prod --baseUrl=https://camunda.example.com --clientId=xxx --clientSecret=yyy
@@ -246,7 +254,7 @@ c8 list profiles
246254

247255
# Set active profile (works with both types)
248256
c8 use profile prod
249-
c8 use profile modeler:Local Dev
257+
c8 use profile "modeler:Local Dev"
250258

251259
# Remove c8ctl profile (modeler profiles are read-only)
252260
c8 remove profile prod
@@ -349,7 +357,7 @@ c8ctl downgrade plugin <package-name> 1.0.0
349357
# Unload a plugin
350358
c8ctl unload plugin <package-name>
351359

352-
# List installed plugins (shows sync status)
360+
# List installed plugins (shows version and sync status)
353361
c8ctl list plugins
354362

355363
# Synchronize plugins from registry
@@ -369,11 +377,20 @@ c8ctl help
369377
- The registry serves as the source of truth for installed plugins
370378
- Default plugins are bundled with c8ctl and loaded automatically
371379
- **Plugin commands cannot override built-in commands** - built-in commands always take precedence
372-
- `c8ctl list plugins` shows sync status:
380+
- `c8ctl list plugins` shows plugin versions and sync status:
373381
- `✓ Installed` - Plugin is in registry and installed
374382
- `⚠ Not installed` - Plugin is in registry but not in global directory (run `sync`)
375383
- `⚠ Not in registry` - Plugin is installed but not tracked in registry
376384
- `c8ctl sync plugins` synchronizes plugins from the registry, rebuilding or reinstalling as needed
385+
- `c8ctl upgrade plugin <name> [version]` respects the plugin source from the registry:
386+
- without `version`: reinstalls the registered source as-is
387+
- npm package source with `version`: installs `<name>@<version>`
388+
- URL/git source with `version`: installs `<source>#<version>`
389+
- file source (`file://`) with `version`: version upgrade is not supported; use `load plugin --from` with the desired local plugin checkout
390+
- `c8ctl downgrade plugin <name> <version>` respects the plugin source from the registry:
391+
- npm package source: installs `<name>@<version>`
392+
- URL/git source: installs `<source>#<version>`
393+
- file source (`file://`): version downgrade is not supported; use `load plugin --from` with the desired local plugin checkout
377394

378395
**Plugin Development:**
379396
- Use `c8ctl init plugin <name>` to scaffold a new plugin with TypeScript template

src/commands/completion.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ _c8ctl_completions() {
4646
local use_resources="profile tenant"
4747
local output_resources="json text"
4848
local completion_resources="bash zsh fish"
49-
local help_resources="list get create complete await search deploy run watch cancel resolve fail activate publish correlate upgrade downgrade init"
49+
local help_resources="list get create complete await search deploy run watch cancel resolve fail activate publish correlate upgrade downgrade init profiles profile plugin plugins"
5050
5151
# Global flags
5252
local flags="--help --version --profile --from --all --bpmnProcessId --id --processInstanceKey --processDefinitionKey --parentProcessInstanceKey --variables --state --assignee --type --correlationKey --timeToLive --maxJobsToActivate --timeout --worker --retries --errorMessage --baseUrl --clientId --clientSecret --audience --oAuthUrl --defaultTenantId --awaitCompletion --fetchVariables --requestTimeout --name --key --elementId --errorType --value --scopeKey --fullValue --userTask --ut --processDefinition --pd --iname --iid --iassignee --ierrorMessage --itype --ivalue"
@@ -458,6 +458,10 @@ _c8ctl() {
458458
'upgrade:Show upgrade command help'
459459
'downgrade:Show downgrade command help'
460460
'init:Show init command help'
461+
'profiles:Show profile management help'
462+
'profile:Alias for profile management help'
463+
'plugin:Show plugin management help'
464+
'plugins:Alias for plugin management help'
461465
)
462466
_describe 'resource' resources
463467
;;
@@ -867,6 +871,14 @@ complete -c c8ctl -n '__fish_seen_subcommand_from help' -a 'downgrade' -d 'Show
867871
complete -c c8 -n '__fish_seen_subcommand_from help' -a 'downgrade' -d 'Show downgrade command help'
868872
complete -c c8ctl -n '__fish_seen_subcommand_from help' -a 'init' -d 'Show init command help'
869873
complete -c c8 -n '__fish_seen_subcommand_from help' -a 'init' -d 'Show init command help'
874+
complete -c c8ctl -n '__fish_seen_subcommand_from help' -a 'profiles' -d 'Show profile management help'
875+
complete -c c8 -n '__fish_seen_subcommand_from help' -a 'profiles' -d 'Show profile management help'
876+
complete -c c8ctl -n '__fish_seen_subcommand_from help' -a 'profile' -d 'Alias for profile management help'
877+
complete -c c8 -n '__fish_seen_subcommand_from help' -a 'profile' -d 'Alias for profile management help'
878+
complete -c c8ctl -n '__fish_seen_subcommand_from help' -a 'plugin' -d 'Show plugin management help'
879+
complete -c c8 -n '__fish_seen_subcommand_from help' -a 'plugin' -d 'Show plugin management help'
880+
complete -c c8ctl -n '__fish_seen_subcommand_from help' -a 'plugins' -d 'Alias for plugin management help'
881+
complete -c c8 -n '__fish_seen_subcommand_from help' -a 'plugins' -d 'Alias for plugin management help'
870882
`;
871883
}
872884

src/commands/help.ts

Lines changed: 119 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Commands:
7070
load plugin <name> Load a c8ctl plugin from npm registry
7171
load plugin --from Load a c8ctl plugin from URL (file://, https://, git://)
7272
unload plugin <name> Unload a c8ctl plugin (npm uninstall wrapper)
73-
upgrade plugin <name> [version] Upgrade a plugin to latest or specific version
73+
upgrade plugin <name> [version] Upgrade a plugin (respects source type)
7474
downgrade plugin <name> <version> Downgrade a plugin to a specific version
7575
sync plugin Synchronize plugins from registry (rebuild/reinstall)
7676
init plugin [name] Create a new plugin from TypeScript template
@@ -167,6 +167,7 @@ Examples:
167167
c8ctl load plugin my-plugin Load plugin from npm registry
168168
c8ctl load plugin --from file:///path/to/plugin Load plugin from file URL
169169
c8ctl upgrade plugin my-plugin Upgrade plugin to latest version
170+
c8ctl upgrade plugin my-plugin 1.2.3 Upgrade plugin to a specific version (source-aware)
170171
c8ctl sync plugin Synchronize plugins
171172
c8ctl completion bash Generate bash completion script
172173
@@ -187,6 +188,9 @@ For detailed help on specific commands with all available flags:
187188
c8ctl help activate Show activate command with all flags
188189
c8ctl help publish Show publish command with all flags
189190
c8ctl help correlate Show correlate command with all flags
191+
c8ctl help profiles Show profile management help
192+
c8ctl help plugin Show plugin management help
193+
c8ctl help plugins Alias for plugin management help
190194
`.trim());
191195
}
192196

@@ -219,7 +223,7 @@ export function showVerbResources(verb: string): void {
219223
use: 'profile, tenant',
220224
output: 'json, text',
221225
completion: 'bash, zsh, fish',
222-
help: 'list, get, create, complete, await, search, deploy, run, watch, cancel, resolve, fail, activate, publish, correlate, upgrade, downgrade, init',
226+
help: 'list, get, create, complete, await, search, deploy, run, watch, cancel, resolve, fail, activate, publish, correlate, upgrade, downgrade, init, profiles, profile, plugin, plugins',
223227
};
224228

225229
const available = resources[verb];
@@ -273,7 +277,7 @@ Resources and their available flags:
273277
(Modeler profiles are shown with 'modeler:' prefix)
274278
275279
plugins
276-
Shows installed plugins with sync status
280+
Shows installed plugins with version and sync status
277281
278282
Examples:
279283
c8ctl list pi --state=ACTIVE
@@ -813,6 +817,110 @@ Examples:
813817
`.trim());
814818
}
815819

820+
/**
821+
* Show detailed help for profile management
822+
*/
823+
export function showProfilesHelp(): void {
824+
console.log(`
825+
c8ctl profiles - Profile management
826+
827+
Usage: c8ctl <command> profile[s] [args] [flags]
828+
829+
Profile commands:
830+
831+
list profiles
832+
List all profiles (c8ctl + Camunda Modeler profiles).
833+
Modeler profiles are shown with "modeler:" prefix.
834+
835+
add profile <name> [flags]
836+
Add a c8ctl-managed profile.
837+
838+
remove profile <name>
839+
rm profile <name>
840+
Remove a c8ctl-managed profile.
841+
842+
use profile <name>
843+
Set active profile for the current session.
844+
845+
Flags for add profile:
846+
Required for all add profile calls:
847+
(none)
848+
849+
Required for OAuth-secured clusters:
850+
--clientId <id> OAuth client ID
851+
--clientSecret <secret> OAuth client secret
852+
853+
Optional (with defaults):
854+
--baseUrl <url> Cluster base URL (default: http://localhost:8080/v2)
855+
--defaultTenantId <id> Default tenant ID (default at runtime: <default>)
856+
857+
Optional (no c8ctl default):
858+
--audience <audience> OAuth audience
859+
--oAuthUrl <url> OAuth token endpoint
860+
861+
Examples:
862+
c8ctl list profiles
863+
c8ctl add profile local --baseUrl=http://localhost:8080
864+
c8ctl add profile prod --baseUrl=https://camunda.example.com --clientId=xxx --clientSecret=yyy
865+
c8ctl use profile prod
866+
c8ctl use profile "modeler:Local Dev"
867+
c8ctl remove profile local
868+
`.trim());
869+
}
870+
871+
/**
872+
* Show detailed help for plugin management
873+
*/
874+
export function showPluginHelp(): void {
875+
console.log(`
876+
c8ctl plugin - Plugin management
877+
878+
Usage: c8ctl <command> plugin [args] [flags]
879+
880+
Plugin commands:
881+
882+
load plugin <name>
883+
Load a plugin from npm registry.
884+
885+
load plugin --from <url>
886+
Load a plugin from URL source (file://, https://, git://, github:).
887+
888+
unload plugin <name>
889+
Unload and unregister a plugin.
890+
891+
list plugins
892+
List installed plugins with version and sync status.
893+
894+
sync plugins
895+
Rebuild/reinstall plugins from registry.
896+
897+
upgrade plugin <name> [version]
898+
Upgrade plugin source.
899+
- without version: reinstalls registered source as-is
900+
- npm source with version: installs <name>@<version>
901+
- URL/git source with version: installs <source>#<version>
902+
- file:// source with version: not supported, use load plugin --from
903+
904+
downgrade plugin <name> <version>
905+
Downgrade plugin source.
906+
- npm source: installs <name>@<version>
907+
- URL/git source: installs <source>#<version>
908+
- file:// source: not supported, use load plugin --from
909+
910+
init plugin [name]
911+
Create a new plugin scaffold from template.
912+
913+
Examples:
914+
c8ctl load plugin my-plugin
915+
c8ctl load plugin --from file:///path/to/plugin
916+
c8ctl list plugins
917+
c8ctl upgrade plugin my-plugin
918+
c8ctl upgrade plugin my-plugin 1.2.3
919+
c8ctl downgrade plugin my-plugin 1.0.0
920+
c8ctl init plugin my-plugin
921+
`.trim());
922+
}
923+
816924
/**
817925
* Show detailed help for specific commands
818926
*/
@@ -867,6 +975,14 @@ export function showCommandHelp(command: string): void {
867975
case 'correlate':
868976
showCorrelateHelp();
869977
break;
978+
case 'profiles':
979+
case 'profile':
980+
showProfilesHelp();
981+
break;
982+
case 'plugin':
983+
case 'plugins':
984+
showPluginHelp();
985+
break;
870986
default:
871987
console.log(`\nNo detailed help available for: ${command}`);
872988
console.log('Run "c8ctl help" for general usage information.');

0 commit comments

Comments
 (0)