Skip to content

Commit e029fdf

Browse files
pavkamCopilot
andauthored
feat: Bucket CLI 2.0 (#448)
- Added `--api-key` option for non-interactive authentication, - Added a new `--check-only` flag for types generation, - Added a version check at startup, - (BREAKING) Removed unused and deprecated functionality, - Enhanced documentation for using the CLI in CI/CD pipelines. --------- Co-authored-by: Copilot <[email protected]>
1 parent ccc648d commit e029fdf

27 files changed

+573
-904
lines changed

.vscode/settings.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,10 @@
3939
"**/*.lock": true
4040
},
4141
"typescript.tsdk": "node_modules/typescript/lib",
42-
"cSpell.words": ["bucketco", "openfeature"]
42+
"cSpell.words": [
43+
"booleanish",
44+
"bucketco",
45+
"openfeature",
46+
"PKCE"
47+
]
4348
}

packages/cli/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ These options can be used with any command:
241241
- `--debug`: Enable debug mode for verbose output.
242242
- `--base-url <url>`: Set the base URL for Bucket API.
243243
- `--api-url <url>`: Set the API URL directly (overrides base URL).
244+
- `--api-key <key>`: Bucket API key for non-interactive authentication.
244245
- `--help`: Display help information for a command.
245246

246247
## AI-Assisted Development
@@ -297,6 +298,50 @@ The command will guide you through:
297298

298299
_**Note: The setup uses [mcp-remote](https://github.com/geelen/mcp-remote) as a compatibility layer allowing the remote hosted Bucket MCP server to work with all editors/clients that support MCP STDIO servers. If your editor/client supports HTTP Streaming with OAuth you can connect to the Bucket MCP server directly.**_
299300

301+
## Using in CI/CD Pipelines (Beta)
302+
303+
The Bucket CLI is designed to work seamlessly in CI/CD pipelines. For automated environments where interactive login is not possible, use the `--api-key` option.
304+
305+
```bash
306+
# Generate types in CI/CD
307+
npx bucket apps list --api-key $BUCKET_API_KEY
308+
```
309+
310+
**Important restrictions:**
311+
312+
- When using `--api-key`, the `login` and `logout` commands are disabled.
313+
- API keys bypass all interactive authentication flows.
314+
- Only _read-only_ access to Bucket API is granted at the moment.
315+
- API keys are bound to one app only. Commands such as `apps list` will only return the bound app.
316+
- Store API keys securely using your CI/CD platform's secret management.
317+
318+
### Primary Use Case: Type Validation in CI/CD
319+
320+
Use the `--check-only` flag with `features types` to validate that generated types are up-to-date:
321+
322+
```bash
323+
# Check if types are current (exits with non-zero code if not)
324+
npx bucket features types --check-only --api-key $BUCKET_API_KEY --app-id ap123456789
325+
```
326+
327+
This is particularly useful for:
328+
329+
- **Pull Request validation**: Ensure developers have regenerated types after feature changes.
330+
- **Build verification**: Confirm types are synchronized before deployment.
331+
- **Automated quality checks**: Catch type drift in your CI pipeline.
332+
333+
Example CI workflow:
334+
335+
```yaml
336+
# GitHub Actions example
337+
- name: Validate Bucket types
338+
run: npx bucket features types --check-only --api-key ${{ secrets.BUCKET_API_KEY }}
339+
340+
- name: Generate types if validation fails
341+
if: failure()
342+
run: npx bucket features types --api-key ${{ secrets.BUCKET_API_KEY }}
343+
```
344+
300345
## Development
301346
302347
```bash

packages/cli/commands/apps.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import { handleError } from "../utils/errors.js";
99
export const listAppsAction = async () => {
1010
const baseUrl = configStore.getConfig("baseUrl");
1111
const spinner = ora(`Loading apps from ${chalk.cyan(baseUrl)}...`).start();
12+
1213
try {
13-
const apps = await listApps();
14+
const apps = listApps();
1415
spinner.succeed(`Loaded apps from ${chalk.cyan(baseUrl)}.`);
1516
console.table(apps.map(({ name, id, demo }) => ({ name, id, demo })));
1617
} catch (error) {
1718
spinner.fail("Failed to list apps.");
18-
void handleError(error, "Apps List");
19+
handleError(error, "Apps List");
1920
}
2021
};
2122

packages/cli/commands/auth.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,57 @@ import { handleError } from "../utils/errors.js";
99

1010
export const loginAction = async () => {
1111
const { baseUrl, apiUrl } = configStore.getConfig();
12+
const { token, isApiKey } = authStore.getToken(baseUrl);
13+
14+
if (isApiKey) {
15+
handleError(
16+
"Login is not allowed when an API token was supplied.",
17+
"Login",
18+
);
19+
}
20+
21+
if (token) {
22+
console.log("Already logged in, nothing to do.");
23+
return;
24+
}
1225

1326
try {
14-
await waitForAccessToken(baseUrl, apiUrl);
27+
const { accessToken } = await waitForAccessToken(baseUrl, apiUrl);
28+
await authStore.setToken(baseUrl, accessToken);
29+
1530
console.log(`Logged in to ${chalk.cyan(baseUrl)} successfully!`);
1631
} catch (error) {
1732
console.error("Login failed.");
18-
void handleError(error, "Login");
33+
handleError(error, "Login");
1934
}
2035
};
2136

2237
export const logoutAction = async () => {
2338
const baseUrl = configStore.getConfig("baseUrl");
39+
40+
const { token, isApiKey } = authStore.getToken(baseUrl);
41+
42+
if (isApiKey) {
43+
handleError(
44+
"Logout is not allowed when an API token was supplied.",
45+
"Logout",
46+
);
47+
}
48+
49+
if (!token) {
50+
console.log("Not logged in, nothing to do.");
51+
return;
52+
}
53+
2454
const spinner = ora("Logging out...").start();
55+
2556
try {
26-
await authStore.setToken(baseUrl, undefined);
57+
await authStore.setToken(baseUrl, null);
58+
2759
spinner.succeed("Logged out successfully!");
2860
} catch (error) {
2961
spinner.fail("Logout failed.");
30-
void handleError(error, "Logout");
62+
handleError(error, "Logout");
3163
}
3264
};
3365

packages/cli/commands/companies.ts

Lines changed: 0 additions & 83 deletions
This file was deleted.

0 commit comments

Comments
 (0)