Knowledge Hub
Comprehensive guides and references for the OpenFrame platform
OpenFrame Gen1 is Here · The AI platform for autonomous IT is out of beta and ready for production.
Comprehensive guides and references for the OpenFrame platform
Thank you for contributing to OpenFrame CLI! This guide covers everything you need to know to submit high-quality contributions.
OpenFrame CLI follows standard Go conventions:
gofmt / goimports formatting is required — no unformatted code will be mergedgo vet must pass with no warnings# Format and organize imports
goimports -w .
# Run vet
go vet ./...
# Run linter (if golangci-lint is configured)
golangci-lint run
| Element | Convention | Example |
|---|---|---|
| Package names | Lowercase, single word | cluster, executor, redact |
| Exported types | PascalCase | ClusterService, CommandExecutor |
| Unexported types | camelCase | clusterManager, mockExecutor |
| Constants | PascalCase (exported), camelCase (unexported) | DefaultClusterName, maxRetries |
| Test files | _test.go suffix |
service_test.go |
| Test functions | Test prefix + PascalCase |
TestCreateClusterSuccess |
fmt.Errorf("context: %w", err)shared/errors types for structured errors (CommandError, AlreadyHandledError)friendlyHint patterns for user-facing errors// GOOD: Wrap with context
if err := mgr.CreateCluster(ctx, cfg); err != nil {
return fmt.Errorf("creating cluster %q: %w", cfg.Name, err)
}
// BAD: Lost context
if err := mgr.CreateCluster(ctx, cfg); err != nil {
return err
}
When adding a new Cobra command, follow the established pattern:
func getMyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "mycommand [name]",
Short: "One-line description",
Long: `Multi-line detailed description.
The long description should explain what the command does,
when to use it, and any important caveats.`,
Args: cobra.MaximumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
// Validate input
// Delegate to service layer
// Handle errors via sharedErrors.HandleGlobalError
return nil
},
}
// Add flags
cmd.Flags().StringVar(&flagVar, "flag-name", "default", "Flag description")
return cmd
}
context.Context as the first argument for cancellable operationsCommandExecutor interface for all external binary invocations — never os/exec directly| Type | Pattern | Example |
|---|---|---|
| Feature | feature/<short-description> |
feature/add-kind-provider |
| Bug fix | fix/<short-description> |
fix/cluster-delete-timeout |
| Documentation | docs/<short-description> |
docs/update-contributing-guide |
| Refactor | refactor/<short-description> |
refactor/extract-helm-manager |
| Test | test/<short-description> |
test/add-bootstrap-integration |
| Chore | chore/<short-description> |
chore/update-go-dependencies |
Rules:
main unless working on a specific release branchOpenFrame CLI uses Conventional Commits:
<type>(<scope>): <short description>
[optional body]
[optional footer(s)]
| Type | When to Use |
|---|---|
feat |
A new feature |
fix |
A bug fix |
docs |
Documentation changes only |
refactor |
Code change that neither fixes a bug nor adds a feature |
test |
Adding or modifying tests |
chore |
Build process, dependency updates, tooling |
perf |
Performance improvements |
ci |
CI/CD configuration changes |
| Scope | Area |
|---|---|
cluster |
Cluster commands and services |
app |
App commands and chart services |
bootstrap |
Bootstrap command and service |
prereq |
Prerequisites system |
update |
Self-update mechanism |
executor |
Command executor |
k8s |
Kubernetes client package |
argocd |
ArgoCD provider |
helm |
Helm provider |
ui |
Terminal UI and wizards |
errors |
Error handling |
redact |
Secret redaction |
feat(cluster): add --wait flag to cluster create command
Adds a --wait flag that blocks until all cluster nodes are Ready.
Useful for CI pipelines that need the cluster immediately after creation.
fix(argocd): handle stalled sync after ref change
When ArgoCD silently fails to adopt a new ref (ArgoCD v3 regression),
the stall detector now surfaces a diagnostic message after 90s.
docs(contributing): add commit message guidelines
test(bootstrap): add integration test for non-interactive mode
chore: upgrade go-git to v5.12.0
# 1. Ensure all tests pass
go test -race ./...
# 2. Format code
goimports -w .
# 3. Run vet
go vet ./...
# 4. Build successfully
go build -o openframe .
# 5. Test your changes manually
./openframe --help
## Summary
<!-- What does this PR do? -->
## Changes
<!-- List the key changes made -->
-
-
## Testing
<!-- How was this tested? -->
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated (if applicable)
- [ ] Manual testing performed
## Checklist
- [ ] Code follows the style guidelines
- [ ] Self-review completed
- [ ] Tests pass (`go test -race ./...`)
- [ ] `go vet ./...` passes
- [ ] `goimports` formatting applied
- [ ] No secrets or credentials in code
- [ ] Security guidelines followed (secrets registered with redact, no shell injection)
| Size | Lines Changed | Guidance |
|---|---|---|
| Small | < 100 lines | Preferred — fast review |
| Medium | 100–500 lines | Include detailed description |
| Large | 500+ lines | Split into smaller PRs if possible |
When reviewing a PR, check:
Correctness:
Security:
redact.RegisterSecret()Architecture:
Tests:
Documentation:
--help text is accurate and helpfulFollow these steps when adding a new CLI command:
cmd/<group>/<command>.goget<Name>Cmd() function returning *cobra.Commandcmd/cluster/cluster.go)internal/<group>/ with injected dependenciestestutil.TestClusterCommand--help output is accurate and descriptiveTo add a new cluster provider (e.g., Kind):
Provider interface in internal/cluster/providers/<name>/manager.gointernal/cluster/prerequisites/internal/cluster/models/cluster.goAll contribution discussions happen in the OpenMSP Slack. There are no GitHub Issues or Discussions for this project — bring your questions, feature ideas, and bug reports to Slack.