@groundfloorcloud/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -0
- package/dist/index.js +1345 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# `@groundfloorcloud/cli` (`gf`)
|
|
2
|
+
|
|
3
|
+
A small, Vercel/`gh`-style CLI to log a developer into the Groundfloor
|
|
4
|
+
Control Plane and reuse that session while building locally (in Cursor,
|
|
5
|
+
scripts, or any app). It works like `vercel login`: run `gf login` once, the
|
|
6
|
+
browser opens, you sign in, and the session is cached and auto-refreshed.
|
|
7
|
+
|
|
8
|
+
The Control Plane never issues its own login tokens — it validates identity
|
|
9
|
+
provider Bearer JWTs. So `gf` obtains tokens from Groundfloor's managed IdP
|
|
10
|
+
(OAuth 2.0 Authorization Code + PKCE) and hands you a valid
|
|
11
|
+
`Authorization: Bearer ...` token for CP and Coderunner APIs. Your Portal user
|
|
12
|
+
is created just-in-time on the first call.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm i -g @groundfloorcloud/cli
|
|
18
|
+
gf login
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or without a global install:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @groundfloorcloud/cli login
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### From this monorepo
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install
|
|
31
|
+
npm run build --workspace=@groundfloorcloud/cli
|
|
32
|
+
npm link --workspace=@groundfloorcloud/cli # then: gf --help
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick start
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
gf login # browser sign-in, caches ~/.groundfloor/auth.json
|
|
39
|
+
gf whoami # shows identity and verifies CP accepts the token
|
|
40
|
+
gf workspaces # list your workspaces
|
|
41
|
+
gf workspaces use <uuid> # set a default workspace
|
|
42
|
+
gf coderunner ls # list coderunners in the default workspace
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Use the session from any local app or shell:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
eval "$(gf env)" # exports GROUNDFLOOR_TOKEN, CONTROLPLANE_URL, ...
|
|
49
|
+
curl -H "Authorization: Bearer $(gf token)" \
|
|
50
|
+
"$CONTROLPLANE_URL/v1/workspaces" | jq .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
In Cursor, run `gf login` once, then `gf token` / `gf env` whenever you (or an
|
|
54
|
+
agent) need a fresh token to call CP APIs during development.
|
|
55
|
+
|
|
56
|
+
## Deploying a coderunner (D-061)
|
|
57
|
+
|
|
58
|
+
**Coderunner is the deploy path.** Do not create an App to run functions/jobs/services —
|
|
59
|
+
`POST …/apps` with `app_kind=coderunner` is rejected. Use `gf deploy`, Control Plane
|
|
60
|
+
`/coderunners` APIs, or the `@groundfloor/coderunner-mcp` MCP server.
|
|
61
|
+
|
|
62
|
+
`gf deploy` packages your code and runs the full lifecycle: create the
|
|
63
|
+
coderunner if it does not exist, upload a new version, wait for the build,
|
|
64
|
+
deploy, **poll deployment until Completed**, and print IDs/URL.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Deploy the current folder (zips the working tree, honoring .gitignore)
|
|
68
|
+
gf deploy
|
|
69
|
+
|
|
70
|
+
# Deploy a remote git/bitbucket repo (upload description includes git_sha=…)
|
|
71
|
+
gf deploy --git https://github.com/me/my-fn.git --ref main
|
|
72
|
+
|
|
73
|
+
# Override target + resources + env
|
|
74
|
+
gf deploy --name my-fn --runtime python --cpu 250m --memory 256Mi \
|
|
75
|
+
-e API_KEY=secret -e STAGE=dev
|
|
76
|
+
|
|
77
|
+
# Bind a newly created coderunner as a helper of an App (optional)
|
|
78
|
+
gf deploy --app-id <app-uuid>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Server push-to-deploy:** connect a repo on the coderunner **Git source** card
|
|
82
|
+
(or `PUT …/coderunners/{id}/git-source`). Point GitHub/Gitea at
|
|
83
|
+
`POST /v1/webhooks/git/{source_id}` with the returned webhook secret. Private
|
|
84
|
+
repos use a workspace Secret named in `secret_key`. App creation is not required.
|
|
85
|
+
|
|
86
|
+
How the target is chosen:
|
|
87
|
+
|
|
88
|
+
- `--coderunner <id>` deploys into that exact coderunner.
|
|
89
|
+
- Otherwise the name comes from `--name`, then `groundfloor.json`, then the
|
|
90
|
+
folder/repo name; its slug is matched against existing coderunners. A match is
|
|
91
|
+
reused; otherwise a new coderunner is created (optionally with `--app-id`).
|
|
92
|
+
|
|
93
|
+
Runtime is auto-detected when not given (`package.json` -> node,
|
|
94
|
+
`requirements.txt`/`pyproject.toml` -> python), defaulting to python.
|
|
95
|
+
|
|
96
|
+
### Optional `groundfloor.json`
|
|
97
|
+
|
|
98
|
+
Drop a `groundfloor.json` in your project root to set defaults (CLI flags still
|
|
99
|
+
win):
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"name": "my-fn",
|
|
104
|
+
"runtime": "python",
|
|
105
|
+
"workloadType": "function",
|
|
106
|
+
"cpu": "250m",
|
|
107
|
+
"memory": "256Mi",
|
|
108
|
+
"env": { "STAGE": "dev" }
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Useful flags
|
|
113
|
+
|
|
114
|
+
| Flag | Description |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `-w, --workspace <id>` | Workspace override (else the default from `gf workspaces use`). |
|
|
117
|
+
| `-p, --path <dir>` | Local directory to package (default: cwd). |
|
|
118
|
+
| `--git <url>` / `--ref <ref>` | Clone and deploy a remote repo at a branch/tag/commit. |
|
|
119
|
+
| `--subdir <dir>` | Package a subdirectory of the source. |
|
|
120
|
+
| `--runtime <r>` | `python` \| `node` \| `dotnet-script`. |
|
|
121
|
+
| `--workload-type <t>` | `function` \| `service` \| `job` \| `schedule`. |
|
|
122
|
+
| `--cpu` / `--memory` | Resource requests, e.g. `250m` / `256Mi`. |
|
|
123
|
+
| `-e, --env KEY=VALUE` | Deployment env var (repeatable). |
|
|
124
|
+
| `-m, --message <text>` | Version description. |
|
|
125
|
+
| `--skip-deploy` | Upload a new version but do not deploy it. |
|
|
126
|
+
|
|
127
|
+
## Commands
|
|
128
|
+
|
|
129
|
+
| Command | Description |
|
|
130
|
+
|---------|-------------|
|
|
131
|
+
| `gf login [--device]` | Browser PKCE login (or device-code flow with `--device`). |
|
|
132
|
+
| `gf logout` | Clear the cached session. |
|
|
133
|
+
| `gf whoami` | Show identity and verify the CP session end-to-end. |
|
|
134
|
+
| `gf token` | Print a fresh (auto-refreshed) access token to stdout. |
|
|
135
|
+
| `gf env` | Print `export ...` lines for `eval "$(gf env)"`. |
|
|
136
|
+
| `gf workspaces` (`ws`) | List workspaces; `gf workspaces use <id>` sets the default. |
|
|
137
|
+
| `gf coderunner ls` (`cr ls`) | List coderunners in the default (or `--workspace`) workspace. |
|
|
138
|
+
| `gf coderunner status -c <id\|slug>` | Status + current deployment JSON. |
|
|
139
|
+
| `gf coderunner run -c <id\|slug> [--payload '{}']` | Smoke invoke a deployed function/job. |
|
|
140
|
+
| `gf deploy` | Package code (local folder or `--git` repo) and deploy it as a coderunner. |
|
|
141
|
+
|
|
142
|
+
### MCP (agents)
|
|
143
|
+
|
|
144
|
+
See [`packages/coderunner-mcp/README.md`](../coderunner-mcp/README.md) and
|
|
145
|
+
[`docs/plans/apps-and-coderunner.md`](../../docs/plans/apps-and-coderunner.md) Phase 1.
|
|
146
|
+
|
|
147
|
+
## Configuration
|
|
148
|
+
|
|
149
|
+
Settings resolve with precedence: command flags > environment > config file >
|
|
150
|
+
built-in dev defaults.
|
|
151
|
+
|
|
152
|
+
| Setting | Flag | Env | Default |
|
|
153
|
+
|---------|------|-----|---------|
|
|
154
|
+
| IdP issuer | `--issuer` | `GROUNDFLOOR_ISSUER` | `https://auth.dev.groundfloor.cloud/realms/groundfloor_dev` |
|
|
155
|
+
| OIDC client id | `--client-id` | `GROUNDFLOOR_CLIENT_ID` | `groundfloor-cli` |
|
|
156
|
+
| Control Plane URL | `--api-url` | `GROUNDFLOOR_API_URL` | `http://localhost:8088` |
|
|
157
|
+
| Default workspace | (via `gf workspaces use`) | `GROUNDFLOOR_WORKSPACE_ID` | (none) |
|
|
158
|
+
|
|
159
|
+
State is stored under `~/.groundfloor/`:
|
|
160
|
+
|
|
161
|
+
- `auth.json` — cached tokens (chmod `600`).
|
|
162
|
+
- `config.json` — non-secret defaults (issuer, client id, api url, workspace).
|
|
163
|
+
|
|
164
|
+
`gf login --issuer ... --client-id ... --api-url ...` persists those values so
|
|
165
|
+
later commands match the login.
|
|
166
|
+
|
|
167
|
+
## Identity provider setup (one-time)
|
|
168
|
+
|
|
169
|
+
`gf` needs a **public** OIDC client (default id `groundfloor-cli`) with:
|
|
170
|
+
|
|
171
|
+
- Standard Flow enabled, PKCE method `S256`.
|
|
172
|
+
- Valid redirect URIs covering the loopback callback. The CLI redirects to
|
|
173
|
+
`http://127.0.0.1:<port>/callback`, so configure **both**:
|
|
174
|
+
- `http://127.0.0.1/*`
|
|
175
|
+
- `http://localhost/*`
|
|
176
|
+
- Optionally, OAuth 2.0 Device Authorization Grant enabled for `gf login --device`.
|
|
177
|
+
|
|
178
|
+
Then add the client id to the Control Plane `KEYCLOAK_AUDIENCE`
|
|
179
|
+
(see `.env.example`) so its tokens verify. The CLI user still needs workspace
|
|
180
|
+
membership in the Portal for workspace-scoped routes.
|
|
181
|
+
|
|
182
|
+
### Redirect URI mismatch ("Invalid parameter: redirect_uri")
|
|
183
|
+
|
|
184
|
+
This means the client's Valid Redirect URIs do not match the loopback URL the
|
|
185
|
+
CLI sends. Options:
|
|
186
|
+
|
|
187
|
+
- Ensure the client lists `http://127.0.0.1/*` (the CLI defaults to `127.0.0.1`).
|
|
188
|
+
- If your IdP only matches `localhost`, run `gf login --redirect-host localhost`.
|
|
189
|
+
- If wildcard/port matching is restrictive, pin an exact URI: register
|
|
190
|
+
`http://127.0.0.1:8976/callback` on the client and run
|
|
191
|
+
`gf login --redirect-port 8976`.
|
|
192
|
+
|
|
193
|
+
## Scope
|
|
194
|
+
|
|
195
|
+
- Phase 1: authenticated developer session (`gf login` + token reuse).
|
|
196
|
+
- Phase 2: `gf deploy` for local folders and remote git/bitbucket repos. The CLI
|
|
197
|
+
packages the code into a ZIP and drives the Control Plane create -> upload ->
|
|
198
|
+
build -> deploy lifecycle (upstream Code Runner is ZIP-based).
|
|
199
|
+
|
|
200
|
+
Server-side push-to-deploy (Control Plane pulling from git via webhooks) is a
|
|
201
|
+
possible future enhancement and is not part of this CLI.
|