Skip to content

Commit d40cf49

Browse files
committed
docs: add cli-architecture skill for command design reference
1 parent 713530d commit d40cf49

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
name: cli-architecture
3+
description: gh-devlake CLI command architecture, cascade flow, and design principles. Use when restructuring commands, adding new commands, fixing inconsistencies between entry points, or understanding how init/deploy/configure relate to each other.
4+
---
5+
6+
# CLI Architecture — Command Cascade & Flow
7+
8+
## Design Principles
9+
10+
| Principle | Rule |
11+
|---|---|
12+
| **Cascade** | `init` = `deploy` + `configure full`. `configure full` = `connection` + `scope` + `project`. Each level delegates downward. |
13+
| **Self-contained subcommands** | Every subcommand must produce a complete, useful result when run standalone — same prompts, same options, same behavior as when called from a parent orchestrator. |
14+
| **Consistent UX** | Whether you run `gh devlake deploy local` or `gh devlake init → local`, you get the same image-choice prompt with the same options. |
15+
| **Fork-first "custom"** | The "custom/fork" option should default to cloning a fork (with `DevExpGBB/incubator-devlake` as the suggested default). This applies to both local and Azure paths symmetrically. |
16+
| **Quiet mode for orchestrators** | Parent commands suppress child summaries via `--quiet` / internal flags, then print their own consolidated summary at the end. |
17+
| **Flag passthrough** | Orchestrators set child flags before calling `RunE`, never duplicate logic that belongs in the child. |
18+
19+
## Command Tree
20+
21+
```
22+
gh devlake
23+
├── init # Interactive wizard (deploy + configure full)
24+
├── deploy
25+
│ ├── local # Docker Compose on this machine
26+
│ └── azure # Azure Container Apps
27+
├── configure
28+
│ ├── full # connection + scope + project in one session
29+
│ ├── connection # Single plugin connection CRUD
30+
│ │ ├── (default: create)
31+
│ │ ├── list
32+
│ │ ├── update
33+
│ │ ├── delete
34+
│ │ └── test
35+
│ ├── scope # Add scopes to existing connections
36+
│ └── project # Create project + blueprint + trigger sync
37+
├── status # Health check + connection summary
38+
└── cleanup # Tear down (local or Azure)
39+
```
40+
41+
## Ideal Cascade Flow
42+
43+
Check if code architecture reflects this ideal flow. If not suggest modifications to align with these principles.
44+
45+
```mermaid
46+
graph TD
47+
subgraph "Top-level Commands"
48+
INIT["gh devlake init<br/>(interactive wizard)"]
49+
DEPLOY["gh devlake deploy"]
50+
CONFIGURE["gh devlake configure"]
51+
STATUS["gh devlake status"]
52+
CLEANUP["gh devlake cleanup"]
53+
end
54+
55+
subgraph "Deploy Subcommands"
56+
DL["gh devlake deploy local"]
57+
DA["gh devlake deploy azure"]
58+
end
59+
60+
subgraph "Configure Subcommands"
61+
CF["gh devlake configure full"]
62+
CC["gh devlake configure connection"]
63+
CS["gh devlake configure scope"]
64+
CP["gh devlake configure project"]
65+
end
66+
67+
%% init cascades through everything
68+
INIT -->|"1. prompt: local or azure"| DEPLOY
69+
INIT -->|"2. calls"| CF
70+
71+
%% deploy subcommands — each owns its own image-choice logic
72+
DEPLOY --> DL
73+
DEPLOY --> DA
74+
75+
DL -->|"prompt: image source?"| DL_OFF["official: download Apache release"]
76+
DL -->|"prompt: image source?"| DL_FORK["fork: clone repo + build images"]
77+
DL -->|"prompt: image source?"| DL_CUSTOM["custom: user's own compose file"]
78+
DL --> START_CONTAINERS["start containers + wait for healthy"]
79+
80+
DA -->|"prompt: image source?"| DA_OFF["official: Docker Hub images"]
81+
DA -->|"prompt: image source?"| DA_FORK["fork: clone repo + build + push ACR"]
82+
DA --> PROVISION["provision Azure infra + wait"]
83+
84+
DL_FORK -->|"default: DevExpGBB/incubator-devlake"| CLONE["git clone --depth 1"]
85+
86+
%% configure full cascades through sub-steps
87+
CF -->|"1."| CC
88+
CF -->|"2."| CS
89+
CF -->|"3."| CP
90+
91+
%% shared internal functions
92+
CC --> CONN_INTERNAL["resolveToken + createConnection"]
93+
CS --> SCOPE_INTERNAL["resolveRepos + putScopes"]
94+
CP --> PROJECT_INTERNAL["createProject + triggerBlueprint"]
95+
```
96+
97+
## Image Source Options (must be symmetric)
98+
99+
Both `deploy local` and `deploy azure` should offer the same three-way choice when the user hasn't explicitly set flags:
100+
101+
| Option | Local behavior | Azure behavior |
102+
|--------|---------------|----------------|
103+
| **official** (default) | Download `docker-compose.yml` + `env.example` from Apache GitHub release | Use official images from Docker Hub, no ACR needed |
104+
| **fork** | Clone repo (default `DevExpGBB/incubator-devlake`), `docker compose build` from source | Clone repo, build images, push to ACR |
105+
| **custom** | User provides their own `docker-compose.yml` in the target dir | User provides pre-built images or custom Dockerfile |
106+
107+
## Refactoring Checklist
108+
109+
When restructuring commands to match the target architecture:
110+
111+
1. **Move image-choice prompt into `runDeployLocal`** — when `--official` flag isn't explicitly set by the user, prompt with 3 options (official / fork / custom). The fork option clones the repo (reuse `newGitClone` from `deploy_azure.go`), builds images, then proceeds.
112+
113+
2. **Move container startup into `runDeployLocal`** — add a `--start` flag (default `true` in interactive, `false` in CI). `init` no longer calls `startLocalContainers` separately.
114+
115+
3. **Make `runInitLocal` thin** — it sets flags/defaults and calls `runDeployLocal`. The git-repo warning and dedicated-directory prompt can stay in `init`, but everything else delegates down.
116+
117+
4. **Make `init` Phase 2–4 call `configure full`** — instead of duplicating the connection/scope/project flow inline in `init.go`, call `runConfigureFull` (or share the same internal orchestrator).
118+
119+
5. **Align the 3 image-source options** between local and Azure paths so both offer official / fork / custom with consistent labels.
120+
121+
## Key Files
122+
123+
| File | Responsibility |
124+
|------|---------------|
125+
| `cmd/init.go` | Top-level wizard — should be thin, delegates to deploy + configure full |
126+
| `cmd/deploy.go` | Parent command, registers `local` and `azure` subcommands |
127+
| `cmd/deploy_local.go` | `runDeployLocal` — owns image-choice, file download/clone, container startup |
128+
| `cmd/deploy_azure.go` | `runDeployAzure` — owns image-choice, Azure provisioning |
129+
| `cmd/configure.go` | Parent command, registers subcommands |
130+
| `cmd/configure_full.go` | `runConfigureFull` — orchestrates connection + scope + project |
131+
| `cmd/configure_connections.go` | Single-plugin connection CRUD |
132+
| `cmd/configure_scopes.go` | Scope management per plugin |
133+
| `cmd/configure_projects.go` | Project + blueprint creation |
134+
| `cmd/connection_types.go` | `ConnectionDef` registry — single source of truth for plugins |
135+
| `cmd/helpers.go` | Shared utilities (banners, git-repo detection, etc.) |

0 commit comments

Comments
 (0)