This guide covers development setup, building from source, and contributing to furyctl.
- mise for tool and task management - https://mise.jdx.dev/getting-started.html
- git for version control
Note: Go, golangci-lint, and all other development tools are automatically installed by mise. You do NOT need to install Go manually.
-
Clone the repository:
git clone git@github.com:sighupio/furyctl.git cd furyctl -
Install all development tools:
mise install # Installs Go 1.24.13, golangci-lint, goreleaser, awscli, and all Go-based tools -
Setup Go module dependencies:
mise run setup # Downloads and tidies Go module dependencies -
Build and test:
mise run build # Build with goreleaser mise run test-unit # Run unit tests mise run lint # Run linting
-
Find built binary: The built binary will be in the
dist/directory after runningmise run build.
What gets installed:
mise installautomatically installs Go 1.24.13, golangci-lint 1.64.8, goreleaser, awscli, addlicense, gofumpt, gci, goimports, formattag, ginkgo, and go-cover-treemap - everything you need for development.
The project uses mise for task and tool management. Here are the essential commands:
mise install: Installs ALL development tools automatically:- Native tools: Go 1.24.13, golangci-lint 1.64.8, goreleaser, awscli 2.15.17
- UBI tools: addlicense v1.1.1, gofumpt v0.6.0
- Go tools: gci v0.13.4, goimports v0.22.0, formattag v0.0.9, ginkgo v2.19.0, go-cover-treemap v1.4.2
mise run setup: Downloads and tidies Go module dependencies (go mod download+go mod tidy).
mise run format-go: Runs complete Go formatting pipeline (fmt → fumpt → imports → gci → formattag).mise run license-add: Adds license headers to newly added files.mise run lint: Runs Go linting to check for style issues or common errors.
mise run test-unit: Runs unit tests.mise run test-integration: Runs integration tests.mise run test-e2e: Runs e2e tests.mise run test-most: Runs most tests except expensive AWS-based ones.mise run test-expensive: WARNING: Runs expensive tests that create AWS clusters.
mise run build: Builds the project with goreleaser.mise run release: Release with goreleaser (requires proper setup).mise run clean: Cleans build artifacts.
mise run env: Shows environment variables for development.mise run mod-download: Downloads go modules.mise run mod-tidy: Tidies go modules.mise run mod-upgrade: Upgrades all modules and tidies.
There are four kinds of tests in furyctl:
- unit: Tests that exercise a single component or function in isolation. Tests using local files and dirs are permitted here.
- integration: Tests that require external services, such as GitHub. Tests using only local files and dirs should not be marked as integration.
- e2e: Tests that exercise furyctl binary, invoking it as a CLI tool and checking its output.
- expensive: E2E tests that incur monetary cost, like running an EKS instance on AWS.
Each test class covers specific use cases depending on speed, cost, and dependencies. Anything that uses I/O should be marked as integration, with the exception of local files and folders - any test that uses only the local filesystem can be marked as 'unit' for convenience.
# Run different test suites
mise run test-unit # Fast unit tests
mise run test-integration # Integration tests (require external services)
mise run test-e2e # End-to-end tests with dry-run
mise run test-most # All tests except expensive ones
mise run test-expensive # ⚠️ WARNING: Creates real AWS resources
# View test coverage
mise run test-most # Generates coverage.out
mise run show-coverage # Opens coverage report in browser- Follow typical Go coding conventions
- Prefer structs with methods over standalone functions
- Use lowercase for private variables and methods
- Follow Go's naming and formatting conventions
MANDATORY: Before committing any code changes:
- Format code: Run
mise run format-goto fix all formatting issues automatically - Lint code: Run
mise run lintto verify zero linting violations - Test changes: Run
mise run test-unit(or appropriate test suite) - Add specific files: Use
git add path/to/file- NEVER usegit add .orgit add -A
The project follows strict linting rules. The formatting pipeline handles most issues automatically:
# The recommended workflow
mise run format-go && mise run lintThis runs the complete formatting chain:
gofmt- Standard Go formattinggofumpt- Stricter formatting rulesgoimports- Import organizationgci- Import grouping and sortingformattag- Struct tag formatting
The linter configuration has been carefully tuned - do not modify linter rules without discussion.
The release process is documented in the MAINTENANCE.md file.
For releases not tied to fury-distribution, create a tag and release it. For releases dependent on new distribution versions, the process may be more complex and require updating fury-distribution first.
cmd/: Main commands created with Cobra library (apply, delete, etc.)configs/: Patch configurations and upgrade paths for the distributionpatches/: Version-specific patches applied to fury-distributionprovisioners/: Terraform templates for EKS provider PreFlight phaseupgrades/: Upgrade hooks organized by version (e.g.,1.29.5-1.30.0)
docs/: Project documentation, changelogs, and guidesinternal/: Private code not meant for external usepkg/: Public APIs meant to be used by other packages/projectstest/: Test data, configurations, and assets
- Fork the repository
- Create a feature branch from
main - Make your changes following the code standards above
- Run the pre-commit checklist (format, lint, test)
- Create a pull request with a clear description of changes
- Run
mise run format-goto format code automatically - Run
mise run lintto verify zero linting violations - Run appropriate test suite (
mise run test-unitminimum) - Add only specific files with
git add path/to/file - Never use
git add .orgit add -A
- Open issues for bugs or feature requests on GitHub Issues
- For distribution-related issues, use the distribution repository instead
- Check the FAQ for common questions and technical explanations