Contributing to Canvas CLI¶
Thank you for your interest in contributing to Canvas CLI! This document provides guidelines and instructions for contributing.
Getting Started¶
Prerequisites¶
- Go 1.21 or later
- Git
- Make (optional, but recommended)
Setting Up Your Development Environment¶
- Fork the repository on GitHub
-
Clone your fork locally:
-
Add the upstream repository:
-
Install dependencies:
-
Build the project:
-
Set up pre-commit hooks:
Development Workflow¶
Branch Strategy¶
We follow a simplified Git Flow:
main ─────●─────●─────●─────●───── (stable releases)
\ /
\ /
develop ─────●───●───●───●─────── (integration branch)
\ /
\ /
feature/xyz ────●─●─────────────── (your work)
Main Branches:
- main - Production-ready code, tagged releases only
- develop - Integration branch for features (PR target)
Supporting Branches:
- feature/* - New features → merge to develop
- fix/* - Bug fixes → merge to develop
- hotfix/* - Urgent production fixes → merge to main and develop
- release/* - Release preparation → merge to main and develop
When develop Syncs with main¶
The develop branch syncs with main in two scenarios:
-
After a release: When a release is tagged on
main, mergemainback intodevelopto capture any release-specific commits (version bumps, changelog updates). -
After a hotfix: Hotfixes merge to both
main(for immediate production fix) anddevelop(to ensure the fix is in future releases).
This ensures develop always contains all production code plus unreleased features.
Creating a Branch¶
Always create a new branch from develop:
Branch naming conventions:
- feature/ - New features
- fix/ - Bug fixes
- hotfix/ - Urgent production fixes
- release/ - Release preparation
- docs/ - Documentation changes
- refactor/ - Code refactoring
- test/ - Adding or updating tests
Making Changes¶
- Make your changes in your branch
- Follow the code style guidelines (see below)
- Add tests for new functionality
- Update documentation as needed
Testing¶
Run tests before committing:
# Run all tests
make test
# Run tests with coverage
make test-coverage
# Run specific package tests
go test -v ./internal/api/...
Code Style¶
- Follow standard Go conventions
-
Use
gofmtto format your code: -
Run the linter:
-
Run
go vet:
Committing Changes¶
We follow conventional commit messages:
Types:
- feat: New feature
- fix: Bug fix
- docs: Documentation changes
- style: Code style changes (formatting, etc.)
- refactor: Code refactoring
- test: Adding or updating tests
- chore: Maintenance tasks
Example:
feat(api): add assignments CRUD operations
Implement Create, Read, Update, and Delete operations for Canvas
assignments with proper error handling and pagination support.
Closes #123
Submitting a Pull Request¶
-
Push your branch to your fork:
-
Open a pull request on GitHub
-
Ensure your PR:
- Has a clear title and description
- References any related issues
- Includes tests for new functionality
- Passes all CI checks
- Updates documentation as needed
Code Organization¶
canvas-cli/
├── cmd/canvas/ # Main entry point
├── commands/ # Cobra CLI commands
├── internal/ # Private packages
│ ├── api/ # Canvas API client
│ ├── auth/ # Authentication & token storage
│ ├── config/ # Configuration management
│ ├── cache/ # Caching system
│ ├── batch/ # Batch operations
│ ├── output/ # Output formatters
│ └── ...
├── pkg/ # Public packages (reusable by other projects)
└── test/ # Test fixtures and integration tests
Package Guidelines¶
- internal/: Private packages that shouldn't be imported by external projects
- pkg/: Public, reusable packages
- commands/: CLI command implementations
- Each package should have a clear, single responsibility
Adding New Features¶
Adding a New Command¶
- Create a new file in
commands/(e.g.,commands/users.go) -
Define your command using Cobra:
-
Implement the command logic
- Add tests in
commands/users_test.go - Update documentation
Adding API Endpoints¶
- Add types to
internal/api/types.goif needed - Create or update the service file (e.g.,
internal/api/users.go) - Implement methods following existing patterns
- Add data normalization in
internal/api/normalize.go - Add tests
Adding a New Output Format¶
- Implement the
Formatterinterface ininternal/output/ - Register the format in
NewFormatter() - Add tests for the new format
- Update documentation
Testing Guidelines¶
Unit Tests¶
- Test file names should match source files with
_test.gosuffix - Use table-driven tests when appropriate
- Mock external dependencies
- Aim for 90%+ code coverage
Example:
func TestNewClient(t *testing.T) {
tests := []struct {
name string
config ClientConfig
wantErr bool
}{
{
name: "valid config",
config: ClientConfig{
BaseURL: "https://canvas.example.com",
Token: "test-token",
},
wantErr: false,
},
// Add more test cases...
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := NewClient(tt.config)
if (err != nil) != tt.wantErr {
t.Errorf("NewClient() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
Integration Tests¶
- Use VCR cassettes to record/replay HTTP interactions
- Never commit real credentials or PII
- Use synthetic test data
Documentation¶
Code Documentation¶
- Add package documentation to the first file in each package
- Document exported functions, types, and constants
- Use complete sentences in comments
- Follow Go doc conventions
Example:
// Client is the Canvas API client with adaptive rate limiting
// and automatic retry logic. It implements the Canvas LMS REST API
// specification.
type Client struct {
// ...
}
// NewClient creates a new Canvas API client with the given configuration.
// It automatically detects the Canvas version and configures appropriate
// rate limiting based on the instance's quota.
func NewClient(config ClientConfig) (*Client, error) {
// ...
}
User Documentation¶
- Update
README.mdfor user-facing changes - Add examples for new commands
- Document new configuration options
- Update the help text in commands
Release Process¶
Releases are automated through GitHub Actions. Here's the complete release workflow:
1. Prepare the Release¶
# Ensure develop is up to date
git checkout develop
git pull origin develop
# Create release branch (optional, for larger releases)
git checkout -b release/v1.0.0
2. Finalize and Tag¶
# Merge develop into main
git checkout main
git pull origin main
git merge develop # or merge release/v1.0.0
# Create version tag
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin main --tags
3. Sync Back to Develop¶
4. Automated Release (GitHub Actions)¶
When the tag is pushed, GitHub Actions will: - Run tests - Build binaries for all platforms (Linux, macOS, Windows) - Create a GitHub release - Upload binaries and checksums - Generate changelog from conventional commits
Getting Help¶
- 📖 Read the project README
- 💬 Ask questions in GitHub Discussions
- 🐛 Report bugs in GitHub Issues
- 📧 Contact maintainers
Code of Conduct¶
Our Standards¶
- Be respectful and inclusive
- Welcome newcomers
- Provide constructive feedback
- Focus on what's best for the community
- Show empathy towards others
Our Responsibilities¶
Maintainers are responsible for: - Clarifying standards of acceptable behavior - Taking appropriate action in response to unacceptable behavior - Moderating comments, commits, code, and other contributions
License¶
By contributing to Canvas CLI, you agree that your contributions will be licensed under the MIT License.
Recognition¶
Contributors will be recognized in: - GitHub contributors page - Release notes - Project README (for significant contributions)
Thank you for contributing to Canvas CLI! 🎉