Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,9 @@
"**/*.lock": true
},
"typescript.tsdk": "node_modules/typescript/lib",
"cSpell.words": ["bucketco", "openfeature"]
"cSpell.words": [
"booleanish",
"bucketco",
"openfeature"
]
}
45 changes: 45 additions & 0 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ These options can be used with any command:
- `--debug`: Enable debug mode for verbose output.
- `--base-url <url>`: Set the base URL for Bucket API.
- `--api-url <url>`: Set the API URL directly (overrides base URL).
- `--api-key <key>`: Bucket API key for non-interactive authentication.
- `--help`: Display help information for a command.

## AI-Assisted Development
Expand Down Expand Up @@ -297,6 +298,50 @@ The command will guide you through:

_**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.**_

## Using in CI/CD Pipelines (Beta)

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.

```bash
# Generate types in CI/CD
npx bucket apps list --api-key $BUCKET_API_KEY
```

**Important restrictions:**

- When using `--api-key`, the `login` and `logout` commands are disabled.
- API keys bypass all interactive authentication flows.
- Only _read-only_ access to Bucket API is granted at the moment.
- API keys are bound to one app only. Commands such as `apps list` will only return the bound app.
- Store API keys securely using your CI/CD platform's secret management.

### Primary Use Case: Type Validation in CI/CD

Use the `--check-only` flag with `features types` to validate that generated types are up-to-date:

```bash
# Check if types are current (exits with non-zero code if not)
npx bucket features types --check-only --api-key $BUCKET_API_KEY --app-id ap123456789
```

This is particularly useful for:

- **Pull Request validation**: Ensure developers have regenerated types after feature changes.
- **Build verification**: Confirm types are synchronized before deployment.
- **Automated quality checks**: Catch type drift in your CI pipeline.

Example CI workflow:

```yaml
# GitHub Actions example
- name: Validate Bucket types
run: npx bucket features types --check-only --api-key ${{ secrets.BUCKET_API_KEY }}

- name: Generate types if validation fails
if: failure()
run: npx bucket features types --api-key ${{ secrets.BUCKET_API_KEY }}
```

## Development

```bash
Expand Down
5 changes: 3 additions & 2 deletions packages/cli/commands/apps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { handleError } from "../utils/errors.js";
export const listAppsAction = async () => {
const baseUrl = configStore.getConfig("baseUrl");
const spinner = ora(`Loading apps from ${chalk.cyan(baseUrl)}...`).start();

try {
const apps = await listApps();
const apps = listApps();
spinner.succeed(`Loaded apps from ${chalk.cyan(baseUrl)}.`);
console.table(apps.map(({ name, id, demo }) => ({ name, id, demo })));
} catch (error) {
spinner.fail("Failed to list apps.");
void handleError(error, "Apps List");
handleError(error, "Apps List");
}
};

Expand Down
23 changes: 20 additions & 3 deletions packages/cli/commands/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,41 @@ import { handleError } from "../utils/errors.js";
export const loginAction = async () => {
const { baseUrl, apiUrl } = configStore.getConfig();

if (authStore.getToken(baseUrl).isApiKey) {
await handleError(
Comment thread
pavkam marked this conversation as resolved.
Outdated
"Login is not allowed when an API token was supplied.",
"Login",
);
}

try {
await waitForAccessToken(baseUrl, apiUrl);
console.log(`Logged in to ${chalk.cyan(baseUrl)} successfully!`);
} catch (error) {
console.error("Login failed.");
void handleError(error, "Login");
await handleError(error, "Login");
}
};

export const logoutAction = async () => {
const baseUrl = configStore.getConfig("baseUrl");

if (authStore.getToken(baseUrl).isApiKey) {
await handleError(
Comment thread
pavkam marked this conversation as resolved.
Outdated
"Logout is not allowed when an API token was supplied.",
"Logout",
);
}

const spinner = ora("Logging out...").start();

try {
await authStore.setToken(baseUrl, undefined);
await authStore.setToken(baseUrl, null);

spinner.succeed("Logged out successfully!");
} catch (error) {
spinner.fail("Logout failed.");
void handleError(error, "Logout");
await handleError(error, "Logout");
Comment thread
pavkam marked this conversation as resolved.
Outdated
}
};

Expand Down
83 changes: 0 additions & 83 deletions packages/cli/commands/companies.ts

This file was deleted.

Loading