This document is a guide to help you through the process of contributing to gcx.
Before implementing features or commands, read:
- ARCHITECTURE.md — system architecture, pipeline diagrams, ADR index
- DESIGN.md — CLI UX design: command grammar, output model, taste rules
- CONSTITUTION.md — invariants you must not violate
- docs/design/ — prescriptive UX implementation rules (output, errors, agent mode, naming, …)
Issues are tracked in GitHub Issues. Use the issue templates when creating new issues — they set the correct issue type and labels automatically.
GitHub's native issue types classify issues. Don't add type prefixes to titles.
| Type | When to use |
|---|---|
| Bug | Something is broken or behaving unexpectedly |
| Task | A specific piece of implementation work |
| Feature | New functionality or capability |
| Enhancement | Improvement to existing functionality |
| Epic | Large effort spanning multiple issues |
Write clear, concise titles. The style depends on the issue type:
| Type | Style | Good | Bad |
|---|---|---|---|
| Task / Feature | Imperative verb | "Add OnCall provider" | "OnCall provider" |
| Enhancement | Imperative verb | "Improve cold-start latency" | "[Enhancement]: cold start is slow" |
| Bug | Descriptive symptom | "Excessive warnings for unconfigured resources" | "[Bug]: warnings" |
| Epic | Noun phrase (scope) | "OAuth authentication via Grafana Assistant" | "Epic: do OAuth stuff" |
Rules:
- No type prefixes (
[Bug]:,Epic:,[Feature]:) — the issue type field handles this - Start with a capital letter
- Be specific — someone should understand the scope from the title alone
- Tasks and features start with a verb: Add, Implement, Port, Create, Fix, Improve, etc.
| Prefix | Purpose |
|---|---|
area/ |
Codebase area (providers, cli-ux, core, skills, docs) |
priority/ |
Severity (critical, high, medium, low, none) |
action/ |
Workflow state (needs-triage) |
Issues are grouped into milestones representing release targets. Check the milestones page for current targets.
gcx relies on devbox to manage all
the tools required to work on it.
A shell including all these tools is accessible via:
$ devbox shellThis shell can be exited like any other shell, with exit or CTRL+D.
One-off commands can be executed within the devbox shell as well:
$ devbox run go versionPackages can be installed using:
$ devbox add go@1.24Available packages can be found on the NixOS package repository.
While unit tests are valuable for testing individual components, integration testing against a real Grafana instance is important to ensure gcx works correctly with the actual Grafana API.
The repository includes a docker-compose.yml file that sets up a complete test environment with:
- Grafana 12.2 (latest stable release)
- MySQL 8.0 (as the backend database)
- Pre-configured with
admin:admincredentials - The
kubernetesDashboardsfeature toggle enabled (required forgcx)
Start the services using the Make target:
$ make test-env-upThis will start both Grafana and MySQL, wait for them to be healthy, and display the connection information.
You can also start the services manually:
$ docker-compose up -dCheck the status of the services:
$ make test-env-statusOr manually:
$ docker-compose psYou should see both gcx-grafana and gcx-mysql in a healthy state.
Verify Grafana is accessible:
$ curl -u admin:admin http://localhost:3000/api/healthYou should receive a JSON response indicating Grafana is running.
The repository includes a pre-configured test config file at testdata/integration-test-config.yaml that you can use to test gcx against the local Grafana instance.
$ devbox run go run ./cmd/gcx --config testdata/integration-test-config.yaml config view$ devbox run go run ./cmd/gcx --config testdata/integration-test-config.yaml resources schemas- Create a dashboard YAML file (e.g.,
test-dashboard.yaml):
apiVersion: v1alpha1
kind: Dashboard
metadata:
name: test-dashboard
spec:
title: Test Dashboard
tags: [test]
timezone: browser
schemaVersion: 36- Push it to Grafana:
$ devbox run go run ./cmd/gcx --config testdata/integration-test-config.yaml resources push test-dashboard.yaml- Pull it back to verify:
$ devbox run go run ./cmd/gcx --config testdata/integration-test-config.yaml resources get dashboards/test-dashboardThe serve command allows you to develop dashboards locally with live reload:
$ devbox run go run ./cmd/gcx --config testdata/integration-test-config.yaml dev serve test-dashboard.yamlThen open your browser to the URL shown in the output (typically http://localhost:8080).
When you're done testing, stop the services:
$ make test-env-downOr manually:
$ docker-compose downTo remove all data (including database volumes):
$ make test-env-cleanOr manually:
$ docker-compose down -vThe Grafana instance uses a custom configuration file at testdata/grafana.ini. You can modify this file to change Grafana's behavior. After making changes, restart the services:
$ docker-compose restart grafanaTo test against a different Grafana version, modify the image field in docker-compose.yml:
services:
grafana:
image: grafana/grafana:12.1 # or any other versionThen restart the services:
$ docker-compose up -d --force-recreate grafanaTo view logs from both services:
$ make test-env-logsTo view logs from a specific service:
$ docker-compose logs -f grafanaOr for MySQL:
$ docker-compose logs -f mysqlCheck the logs for errors:
$ docker-compose logs grafanaCommon issues:
- MySQL not fully initialized yet - wait a few more seconds and check again
- Port 3000 already in use - stop any other Grafana instances or change the port in
docker-compose.yml
Verify Grafana is accessible:
$ curl -u admin:admin http://localhost:3000/api/healthIf this fails, check:
- Services are running:
docker-compose ps - Firewall settings are not blocking port 3000
- Check Grafana logs:
docker-compose logs grafana
Check MySQL is healthy:
$ docker-compose ps mysqlIf MySQL is not healthy, check the logs:
$ docker-compose logs mysqlYou may need to remove the volume and recreate it:
$ docker-compose down -v
$ docker-compose up -d