Thank you for your interest in contributing to CUDly! This document provides guidelines and instructions for contributing to the self-hosted platform component.
By participating in this project, you agree to maintain a respectful and inclusive environment. Be kind, constructive, and professional in all interactions.
- Search existing issues - Check if the bug has already been reported
- Create a detailed report including:
- CUDly server build (logged on startup as
CUDly Server v<version> (git: <sha>, built: <time>); built withmake build) - Go version (
go version) - Operating system and architecture
- Cloud provider and service affected
- Steps to reproduce
- Expected vs actual behavior
- Relevant logs (with sensitive data removed)
- CUDly server build (logged on startup as
- Search existing issues - Your idea may already be proposed
- Open a feature request with:
- Clear description of the feature
- Use case and benefits
- Proposed implementation (if applicable)
- Any potential drawbacks
-
Fork the repository
-
Create a feature branch from
main:git checkout -b feature/your-feature-name
-
Make your changes following our coding standards
-
Write or update tests for your changes
-
Run the test suite to ensure everything passes
-
Commit with clear messages following our commit conventions
-
Push to your fork and submit a Pull Request
- Go 1.26.9 or later (the floor set by the
godirective ingo.mod) - Node.js and npm for the
frontend/dashboard - Terraform, when changing deployment definitions
- AWS/Azure/GCP credentials for integration testing
- Git
# Clone your fork
git clone https://github.com/YOUR_USERNAME/cloud-commitments-platform.git
cd cloud-commitments-platform
# Add upstream remote
git remote add upstream https://github.com/LeanerCloud/cloud-commitments-platform.git
# Install dependencies
go mod download
# Build
make build
# Run the unit tests
make test-unitThe repo ships a go.work that lists only this repository's own modules (the root module and tests/e2e). The shared libraries and providers are consumed at the versions pinned in go.mod, so there is nothing else to set up for a standard clone. When you are working across multiple git worktrees simultaneously, gopls needs each worktree's module added to the workspace or it flags every file in the sibling trees with BrokenImport / undefined: <Type>.
Do not edit the committed go.work for local paths -- they vary per
developer and per session.
Instead, create a go.work.local next to go.work (it is gitignored): start
from a copy of the committed go.work and append your active worktrees:
// go.work.local -- gitignored, developer-local
// Keep this `go` line at or above the modules' own directive, otherwise the
// workspace is rejected. Copy it from the committed go.work.
go 1.26.9
use (
.
./tests/e2e
../.worktrees/cloud-commitments-platform/fix-516
../.worktrees/cloud-commitments-platform/feat-something
)Then point gopls at it by setting GOWORK before launching your editor, or by
symlinking it over go.work temporarily:
# Option A: set GOWORK in your shell profile or editor launcher
export GOWORK="$PWD/go.work.local"
# Option B: create go.work.local and let gopls auto-discover it
# (gopls respects GOWORK when set; otherwise it walks up for go.work)After adding or removing a worktree, update go.work.local to match:
# Quick regeneration from git worktree list (space-safe: keeps full paths,
# adds one -use entry per worktree; skips the main checkout on line 1)
git worktree list --porcelain | sed -n 's/^worktree //p' | tail -n +2 |
while IFS= read -r wt; do go work edit -use "$wt"; doneThe committed go.work (listing only this repository's own modules) keeps
go build ./... and CI clean for everyone without requiring any local setup.
# Run the unit tests
make test-unit
# The same suite, invoked directly
go test -short -race ./...
# Run tests with coverage
go test -cover ./...
# Run tests for a specific package
go test ./internal/...
# Run tests with verbose output
go test -v ./...
# Run a specific test
go test -run TestFunctionName ./path/to/packageWe aim to maintain the following minimum test coverage:
| Package | Minimum Coverage |
|---|---|
| API handlers | 70% |
Domain packages (internal/) |
70% |
cmd/ entry points |
60% |
- Follow the Effective Go guidelines
- Use
gofmtto format code - Use
golintandgo vetto catch issues - Keep functions focused and reasonably sized
- Write clear, self-documenting code
- Use CamelCase for exported names, camelCase for unexported
- Use meaningful, descriptive names
- Interfaces describing behavior should end in
-er(e.g.,Reader,Writer) - Test files:
*_test.go - Mock implementations: prefix with
mock
- All exported functions, types, and packages must have doc comments
- Use complete sentences starting with the name being documented
- Include usage examples for complex functionality
- Keep comments up to date with code changes
- Always handle errors explicitly
- Wrap errors with context using
fmt.Errorf("context: %w", err) - Use custom error types for domain-specific errors
- Never ignore errors silently
- Write table-driven tests where appropriate
- Use interfaces and dependency injection for testability
- Mock external dependencies (AWS/Azure/GCP SDKs)
- Test both success and error paths
- Include edge cases in test coverage
cloud-commitments-platform/
├── cmd/ # server, lambda, and utility entry points
├── internal/ # application code (API, auth, purchase, scheduler, ...)
├── iac/ # infrastructure-as-code helpers
├── frontend/ # web dashboard (TypeScript)
├── terraform/, cloudformation/, arm/ # deployment definitions
├── tests/e2e/ # black-box suite (separate stdlib-only module)
├── known_issues/ # tracked tech debt and deferred fixes
├── scripts/ # Repository hook and helper scripts
├── go.mod # Pins the shared modules from cloud-commitments-go
└── Makefile # build, test, vet, and lint targets
Service clients live in github.com/LeanerCloud/cloud-commitments-go. In this
repository:
- Add the service to the provider registry the API reads
- Expose it through
internal/apiif it needs an HTTP route - Add recommendations support if applicable
- Write comprehensive tests
- Update documentation
Provider implementations live in github.com/LeanerCloud/cloud-commitments-go
(providers/aws, providers/azure, providers/gcp). Open the change there.
This repository consumes providers at the versions pinned in go.mod, so
bumping that pin is the only change needed here.
type(scope): brief description
Longer description if needed. Explain what and why,
not how (the code shows how).
Fixes #123
feat: New featurefix: Bug fixdocs: Documentation onlystyle: Formatting, missing semicolons, etc.refactor: Code change that neither fixes a bug nor adds a featureperf: Performance improvementtest: Adding or updating testschore: Build process, dependencies, etc.
feat(aws): add MemoryDB reserved node support
Implements purchase and recommendation fetching for
Amazon MemoryDB reserved nodes.
Fixes #42
fix(azure): handle subscription pagination correctly
The previous implementation missed subscriptions after
the first page. Now properly iterates all pages.
- Update documentation for any user-facing changes
- Add or update tests for your changes
- Ensure all tests pass before submitting
- Fill out the PR template completely
- Request review from maintainers
- Address feedback promptly and constructively
- Code follows project style guidelines
- Tests added/updated and passing
- Documentation updated
- Commit messages follow conventions
- No sensitive data in code or commits
- Changes are backwards compatible (or breaking changes documented)
The known_issues/ directory tracks open tech debt, deferred fixes, and
surfaced bugs that are out of scope for the current PR. To stay useful, it
needs periodic housekeeping.
Each file must begin with a # Known Issues: <topic> heading followed by an
audit-status line:
> **Audit status (<YYYY-MM-DD>):** `<N> needs triage · <M> resolved`
Subsequent sections use ## SEVERITY: Short title (e.g. ## MEDIUM: ...) and
include at minimum: Files (affected paths), Description, Why
deferred, and Status.
- Tech debt or a follow-up bug is discovered during a PR review but is explicitly out of scope for that PR.
- A test is marked flaky and a root-cause fix is deferred.
- A deliberate deferral is made (e.g. "fix after the current refactor lands").
Create a new file known_issues/<NN>_<slug>.md (sequential number, lowercase
slug) and open a corresponding GitHub issue so it can be tracked and closed.
An entry is stale when its corresponding GitHub issue is closed OR when the
entry has had no recurrence for more than 6 months and no open issue
references it. Do not delete stale files; move them to known_issues/resolved/
so the rationale is preserved for future readers.
Any contributor working in a file covered by a known_issues/ doc should
check whether that doc's referenced issue is still open; archive it if not.
A dedicated sweep over the whole directory should happen:
- At the start of each sprint (or monthly if sprints are not used).
- After any PR that explicitly closes multiple issues.
- When a new contributor is onboarding and doing a codebase walkthrough.
To perform a sweep:
# List docs referencing a specific issue number
grep -rl "#<issue-number>" known_issues/
# Cross-check all referenced issues in bulk
grep -h "closes #\|Fixes #\|#[0-9]\+" known_issues/*.md \
| grep -oE '#[0-9]+' | sort -u \
| xargs -I{} gh issue view {} --json state,number,title --jq '[.number,.state,.title]'Move resolved docs to known_issues/resolved/:
git mv known_issues/<file>.md known_issues/resolved/Include the archive in the same PR that closes the underlying issue, or in a
dedicated chore(docs): archive resolved known_issues commit.
Do not report security vulnerabilities through public issues.
Instead, please email security concerns to the maintainers directly. Include:
- Description of the vulnerability
- Steps to reproduce
- Potential impact
- Suggested fix (if any)
- Never commit credentials or secrets
- Use environment variables for sensitive configuration
- Validate all external input
- Follow least-privilege principles
- Keep dependencies updated
We welcome contributions in these areas:
- Additional AWS services (Lambda, DynamoDB, etc.)
- Azure service implementations
- GCP service implementations
- Improved error messages and user experience
- Enhanced reporting and analytics
- Terraform/CloudFormation integration
- Web UI dashboard
- Performance optimizations
- Usage tutorials and guides
- Architecture documentation
- API documentation
- Translation to other languages
- Issues: Open a GitHub issue for bugs or features
- Discussions: Use GitHub Discussions for questions
- Documentation: Check the README and code comments
By contributing to CUDly, you agree that your contributions will be licensed under the Open Software License 3.0 (OSL-3.0).
This means:
- Your contributions can be used commercially
- Derivative works must also be OSL-3.0 licensed
- You grant a patent license for your contributions
- Attribution must be maintained
Thank you to all contributors who help make CUDly better! Your time and expertise are greatly appreciated.