Skip to content

Commit 7950ea5

Browse files
authored
Merge branch 'main' into copilot/log-search-criteria-to-user
2 parents 967cbf8 + 7254365 commit 7950ea5

27 files changed

+1588
-474
lines changed

.github/workflows/release.yml

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,8 @@ jobs:
3838
run: npm run test:unit
3939

4040
- name: Start Camunda ${{ matrix.camunda }} with Docker Compose
41-
run: |
42-
cd assets/c8/${{ matrix.camunda }}
43-
DATABASE=elasticsearch docker compose --profile elasticsearch up -d
44-
env:
45-
DATABASE: elasticsearch
41+
working-directory: assets/c8/${{ matrix.camunda }}
42+
run: docker compose up -d
4643

4744
- name: Wait for Camunda to be ready
4845
run: |
@@ -79,19 +76,13 @@ jobs:
7976

8077
- name: Stop Camunda
8178
if: always()
82-
run: |
83-
cd assets/c8/${{ matrix.camunda }}
84-
DATABASE=elasticsearch docker compose --profile elasticsearch down -v
85-
env:
86-
DATABASE: elasticsearch
79+
working-directory: assets/c8/${{ matrix.camunda }}
80+
run: docker compose down -v
8781

8882
- name: Show Camunda logs on failure
8983
if: failure()
90-
run: |
91-
cd assets/c8/${{ matrix.camunda }}
92-
DATABASE=elasticsearch docker compose --profile elasticsearch logs
93-
env:
94-
DATABASE: elasticsearch
84+
working-directory: assets/c8/${{ matrix.camunda }}
85+
run: docker compose logs
9586

9687
release:
9788
name: Release

.github/workflows/test.yml

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,9 @@ jobs:
3535
run: npm run test:unit
3636

3737
- name: Start Camunda ${{ matrix.camunda }} with Docker Compose
38-
run: |
39-
cd assets/c8/${{ matrix.camunda }}
40-
DATABASE=elasticsearch docker compose --profile elasticsearch up -d
41-
env:
42-
DATABASE: elasticsearch
43-
38+
working-directory: assets/c8/${{ matrix.camunda }}
39+
run: docker compose up -d
40+
4441
- name: Wait for Camunda to be ready
4542
run: |
4643
echo "Waiting for Camunda at localhost:8080..."
@@ -76,16 +73,10 @@ jobs:
7673

7774
- name: Stop Camunda
7875
if: always()
79-
run: |
80-
cd assets/c8/${{ matrix.camunda }}
81-
DATABASE=elasticsearch docker compose --profile elasticsearch down -v
82-
env:
83-
DATABASE: elasticsearch
76+
working-directory: assets/c8/${{ matrix.camunda }}
77+
run: docker compose down -v
8478

8579
- name: Show Camunda logs on failure
8680
if: failure()
87-
run: |
88-
cd assets/c8/${{ matrix.camunda }}
89-
DATABASE=elasticsearch docker compose --profile elasticsearch logs
90-
env:
91-
DATABASE: elasticsearch
81+
working-directory: assets/c8/${{ matrix.camunda }}
82+
run: docker compose logs

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ web_modules/
7272
.env.*
7373
!.env.example
7474
!.env.database.*
75+
!assets/**/*/.env
7576

7677
# parcel-bundler cache (https://parceljs.org/)
7778
.cache
@@ -140,3 +141,7 @@ dist
140141
# Vite logs files
141142
vite.config.js.timestamp-*
142143
vite.config.ts.timestamp-*
144+
145+
# Test plugin directories
146+
c8ctl-test-*
147+
test-plugin-temp

EXAMPLES.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ c8 create pi --id=order-process --variables='{"orderId":"12345","amount":100}'
6363
# Create and wait for completion
6464
c8 create pi --id=order-process --awaitCompletion
6565

66+
# Create and wait with custom timeout (30 seconds)
67+
c8 create pi --id=order-process --awaitCompletion --requestTimeout=30000
68+
6669
# Note: --fetchVariables is reserved for future API support
6770
# All variables are currently returned by default
6871
```
@@ -71,6 +74,8 @@ c8 create pi --id=order-process --awaitCompletion
7174

7275
The `await` command is an alias for `create` with `--awaitCompletion`. It uses the Camunda 8 API's built-in server-side waiting to create a process instance and wait for completion.
7376

77+
The `--requestTimeout` option specifies the maximum time in milliseconds to wait for the process instance to complete. By default (or when set to 0), the generic request timeout configured in the cluster is used.
78+
7479
```bash
7580
# Create and wait for completion (shorthand)
7681
c8 await pi --id=order-process
@@ -79,6 +84,9 @@ c8 await process-instance --id=order-process
7984
# With variables
8085
c8 await pi --id=order-process --variables='{"orderId":"12345"}'
8186

87+
# With custom timeout (60 seconds)
88+
c8 await pi --id=order-process --requestTimeout=60000
89+
8290
# Equivalent to:
8391
c8 create pi --id=order-process --awaitCompletion
8492

PLUGIN-HELP.md

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,46 @@ This document describes how c8ctl plugins can provide help text that gets integr
66

77
When users load plugins, their commands automatically appear in the help text. Plugins can optionally provide descriptions for their commands to make the help more informative.
88

9+
## Global Plugin System
10+
11+
c8ctl uses a global plugin system where plugins are installed to a user-specific directory. This means:
12+
13+
- **No local package.json required**: Plugins work from any directory
14+
- **Global installation**: Plugins are installed to OS-specific directories:
15+
- **Linux**: `~/.config/c8ctl/plugins/node_modules`
16+
- **macOS**: `~/Library/Application Support/c8ctl/plugins/node_modules`
17+
- **Windows**: `%APPDATA%\c8ctl\plugins\node_modules`
18+
- **Plugin registry**: Tracked in `plugins.json` in the same parent directory
19+
- **Persistent across projects**: Once loaded, plugins are available everywhere
20+
- **Centralized management**: All plugins are managed through the c8ctl plugin registry
21+
- **Cannot override built-in commands**: Plugin commands are executed only if no built-in command matches
22+
23+
> **Note:** You can override the default data directory by setting the `C8CTL_DATA_DIR` environment variable.
24+
25+
## Plugin Registry
26+
27+
The plugin registry (`plugins.json`) maintains a list of all installed plugins with metadata:
28+
29+
```json
30+
{
31+
"plugins": [
32+
{
33+
"name": "my-plugin",
34+
"source": "my-plugin@1.0.0",
35+
"installedAt": "2024-01-15T10:30:00.000Z"
36+
}
37+
]
38+
}
39+
```
40+
41+
Registry locations by OS:
42+
- **Linux**: `~/.config/c8ctl/plugins.json`
43+
- **macOS**: `~/Library/Application Support/c8ctl/plugins.json`
44+
- **Windows**: `%APPDATA%\c8ctl\plugins.json`
45+
946
## How It Works
1047

11-
1. **Automatic Discovery**: When `c8ctl help` is invoked, it scans all loaded plugins
48+
1. **Automatic Discovery**: When `c8ctl help` is invoked, it scans all loaded plugins from the global plugins directory
1249
2. **Plugin Section**: If plugins are loaded, a "Plugin Commands" section appears at the bottom of the help text
1350
3. **Command Listing**: Each plugin command is listed with its optional description
1451

@@ -83,6 +120,7 @@ export const commands = {
83120
## Help Output Example
84121

85122
Without plugins loaded:
123+
86124
```
87125
c8ctl - Camunda 8 CLI v2.0.0
88126
@@ -95,6 +133,7 @@ Commands:
95133
```
96134

97135
With plugins loaded:
136+
98137
```
99138
c8ctl - Camunda 8 CLI v2.0.0
100139
@@ -121,6 +160,7 @@ The plugin loader ([src/plugin-loader.ts](src/plugin-loader.ts)) provides:
121160
- `getPluginCommandNames()`: Returns array of command names
122161
- `getPluginCommandsInfo()`: Returns detailed info including descriptions
123162
- Automatic metadata extraction during plugin loading
163+
- Scans the [global plugins directory](#global-plugin-system) for installed plugins
124164

125165
### Help Command
126166

@@ -150,25 +190,59 @@ interface PluginMetadata {
150190
2. **Keep descriptions concise**: Aim for one line (< 60 characters)
151191
3. **Use imperative verbs**: Start with action words (Analyze, Deploy, Check, etc.)
152192
4. **Match command names**: Ensure metadata command names match exported functions
153-
5. **TypeScript plugins**: The `c8ctl-plugin.js` entry point must be JavaScript. Node.js doesn't support type stripping in `node_modules`. Transpile TypeScript to JavaScript before publishing your plugin.
193+
5. **Use unique command names**: Plugin commands cannot override built-in commands (see [Command Precedence](#command-precedence))
194+
6. **TypeScript plugins**: The `c8ctl-plugin.js` entry point must be JavaScript. Node.js doesn't support type stripping in `node_modules`. Transpile TypeScript to JavaScript before publishing your plugin.
195+
196+
## Command Precedence
197+
198+
**Important:** Plugin commands cannot override built-in c8ctl commands. Built-in commands always take precedence.
199+
200+
When c8ctl processes a command, it follows this order:
201+
202+
1. Check for built-in commands (list, get, create, deploy, etc.)
203+
2. If no built-in command matches, check plugin commands
204+
3. Execute the matched command
205+
206+
### Example
207+
208+
If a plugin exports a command named `list`:
209+
210+
```javascript
211+
export const commands = {
212+
'list': async (args) => {
213+
console.log('This will NEVER execute');
214+
}
215+
};
216+
```
217+
218+
When users run `c8ctl list profiles`, the built-in `list` command will execute, not the plugin version.
219+
220+
### Recommendation
221+
222+
Choose descriptive, unique names for your plugin commands that don't conflict with built-in commands. For example:
223+
-`analyze-process`, `export-data`, `sync-resources`
224+
-`list`, `get`, `create`, `deploy`
154225

155226
## Testing
156227

157228
See [tests/unit/plugin-loader.test.ts](tests/unit/plugin-loader.test.ts) for unit tests that verify:
229+
158230
- `getPluginCommandsInfo()` returns correct structure
159231
- Help text includes plugin commands
160232
- Metadata is properly parsed
161233

162234
## Example Plugin Development Flow
163235

164236
1. Create plugin with commands:
237+
165238
```typescript
166239
export const commands = {
167240
myCommand: async () => { /* ... */ }
168241
};
169242
```
170243

171-
2. Add metadata for help:
244+
1. Add metadata for help:
245+
172246
```typescript
173247
export const metadata = {
174248
commands: {
@@ -179,12 +253,14 @@ export const metadata = {
179253
};
180254
```
181255

182-
3. Load plugin:
256+
1. Load plugin:
257+
183258
```bash
184259
c8ctl load plugin my-plugin
185260
```
186261

187-
4. Verify help includes your command:
262+
1. Verify help includes your command:
263+
188264
```bash
189265
c8ctl help
190266
```

README.md

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# c8ctl - Camunda 8 CLI
1+
# Cocktail (c8ctl) - Camunda 8 CLI
22

3-
A minimal-dependency CLI for Camunda 8 operations built on top of `@camunda8/orchestration-cluster-api`.
3+
c8ctl (_pronounced: "cocktail"_) — a minimal-dependency CLI for Camunda 8 operations built on top of [`@camunda8/orchestration-cluster-api`](https://www.npmjs.com/package/@camunda8/orchestration-cluster-api).
44

55
## Features
66

@@ -109,10 +109,16 @@ c8ctl create process-instance --id=myProcess
109109
# Create process instance and wait for completion
110110
c8ctl create pi --id=myProcess --awaitCompletion
111111

112+
# Create process instance with custom timeout (30 seconds)
113+
c8ctl create pi --id=myProcess --awaitCompletion --requestTimeout=30000
114+
112115
# Await process instance completion (alias for create with --awaitCompletion)
113116
c8ctl await pi --id=myProcess
114117
c8ctl await process-instance --id=myProcess
115118

119+
# Await with custom timeout
120+
c8ctl await pi --id=myProcess --requestTimeout=60000
121+
116122
# Cancel process instance
117123
c8ctl cancel pi 123456
118124

@@ -306,9 +312,24 @@ Debug output is written to stderr with timestamps and won't interfere with norma
306312

307313
### Plugin Management
308314

309-
c8ctl supports a plugin system that allows extending the CLI with custom commands via npm packages. Plugins are tracked in a registry file (`~/.config/c8ctl/plugins.json` on Linux, similar locations on other platforms) for persistence across npm operations.
315+
c8ctl supports a global plugin system that allows extending the CLI with custom commands via npm packages. Plugins are installed globally to a user-specific directory and tracked in a registry file.
316+
317+
**Plugin Storage Locations:**
318+
319+
The plugin system uses OS-specific directories:
320+
321+
| OS | Plugins Directory | Registry File |
322+
|----|-------------------|---------------|
323+
| **Linux** | `~/.config/c8ctl/plugins/node_modules` | `~/.config/c8ctl/plugins.json` |
324+
| **macOS** | `~/Library/Application Support/c8ctl/plugins/node_modules` | `~/Library/Application Support/c8ctl/plugins.json` |
325+
| **Windows** | `%APPDATA%\c8ctl\plugins\node_modules` | `%APPDATA%\c8ctl\plugins.json` |
326+
327+
> **Note:** You can override the data directory with the `C8CTL_DATA_DIR` environment variable.
310328
311329
```bash
330+
# Create a new plugin from template
331+
c8ctl init plugin my-plugin
332+
312333
# Load a plugin from npm registry
313334
c8ctl load plugin <package-name>
314335

@@ -318,7 +339,14 @@ c8ctl load plugin --from file:///path/to/plugin
318339
c8ctl load plugin --from https://github.com/user/repo
319340
c8ctl load plugin --from git://github.com/user/repo.git
320341

321-
# Unload a plugin (wraps npm uninstall)
342+
# Upgrade a plugin to latest or specific version
343+
c8ctl upgrade plugin <package-name>
344+
c8ctl upgrade plugin <package-name> 1.2.3
345+
346+
# Downgrade a plugin to a specific version
347+
c8ctl downgrade plugin <package-name> 1.0.0
348+
349+
# Unload a plugin
322350
c8ctl unload plugin <package-name>
323351

324352
# List installed plugins (shows sync status)
@@ -333,21 +361,32 @@ c8ctl sync plugins
333361
c8ctl help
334362
```
335363

336-
**Plugin Registry:**
337-
- Plugins are tracked independently of `package.json` in a registry file
338-
- The registry serves as the source of truth (local precedence)
364+
**Global Plugin System:**
365+
- Plugins are installed to a global directory (OS-specific, see table above)
366+
- Plugin registry file (`plugins.json`) tracks all installed plugins
367+
- No local `package.json` is required in your working directory
368+
- Plugins are available globally from any directory
369+
- The registry serves as the source of truth for installed plugins
370+
- Default plugins are bundled with c8ctl and loaded automatically
371+
- **Plugin commands cannot override built-in commands** - built-in commands always take precedence
339372
- `c8ctl list plugins` shows sync status:
340373
- `✓ Installed` - Plugin is in registry and installed
341-
- `⚠ Not installed` - Plugin is in registry but not in node_modules (run `sync`)
342-
- `⚠ Not in registry` - Plugin is in package.json but not tracked in registry
374+
- `⚠ Not installed` - Plugin is in registry but not in global directory (run `sync`)
375+
- `⚠ Not in registry` - Plugin is installed but not tracked in registry
343376
- `c8ctl sync plugins` synchronizes plugins from the registry, rebuilding or reinstalling as needed
344377

378+
**Plugin Development:**
379+
- Use `c8ctl init plugin <name>` to scaffold a new plugin with TypeScript template
380+
- Generated scaffold includes all necessary files and build configuration
381+
- Plugins have access to the c8ctl runtime via `globalThis.c8ctl`
382+
- See the bundled `hello-world` plugin in `default-plugins/` for a complete example
383+
345384
**Plugin Requirements:**
346385
- Plugin packages must be regular Node.js modules
347386
- They must include a `c8ctl-plugin.js` or `c8ctl-plugin.ts` file in the root directory
348387
- The plugin file must export a `commands` object
349388
- Optionally export a `metadata` object to provide help text
350-
- Plugins are installed in `node_modules` like regular npm packages
389+
- Plugins are installed globally and work from any directory
351390
- The runtime object `c8ctl` provides environment information to plugins
352391
- **Important**: `c8ctl-plugin.js` must be JavaScript. Node.js doesn't support type stripping in `node_modules`. If writing in TypeScript, transpile to JS before publishing.
353392

assets/c8/8.8/.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Default configuration for docker compose
2+
# Activates the elasticsearch profile (vs opensearch)
3+
COMPOSE_PROFILES=elasticsearch

assets/c8/8.8/docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ services:
128128
- 9600:9600
129129
- 8080:8080
130130
depends_on:
131-
- ${DATABASE}
131+
- elasticsearch
132132
networks:
133133
- zeebe_network
134134
env_file:
135-
- envs/.env.database.${DATABASE}
135+
- envs/.env.database.elasticsearch
136136

assets/c8/8.9/.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Default configuration for docker compose
2+
CAMUNDA_VERSION=8.9.0-alpha4

0 commit comments

Comments
 (0)