diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e1b9731 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,85 @@ +# Contributing to ChartScan + +Thanks for taking the time to contribute. This document walks you through everything you need to develop, test, and submit changes. + +## Prerequisites + +- **Go 1.26** or newer (declared in [`go.mod`](go.mod)). +- **Helm** on your `PATH`. ChartScan shells out to `helm lint`, `helm template`, and `helm dependency update` and the test suite assumes Helm is available. +- **Git**, for cloning and for ChartScan's auto-discovery feature. + +## Repository layout + +``` +chartscan/ +├── cmd/chartscan/ # CLI entry point — Cobra commands wired in main.go. +├── internal/ +│ ├── finder/ # Recursive discovery of Helm charts via Chart.yaml. +│ ├── models/ # Result, Config, TestSuite data structures. +│ └── renderer/ # Linting, templating, value-reference checking. +├── pkg/utils/ # Shared utilities (logger). +├── mock/ # Sample charts (valid + invalid) used by tests and smoke runs. +├── demo/ # Demo chart and the README gif. +├── docs/ # User documentation (usage, configuration). +└── .github/workflows/ # CI: go-test on every PR, go-build on release. +``` + +## Local development + +Install dependencies and run the CLI: + +```bash +go mod tidy +go run ./cmd/chartscan scan mock/charts +``` + +Build a binary: + +```bash +go build -o chartscan ./cmd/chartscan +./chartscan version +``` + +## Testing + +Run the full unit test suite: + +```bash +go test ./... +``` + +The repo also ships a [`test.sh`](test.sh) helper that runs `go fmt`, `go vet`, `go test`, and a smoke `scan` against `mock/charts`. Note that `test.sh` currently hard-codes a developer-specific `GOROOT` near the top of the file — adjust the `export` lines for your machine, or just run the underlying commands directly: + +```bash +go fmt ./... +go vet ./... +go test ./... +go run ./cmd/chartscan scan mock/charts +``` + +## Continuous integration + +Two GitHub Actions workflows live in [`.github/workflows/`](.github/workflows): + +- **`go-test.yml`** — runs `go vet` and `go test -v ./...` on every pull request and push to `main`. Uses Go 1.26. +- **`go-build.yml`** — runs when a release is created. Builds `linux/amd64`, `linux/arm64`, and `linux/386` binaries with the release tag injected as the version, and attaches them as release assets. + +Your PR must pass `go-test` before it can be merged. + +## Submitting a pull request + +1. Fork the repository. +2. Create a feature branch: `git checkout -b my-feature`. +3. Make your changes. Keep commits focused and write descriptive messages. +4. Run `go fmt ./... && go vet ./... && go test ./...` and make sure everything passes. +5. Update the user-facing docs in [`docs/`](docs) or [`README.md`](README.md) if you changed CLI behavior, flags, or configuration syntax. +6. Push the branch: `git push origin my-feature`. +7. Open a pull request against `main` and describe what changed and why. + +## Reporting bugs + +Open an issue on [GitHub](https://github.com/Jaydee94/chartscan/issues) with: + +- The ChartScan version (`chartscan version`) and Helm version (`helm version`). +- The exact command you ran. +- The full output, plus the chart or a minimal reproducer if possible. diff --git a/README.md b/README.md index 8df16fa..ee7feb8 100644 --- a/README.md +++ b/README.md @@ -1,209 +1,109 @@ # ChartScan -![Latest Release](https://img.shields.io/github/release/Jaydee94/chartscan.svg) +[![Latest Release](https://img.shields.io/github/release/Jaydee94/chartscan.svg)](https://github.com/Jaydee94/chartscan/releases) +[![Build](https://github.com/Jaydee94/chartscan/actions/workflows/go-build.yml/badge.svg)](https://github.com/Jaydee94/chartscan/actions/workflows/go-build.yml) +[![Tests](https://github.com/Jaydee94/chartscan/actions/workflows/go-test.yml/badge.svg)](https://github.com/Jaydee94/chartscan/actions/workflows/go-test.yml) ![Built with Go](https://img.shields.io/badge/built%20with-Go-00ADD8.svg) -![License](https://img.shields.io/github/license/Jaydee94/chartscan.svg) +[![License](https://img.shields.io/github/license/Jaydee94/chartscan.svg)](LICENSE) ![Stars](https://img.shields.io/github/stars/Jaydee94/chartscan.svg) -**ChartScan** is a CLI tool for scanning and analyzing Helm charts. It provides insights into Helm chart configurations, values, and rendering issues, allowing developers to efficiently debug and validate Helm charts before deployment. +**ChartScan** is a command-line tool for validating Helm charts before they ship. It walks a directory, finds every chart, renders the templates with the values you give it, and reports anything that fails to lint, fails to render, or references a value that is not defined. -drawing +ChartScan logo --- ## Features -- Scans directories for Helm charts. -- Supports multiple values files for rendering charts. -- Configurable output formats: **pretty**, **JSON**, **JUnit**, or **YAML**. -- Supports configuration through YAML-based config files. +- Recursively discovers Helm charts under any directory. +- Renders charts with one or more values files and `--set` overrides. +- Detects undefined `.Values` references in templates. +- Four output formats: `pretty`, `json`, `yaml`, `junit`. +- YAML configuration with named environments (`test`, `staging`, `production`, …). +- Automatically loads `chartscan.yaml` from the root of the current Git repository. +- Renders charts to stdout or to a file via `chartscan template`. --- ## Installation -### Precompiled Binaries +### Precompiled binary -For convenience, precompiled binaries are available for the latest releases of **ChartScan**. These binaries are built for multiple architectures and can be directly downloaded from the **Releases** page on GitHub. +Download the binary for your platform from the [Releases page](https://github.com/Jaydee94/chartscan/releases): -To download the latest release: +| Platform | Asset | +|-----------------|----------------------| +| Linux x86_64 | `chartscan-amd64` | +| Linux ARM64 | `chartscan-arm64` | +| Linux x86 (32) | `chartscan-386` | -1. Go to the [ChartScan Releases Page](https://github.com/Jaydee94/chartscan/releases). -2. Download the appropriate binary for your system: - - **Linux amd64**: `chartscan-amd64` - - **Linux arm64**: `chartscan-arm64` - - **Linux 386**: `chartscan-386` -3. (Optional) Move the binary to a directory in your system's `PATH`: - - ```bash - mv chartscan-[architecture] /usr/local/bin/chartscan - ``` - ---- - -## Prerequisites - -Ensure the following dependencies are installed: - -- **Helm**: [Install Helm](https://helm.sh/docs/intro/install/) - ---- - -## Usage - -### Demo - -![demo](demo/chartscan.gif) - -### Commands - -#### Scan Command - -The `scan` command is used to analyze Helm charts for potential issues: +Move it into your `PATH`: ```bash -chartscan scan [chart-path] +chmod +x chartscan-amd64 +sudo mv chartscan-amd64 /usr/local/bin/chartscan ``` -### Options for `scan` - -- `-f, --values`: Specify values files to use for rendering. -- `-o, --format`: Set the output format (pretty, json, yaml, junit). Default is `pretty`. -- `-c, --config`: Provide a configuration file (YAML format) to override CLI flags. -- `-e, --environment`: (Optional) Specify the environment to use (e.g., test, staging, production). This will load preconfigured values files for the specified environment in chartscan.yaml. - -#### Template Command - -The `template` command is used to render Helm charts with helm template: +### From source ```bash -chartscan template [chart-path] +go install github.com/Jaydee94/chartscan/cmd/chartscan@latest ``` -### Options for `template` +Requires Go 1.26 or newer (see [go.mod](go.mod)). -- `-f, --values`: Specify values files to use for rendering. -- `-o, --format`: Specify an output file to write the rendered chart (optional). -- `-c, --config`: Provide a configuration file (YAML format) to override CLI flags. -- `-e, --environment`: (Optional) Specify the environment to use (e.g., test, staging, production). This will load preconfigured values files for the specified environment in chartscan.yaml. +--- -#### Version Command +## Prerequisites -The `version` command displays the current version of ChartScan: +- [Helm](https://helm.sh/docs/intro/install/) on your `PATH`. ChartScan shells out to `helm lint`, `helm template` and `helm dependency update`. -```bash -chartscan version -``` +--- -### Examples +## Quickstart -#### Scan a Chart Directory with Values Files +Scan a single chart: ```bash -chartscan scan ./charts -f values.yaml -o json +chartscan scan ./charts/my-chart -f values.yaml ``` -#### Use a Config File +Scan every chart under a directory and emit JUnit for CI: ```bash -chartscan scan -c config.yaml -``` - -#### Example Config File - -```yaml -chartPath: ./charts -valuesFiles: - - values.yaml -format: yaml -environments: - test: - valuesFiles: - - values-test.yaml - - values-2-test.yaml - staging: - valuesFiles: - - values-staging.yaml - production: - valuesFiles: - - values-production.yaml +chartscan scan ./charts -o junit > report.xml ``` ---- - -## Automatic Config File Loading in Git Repositories +Render a chart with `helm template`: -When you run ChartScan inside a Git repository, the tool will automatically search for and load a configuration file located in the root directory of the repository. This behavior eliminates the need to manually specify the config file with the -c option if you already have one in your repository. - -How It Works -ChartScan looks for a file named chartscan.yaml in the root directory of the repository. -If the config file is found, ChartScan will automatically load it and use its settings, including chart paths, values files, output format, and more. - -This behavior simplifies configuration management, especially for projects with shared settings across team members. -Example: Automatic Config Loading -For example, if your Git repository has the following directory structure: - -``` -my-repo/ -├── chartscan.yaml -├── charts/ -│ └── my-chart/ -├── values.yaml -└── README.md +```bash +chartscan template ./charts/my-chart -f values.yaml -o rendered.yaml ``` -When you run (inside a git repo with a chartscan.yaml in the root directory): +Use a config file: ```bash -chartscan scan ./charts +chartscan scan -c chartscan.yaml ``` -ChartScan will automatically detect and use chartscan.yaml for its configuration. +When you run ChartScan inside a Git repository that has a `chartscan.yaml` at its root, the file is picked up automatically — no `-c` needed. --- -## Output Formats +## Demo -- **Pretty**: Human-readable formatted output. -- **JSON**: Machine-readable JSON format. -- **YAML**: YAML-encoded output for further processing. -- **JUnit**: JUnit-compatible XML format for test reports. +![ChartScan demo](demo/chartscan.gif) --- -## Development +## Documentation -### Running Locally - -1. Clone the repository. -2. Install dependencies: - - ```bash - go mod tidy - ``` - -3. Run the tool: - - ```bash - go run ./cmd/chartscan [command] [options] - ``` - -### Testing - -Run the test suite: - -```bash -go test ./... -``` +- [Usage reference](docs/usage.md) — every command, flag, and example. +- [Configuration](docs/configuration.md) — `chartscan.yaml` schema, environments, auto-discovery. +- [Contributing](CONTRIBUTING.md) — local setup, tests, PR workflow. --- -## Contribution - -Contributions are welcome! Please follow these steps: +## License -1. Fork the repository. -2. Create a feature branch (`git checkout -b feature-name`). -3. Commit your changes (`git commit -m "Add feature"`). -4. Push to the branch (`git push origin feature-name`). -5. Open a pull request. +Released under the terms of the [LICENSE](LICENSE) file in this repository. diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..59b854c --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,88 @@ +# Configuration + +ChartScan can be driven entirely from the command line, but for repeatable runs — local development, CI pipelines, multi-environment promotions — you will want a `chartscan.yaml` file. + +## Schema + +```yaml +# Directory that contains your charts. Relative to the config file. +chartPath: ./charts + +# Default output format for `scan`. One of: pretty, json, yaml, junit. +format: pretty + +# Values files applied to every chart, unless overridden per environment +# or by the -f / --values CLI flag. Paths are relative to the config file. +valuesFiles: + - values.yaml + +# Optional named environments. Each environment overrides `valuesFiles` +# when the user passes -e . +environments: + test: + valuesFiles: + - values-test.yaml + staging: + valuesFiles: + - values-staging.yaml + production: + valuesFiles: + - values-production.yaml +``` + +All keys are optional. An empty file is valid; ChartScan will simply rely on CLI flags. + +## Path resolution + +Every path in `chartscan.yaml` — `chartPath` and every entry in `valuesFiles` — is resolved relative to the directory that holds the config file, not the current working directory. This means you can run ChartScan from any subdirectory of your repo without rewriting paths. + +## Environments + +Each entry under `environments` is a named bundle of `valuesFiles` to apply for that environment. Select one at runtime with `-e, --environment`: + +```bash +chartscan scan -c chartscan.yaml -e staging +``` + +That replaces the top-level `valuesFiles` for the duration of the run. If the environment exists but defines no `valuesFiles`, the top-level list is cleared (no values files are passed). + +List the environments declared in a file: + +```bash +chartscan -l -c chartscan.yaml +``` + +Sample output: + +```text ++-------------+---------------------------+ +| ENVIRONMENT | VALUES FILES | ++-------------+---------------------------+ +| test | • values-test.yaml | +| staging | • values-staging.yaml | +| production | • values-production.yaml | ++-------------+---------------------------+ +``` + +## Automatic discovery in Git repositories + +If you do not pass `-c`, ChartScan checks whether the current directory is inside a Git repository. If it is, ChartScan looks for `chartscan.yaml` at the repository root (the output of `git rev-parse --show-toplevel`). When the file is present, ChartScan prints: + +```text +Using config file from project root: /path/to/repo/chartscan.yaml +``` + +…and proceeds as if `-c` had been passed. This makes shared team configurations friction-free: commit `chartscan.yaml` to your repo and every contributor gets the same behavior. + +If you are not in a Git repository, or if the file does not exist at the repo root, ChartScan falls back to CLI-only configuration. + +## CLI overrides + +The order of precedence, lowest to highest: + +1. `chartscan.yaml` defaults. +2. Environment override (`-e`) — replaces `valuesFiles`. +3. CLI flags — `-f, --values` replaces `valuesFiles`; `-o, --output-format` replaces `format`. +4. `--set` overrides — applied last when rendering, the same way `helm template --set` works. + +In other words: the further to the right you go on the command line, the more it wins. diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..457f49b --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,172 @@ +# Usage + +This page documents every ChartScan command, every flag, and a recipe for each common workflow. For configuration file syntax see [configuration.md](configuration.md). + +## Commands at a glance + +| Command | Purpose | +|------------|------------------------------------------------------------| +| `scan` | Discover Helm charts, render them, report errors and undefined values. | +| `template` | Render one or more charts with `helm template`. | +| `version` | Print the ChartScan version. | + +## Global flags + +These flags work on the root command and on every subcommand. + +| Flag | Description | +|----------------------------|----------------------------------------------------------------------------------------------| +| `-c, --config ` | Path to a `chartscan.yaml` configuration file. | +| `-l, --list-environments` | List every environment defined in the resolved config file and exit. Works with `-c` or with auto-discovery in a Git repo. | +| `-h, --help` | Show help for the current command. | + +--- + +## `scan` + +Discover Helm charts under one or more paths, render each one, and report the result. + +**Synopsis** + +```text +chartscan scan [chart-path]... [flags] +``` + +At least one chart path is required. Each path may be a single chart directory or a parent directory that contains many charts — ChartScan recurses and treats every directory that contains a `Chart.yaml` as a chart. + +**Flags** + +| Flag | Default | Description | +|-------------------------------|----------|---------------------------------------------------------------------------------------------------| +| `-f, --values ` | — | Values file to use. Repeat the flag to merge multiple files (later files win). | +| `-o, --output-format ` | `pretty` | One of `pretty`, `json`, `yaml`, `junit`. | +| `-c, --config ` | — | Configuration file. CLI flags override values from the file. | +| `-e, --environment ` | — | Use the `valuesFiles` defined under `environments.` in the config file. | +| `--set key=val[,key=val…]` | — | Inline value override, identical in semantics to `helm template --set`. Repeatable. | +| `--fail-on-error` | `false` | Exit with status `1` if any chart fails to render. Without this flag, errors are reported but ChartScan exits `0`. | + +**Exit codes** + +| Code | Meaning | +|------|----------------------------------------------------------------------------------------| +| `0` | All charts processed successfully, or errors were reported without `--fail-on-error`. | +| `1` | A fatal error occurred (bad flags, missing files), or `--fail-on-error` was set and at least one chart was invalid. | + +--- + +## `template` + +Render one or more Helm charts using `helm template`, writing the output to stdout or to a file. + +**Synopsis** + +```text +chartscan template [chart-path]... [flags] +``` + +At least one chart path is required. Multiple paths are allowed and are rendered in sequence. + +**Flags** + +| Flag | Default | Description | +|-------------------------------|---------|------------------------------------------------------------------------------------------| +| `-f, --values ` | — | Values file to use. Repeat the flag to merge multiple files. | +| `-o, --output ` | stdout | Write the rendered manifests to this file instead of stdout. | +| `-c, --config ` | — | Configuration file. CLI flags override values from the file. | +| `-e, --environment ` | — | Use the `valuesFiles` defined under `environments.` in the config file. | +| `--set key=val[,key=val…]` | — | Inline value override, identical in semantics to `helm template --set`. Repeatable. | + +--- + +## `version` + +Print the ChartScan version. + +```bash +chartscan version +``` + +The version string is `dev` for `go run` and `go install` builds. Release builds inject the Git tag via `-ldflags "-X main.version=$VERSION"` (see [`.github/workflows/go-build.yml`](../.github/workflows/go-build.yml)). + +--- + +## Output formats + +The `-o, --output-format` flag on `scan` selects one of: + +| Format | Description | +|----------|------------------------------------------------------------------------------------------------------| +| `pretty` | Human-readable colored table. Default. | +| `json` | One JSON document with the array of per-chart results. Suitable for piping into `jq`. | +| `yaml` | Same structure as `json` but YAML-encoded. | +| `junit` | JUnit XML test report — one `` per chart, with a `` element on rendering errors. | + +Each result entry contains the chart path, a success flag, any errors, the merged values, and the list of undefined value references. + +--- + +## Recipes + +**Scan one chart** + +```bash +chartscan scan ./charts/my-chart -f values.yaml +``` + +**Scan every chart in a directory tree** + +```bash +chartscan scan ./charts +``` + +**Merge multiple values files** + +```bash +chartscan scan ./charts/my-chart \ + -f values.yaml \ + -f values-overrides.yaml +``` + +**Inline overrides** + +```bash +chartscan scan ./charts/my-chart \ + -f values.yaml \ + --set image.tag=1.4.2,replicaCount=3 +``` + +**Fail the build if any chart is broken** + +```bash +chartscan scan ./charts --fail-on-error +``` + +**Render a chart to a file** + +```bash +chartscan template ./charts/my-chart -f values.yaml -o rendered.yaml +``` + +**Render several charts in one invocation** + +```bash +chartscan template ./charts/api ./charts/worker -f common-values.yaml +``` + +**Produce a JUnit report for CI** + +```bash +chartscan scan ./charts -o junit > chartscan-report.xml +``` + +**List the environments declared in a config file** + +```bash +chartscan -l -c chartscan.yaml +``` + +**Use a named environment from the config file** + +```bash +chartscan scan -c chartscan.yaml -e staging +```