Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ jobs:
- name: Run integration tests
run: npm run test:integration
env:
CAMUNDA_VERSION: ${{ matrix.camunda }}

- name: Stop Camunda
if: always()
Expand Down
8 changes: 7 additions & 1 deletion src/commands/completion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ _c8ctl_completions() {
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"
# Global flags
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 --sortBy --asc --desc --limit --name --key --elementId --errorType --value --scopeKey --fullValue --userTask --ut --processDefinition --pd --iname --iid --iassignee --ierrorMessage --itype --ivalue"
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 --sortBy --asc --desc --limit --between --dateField --name --key --elementId --errorType --value --scopeKey --fullValue --userTask --ut --processDefinition --pd --iname --iid --iassignee --ierrorMessage --itype --ivalue"
case \${cword} in
1)
Expand Down Expand Up @@ -237,6 +237,8 @@ _c8ctl() {
'--asc[Sort in ascending order (default)]'
'--desc[Sort in descending order]'
'--limit[Maximum number of items to fetch]:number:'
'--between[Filter by date range (from..to)]:range:'
'--dateField[Date field to filter on with --between]:field:'
'--name[Variable or resource name]:name:'
'--key[Resource key]:key:'
'--elementId[Element ID]:id:'
Expand Down Expand Up @@ -576,6 +578,10 @@ complete -c c8ctl -l desc -d 'Sort in descending order'
complete -c c8 -l desc -d 'Sort in descending order'
complete -c c8ctl -l limit -d 'Maximum number of items to fetch' -r
complete -c c8 -l limit -d 'Maximum number of items to fetch' -r
complete -c c8ctl -l between -d 'Filter by date range (from..to)' -r
complete -c c8 -l between -d 'Filter by date range (from..to)' -r
complete -c c8ctl -l dateField -d 'Date field to filter on with --between' -r
complete -c c8 -l dateField -d 'Date field to filter on with --between' -r
complete -c c8ctl -l name -d 'Variable or resource name' -r
complete -c c8 -l name -d 'Variable or resource name' -r
complete -c c8ctl -l key -d 'Resource key' -r
Expand Down
34 changes: 34 additions & 0 deletions src/commands/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ Flags:
--asc Sort in ascending order (default)
--desc Sort in descending order
--limit <n> Maximum number of items to fetch (default: 1000000)
--between <from>..<to> Filter by date range (use with 'list' or 'search'; short dates YYYY-MM-DD or ISO 8601)
--dateField <field> Date field to filter on with --between (default depends on resource)
Comment on lines +98 to +99
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom guidelines (.github/copilot-instructions.md) require that "cli commands, resources and options are reflected in the help tests, README.md, EXAMPLES.md and other documentation." The --between and --dateField options have been added to help text and shell completion, but are missing from README.md and EXAMPLES.md.

Consider adding examples to these documentation files showing how to use the new date filtering feature. For instance:

  • README.md could include a basic example like c8 list pi --between=2024-01-01..2024-12-31
  • EXAMPLES.md should include comprehensive examples demonstrating various date filtering use cases across different resources

Copilot generated this review using guidance from repository custom instructions.
--version, -v Show version
--help, -h Show help

Expand Down Expand Up @@ -257,6 +259,8 @@ Resources and their available flags:
--id <id> Filter by process definition ID (alias: --bpmnProcessId)
--state <state> Filter by state (ACTIVE, COMPLETED, etc.)
--all List all instances (pagination)
--between <from>..<to> Filter by date range (default field: startDate)
--dateField <field> Date field for --between (startDate, endDate)
--sortBy <column> Sort by column (Key, Process ID, State, Version, Start Date, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -275,6 +279,8 @@ Resources and their available flags:
--state <state> Filter by state (CREATED, COMPLETED, etc.)
--assignee <name> Filter by assignee
--all List all tasks (pagination)
--between <from>..<to> Filter by date range (default field: creationDate)
--dateField <field> Date field for --between (creationDate, completionDate, followUpDate, dueDate)
--sortBy <column> Sort by column (Key, Name, State, Assignee, Created, Process Instance, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -284,6 +290,7 @@ Resources and their available flags:
incidents (inc)
--state <state> Filter by state (ACTIVE, RESOLVED, etc.)
--processInstanceKey <key> Filter by process instance
--between <from>..<to> Filter by date range (field: creationTime)
--sortBy <column> Sort by column (Key, Type, Message, State, Created, Process Instance, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -293,6 +300,8 @@ Resources and their available flags:
jobs
--state <state> Filter by state (ACTIVATABLE, ACTIVATED, etc.)
--type <type> Filter by job type
--between <from>..<to> Filter by date range (default field: creationTime)
--dateField <field> Date field for --between (creationTime, lastUpdateTime)
--sortBy <column> Sort by column (Key, Type, State, Retries, Created, Process Instance, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -308,13 +317,18 @@ Resources and their available flags:

Examples:
c8ctl list pi --state=ACTIVE
c8ctl list pi --between=2024-01-01..2024-12-31
c8ctl list pi --between=2024-01-01T00:00:00Z..2024-06-30T23:59:59Z --dateField=endDate
c8ctl list pi --sortBy=State
c8ctl list pi --sortBy=State --desc
c8ctl list ut --assignee=john.doe
c8ctl list ut --between=2024-01-01..2024-03-31 --dateField=dueDate
c8ctl list ut --sortBy=Assignee
c8ctl list inc --processInstanceKey=123456
c8ctl list inc --between=2024-06-01..2024-06-30
c8ctl list inc --sortBy=Type --desc
c8ctl list jobs --type=email-service
c8ctl list jobs --between=2024-01-01..2024-12-31
c8ctl list jobs --sortBy=Retries --asc
c8ctl list profiles
c8ctl list plugins
Expand Down Expand Up @@ -534,6 +548,8 @@ Resources and their available flags:
--state <state> Filter by state (ACTIVE, COMPLETED, etc.)
--key <key> Filter by key
--parentProcessInstanceKey <key> Filter by parent process instance key
--between <from>..<to> Filter by date range (default field: startDate)
--dateField <field> Date field for --between (startDate, endDate)
--sortBy <column> Sort by column (Key, Process ID, State, Version, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -557,6 +573,8 @@ Resources and their available flags:
--processInstanceKey <key> Filter by process instance key
--processDefinitionKey <key> Filter by process definition key
--elementId <id> Filter by element ID
--between <from>..<to> Filter by date range (default field: creationDate)
--dateField <field> Date field for --between (creationDate, completionDate, followUpDate, dueDate)
--sortBy <column> Sort by column (Key, Name, State, Assignee, Process Instance, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -571,6 +589,7 @@ Resources and their available flags:
--errorType <type> Filter by error type
--errorMessage <msg> Filter by error message
--ierrorMessage <pattern> Case-insensitive --errorMessage filter
--between <from>..<to> Filter by date range (field: creationTime)
--sortBy <column> Sort by column (Key, Type, Message, State, Process Instance, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -582,6 +601,8 @@ Resources and their available flags:
--itype <pattern> Case-insensitive --type filter
--processInstanceKey <key> Filter by process instance key
--processDefinitionKey <key> Filter by process definition key
--between <from>..<to> Filter by date range (default field: creationTime)
--dateField <field> Date field for --between (creationTime, lastUpdateTime)
--sortBy <column> Sort by column (Key, Type, State, Retries, Process Instance, Tenant ID)
--asc Sort in ascending order (default)
--desc Sort in descending order
Expand All @@ -601,6 +622,14 @@ Resources and their available flags:
--limit <n> Maximum number of items to fetch (default: 1000000)
--profile <name> Use specific profile

Date Range Filter:
Use --between <from>..<to> to filter results by a date range.
Dates can be short (YYYY-MM-DD) or full ISO 8601 datetimes.
Short dates: 'from' is expanded to T00:00:00.000Z, 'to' to T23:59:59.999Z.
Use --dateField to specify which date field to filter on (default depends on resource).
Example: --between=2024-01-01..2024-12-31
Example: --between=2024-01-01T00:00:00Z..2024-06-30T23:59:59Z --dateField=endDate

Wildcard Search:
String filters support wildcards: * (any chars) and ? (single char).
Example: --name='*main*' matches all names containing "main".
Expand All @@ -613,15 +642,20 @@ Case-Insensitive Search:
Examples:
c8ctl search pi --state=ACTIVE
c8ctl search pi --bpmnProcessId=order-process
c8ctl search pi --between=2024-01-01..2024-12-31
c8ctl search pi --between=2024-01-01..2024-06-30 --dateField=endDate
c8ctl search pd --name='*main*'
c8ctl search pd --iname='*order*'
c8ctl search pd --sortBy=Name --desc
c8ctl search ut --assignee=john.doe
c8ctl search ut --iassignee=John
c8ctl search ut --between=2024-01-01..2024-03-31 --dateField=dueDate
c8ctl search ut --sortBy=State --asc
c8ctl search inc --state=ACTIVE --processInstanceKey=123456
c8ctl search inc --between=2024-06-01..2024-06-30
c8ctl search jobs --type=email-service
c8ctl search jobs --itype='*SERVICE*'
c8ctl search jobs --between=2024-01-01..2024-12-31
c8ctl search jobs --sortBy=Type --desc
c8ctl search variables --name=orderId
c8ctl search variables --value=12345 --fullValue
Expand Down
12 changes: 12 additions & 0 deletions src/commands/incidents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getLogger } from '../logger.ts';
import { sortTableData, type SortOrder } from '../logger.ts';
import { createClient, fetchAllPages } from '../client.ts';
import { resolveTenantId } from '../config.ts';
import { parseBetween, buildDateFilter } from '../date-filter.ts';

/**
* List incidents
Expand All @@ -17,6 +18,7 @@ export async function listIncidents(options: {
sortBy?: string;
sortOrder?: SortOrder;
limit?: number;
between?: string;
}): Promise<void> {
const logger = getLogger();
const client = createClient(options.profile);
Expand All @@ -37,6 +39,16 @@ export async function listIncidents(options: {
filter.filter.processInstanceKey = options.processInstanceKey;
}

if (options.between) {
const parsed = parseBetween(options.between);
if (parsed) {
filter.filter.creationTime = buildDateFilter(parsed.from, parsed.to);
} else {
logger.error('Invalid --between value. Expected format: <from>..<to> (e.g. 2024-01-01..2024-12-31 or ISO 8601 datetimes)');
process.exit(1);
}
}

const allItems = await fetchAllPages(
(f, opts) => client.searchIncidents(f, opts),
filter,
Expand Down
14 changes: 14 additions & 0 deletions src/commands/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getLogger } from '../logger.ts';
import { sortTableData, type SortOrder } from '../logger.ts';
import { createClient, fetchAllPages } from '../client.ts';
import { resolveTenantId } from '../config.ts';
import { parseBetween, buildDateFilter } from '../date-filter.ts';

/**
* List jobs
Expand All @@ -17,6 +18,8 @@ export async function listJobs(options: {
sortBy?: string;
sortOrder?: SortOrder;
limit?: number;
between?: string;
dateField?: string;
}): Promise<void> {
const logger = getLogger();
const client = createClient(options.profile);
Expand All @@ -37,6 +40,17 @@ export async function listJobs(options: {
filter.filter.type = options.type;
}

if (options.between) {
const parsed = parseBetween(options.between);
if (parsed) {
const field = options.dateField ?? 'creationTime';
filter.filter[field] = buildDateFilter(parsed.from, parsed.to);
} else {
logger.error('Invalid --between value. Expected format: <from>..<to> (e.g. 2024-01-01..2024-12-31 or ISO 8601 datetimes)');
process.exit(1);
}
}

const allItems = await fetchAllPages(
(f, opts) => client.searchJobs(f, opts),
filter,
Expand Down
14 changes: 14 additions & 0 deletions src/commands/process-instances.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getLogger } from '../logger.ts';
import { sortTableData, type SortOrder } from '../logger.ts';
import { createClient, fetchAllPages } from '../client.ts';
import { resolveTenantId } from '../config.ts';
import { parseBetween, buildDateFilter } from '../date-filter.ts';
import type { ProcessInstanceCreationInstructionById } from '@camunda8/orchestration-cluster-api';

/**
Expand All @@ -19,6 +20,8 @@ export async function listProcessInstances(options: {
sortBy?: string;
sortOrder?: SortOrder;
limit?: number;
between?: string;
dateField?: string;
}): Promise<{ items: Array<Record<string, unknown>>; total?: number } | undefined> {
const logger = getLogger();
const client = createClient(options.profile);
Expand All @@ -42,6 +45,17 @@ export async function listProcessInstances(options: {
filter.filter.state = 'ACTIVE';
}

if (options.between) {
const parsed = parseBetween(options.between);
if (parsed) {
const field = options.dateField ?? 'startDate';
filter.filter[field] = buildDateFilter(parsed.from, parsed.to);
} else {
logger.error('Invalid --between value. Expected format: <from>..<to> (e.g. 2024-01-01..2024-12-31 or ISO 8601 datetimes)');
process.exit(1);
}
}

const allItems = await fetchAllPages(
(f, opts) => client.searchProcessInstances(f, opts),
filter,
Expand Down
Loading