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
16 changes: 1 addition & 15 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,21 +482,6 @@ capy org [options]

JSON support: no

### `capy org projects`

List projects in the active organization; --deleted also lists deleted ones (owners only)

```
capy org projects [options]
```

| Option | Description | Default |
|---|---|---|
| `--deleted` | also list deleted projects, marked as deleted, with the date | |
| `--json` | emit machine-readable JSON instead of the human UI | |

JSON support: yes (`--json`)

## `capy project`

Create, delete or restore a project in the active organization
Expand Down Expand Up @@ -617,6 +602,7 @@ capy projects [options]

| Option | Description | Default |
|---|---|---|
| `--deleted` | also list deleted projects, marked as deleted, with the date (owners only) | |
| `--json` | emit machine-readable JSON instead of the human UI | |

JSON support: yes (`--json`)
Expand Down
15 changes: 2 additions & 13 deletions src/index-dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -787,18 +787,6 @@ projectCmd
await restoreProjectCommand(ref, { yes, nonTty, json, dryRun, apiUrl: process.env.CAPY_API_URL, devMode: true });
});

orgCmd
.command('projects')
.description('List projects in the active organization; --deleted also lists deleted ones (owners only)') // COPY-FLAG
.option('--deleted', 'also list deleted projects, marked as deleted, with the date') // COPY-FLAG
.option('--json', 'emit machine-readable JSON instead of the human UI')
.action(async (_options: any, command: any) => {
const { ProjectsCommand } = await import('./commands/projectsCommand');
const cmd = new ProjectsCommand(process.env.CAPY_API_URL, true);
const merged = command.optsWithGlobals();
await cmd.execute({ json: merged.json, deleted: merged.deleted === true });
});

program
.command('info')
.description('Show current session info')
Expand Down Expand Up @@ -832,11 +820,12 @@ program
program
.command('projects')
.description('List projects in the active organization and their branches')
.option('--deleted', 'also list deleted projects, marked as deleted, with the date (owners only)') // COPY-FLAG
.option('--json', 'emit machine-readable JSON instead of the human UI')
.action(async (options) => {
const { ProjectsCommand } = await import('./commands/projectsCommand');
const cmd = new ProjectsCommand(process.env.CAPY_API_URL, true);
await cmd.execute({ json: options.json });
await cmd.execute({ json: options.json, deleted: options.deleted === true });
});

const secretsCmd = program
Expand Down
16 changes: 2 additions & 14 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -826,19 +826,6 @@ projectCmd
await restoreProjectCommand(ref, { yes, nonTty, json, dryRun });
});

orgCmd
.command('projects')
.description('List projects in the active organization; --deleted also lists deleted ones (owners only)') // COPY-FLAG
.option('--deleted', 'also list deleted projects, marked as deleted, with the date') // COPY-FLAG
.option('--json', 'emit machine-readable JSON instead of the human UI')
.action(async (_options: any, command: any) => {
assertNotLocalOnly('org projects');
const { ProjectsCommand } = await import('./commands/projectsCommand');
const cmd = new ProjectsCommand();
const merged = command.optsWithGlobals();
await cmd.execute({ json: merged.json, deleted: merged.deleted === true });
});

program
.command('info')
.description('Show current session info')
Expand Down Expand Up @@ -875,12 +862,13 @@ program
program
.command('projects')
.description('List projects in the active organization and their branches')
.option('--deleted', 'also list deleted projects, marked as deleted, with the date (owners only)') // COPY-FLAG
.option('--json', 'emit machine-readable JSON instead of the human UI')
.action(async (options) => {
assertNotLocalOnly('projects');
const { ProjectsCommand } = await import('./commands/projectsCommand');
const cmd = new ProjectsCommand();
await cmd.execute({ json: options.json });
await cmd.execute({ json: options.json, deleted: options.deleted === true });
});

const secretsCmd = program
Expand Down
16 changes: 13 additions & 3 deletions tests/commands/projectDeletedCli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async function deletedFolder(h: Harness): Promise<void> {
h.markProjectDeleted();
}

describe('project delete / project restore / org projects: flags the program also defines', () => {
describe('project delete / project restore / projects: flags the program also defines', () => {
test('--force arrives: the DELETE body is {"force":true}; without it there is no body', async () => {
await withHarness(async (h) => {
const forced = await h.run(['project', 'delete', PROJECT_ID, '--force', '--yes', '--json']);
Expand Down Expand Up @@ -67,14 +67,24 @@ describe('project delete / project restore / org projects: flags the program als
});
});

test('org projects --deleted asks the service for the deleted ones too', async () => {
test('projects --deleted asks the service for the deleted ones too', async () => {
await withHarness(async (h) => {
h.setBranches(PROJECT_ID, [{ id: 'br_1', name: 'production', is_protected: false }]);
const out = await h.run(['org', 'projects', '--deleted', '--json']);
const out = await h.run(['projects', '--deleted', '--json']);
expect(out.code).toBe(0);
expect(h.requests().some((r) => r.method === 'GET' && r.path === '/projects?include_deleted=1')).toBe(true);
});
});

test('projects without --deleted sends the plain listing request', async () => {
await withHarness(async (h) => {
h.setBranches(PROJECT_ID, [{ id: 'br_1', name: 'production', is_protected: false }]);
const out = await h.run(['projects', '--json']);
expect(out.code).toBe(0);
const lists = h.requests().filter((r) => r.method === 'GET' && (r.path === '/projects' || r.path.startsWith('/projects?')));
expect(lists.map((r) => r.path)).toEqual(['/projects']);
});
});
});

describe('lifecycleOptsFrom: --non-tty and --force, wherever the outer command took them', () => {
Expand Down
2 changes: 1 addition & 1 deletion tests/commands/projectsDeleted.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, it, expect, spyOn, mock, afterAll, beforeEach } from 'bun:test';

/**
* `capy org projects --deleted` (CAP-729): the listing includes deleted
* `capy projects --deleted`: the listing includes deleted
* projects, each marked deleted with its date; a plain listing is unchanged.
*
* Org resolution and the spinner are replaced; `projectsCommand` and the
Expand Down
Loading