An open API service indexing awesome lists of open source software.

https://github.com/cozystack/cozyvalues-gen

OpenAPI schema and README generator for Helm
https://github.com/cozystack/cozyvalues-gen

helm

Last synced: 17 days ago
JSON representation

OpenAPI schema and README generator for Helm

Awesome Lists containing this project

README

          

# cozyvalues-gen

Tiny helper that turns **JSDoc-annotated `values.yaml`** files into:

1. **Go structs** – strongly typed, IDE-friendly.
2. **CustomResourceDefinitions (CRD)** – produced by `controller-gen`.
3. **values.schema.json** – OpenAPI schema extracted from the CRD.
4. **README.md** – auto-updated `## Parameters` section.

The chain "_structs → CRD → OpenAPI_" re-uses the same code that Kubernetes itself relies on, so you get **maximum type compatibility** for free.

## Syntax Overview

Uses **JSDoc-like syntax** for clean, readable type annotations:

---

## How it works

```mermaid
graph LR
A[values.yaml] --> B(Go structs)
B --> C[CRD YAML]
C --> D[values.schema.json]
A --> E[README.md]
```

- Annotate your `values.yaml` (see [examples](examples) for the exact syntax).
- Run cozyvalues-gen; it parses the comments and spits out Go code.
- controller-gen compiles that code, emitting a CRD.
- The tool trims the CRD down to a Helm-compatible schema.

### Usage (one-liner)

```
cozyvalues-gen \
--values values.yaml \
--schema values.schema.json
```

See `cozyvalues-gen` -h for all flags.

## Installation

### Homebrew (macOS and Linux)

```bash
brew tap cozystack/tap
brew install cozyvalues-gen
```

> **Note**: This uses our [incubating tap](https://github.com/cozystack/homebrew-tap). The formula will be submitted to official homebrew/core once it reaches 75+ stars and stable adoption.

### Using `go install`

Requires Go toolchain installed and accessible via `$PATH`.

```console
go install github.com/cozystack/cozyvalues-gen@latest
```

The binary lands in `$(go env GOPATH)/bin` (usually `~/go/bin`). Make sure that directory is on your `$PATH`.

### Download a pre‑built release binary

Head over to [https://github.com/cozystack/cozyvalues-gen/releases](https://github.com/cozystack/cozyvalues-gen/releases), grab the archive for your OS/arch, unpack it somewhere on your `$PATH`.

## Annotation Tags

### @param
Defines a top-level parameter:
```yaml
## @param {type} name - description
## @param {string} hostname - Server hostname
hostname: "example.com"

## @param {int} replicas - Number of replicas
replicas: 3
```

### @typedef
Defines a custom type (struct):
```yaml
## @typedef {struct} Database - Database configuration
## @field {string} host - Database host
## @field {int} port - Database port

## @param {Database} database - Database config
database:
host: localhost
port: 5432
```

### @field / @property
Defines fields within a typedef (@property is a synonym):
```yaml
## @typedef {struct} User
## @field {string} name - User name
## @field {string} [email] - Email (optional, with omitempty)
## @field {int} age=18 - Age with default value
```

### @enum
Defines an enumeration type:
```yaml
## @enum {string} Size - Size preset
## @value small
## @value medium
## @value large

## @param {Size} size="medium" - Selected size
size: "medium"
```

### Special Syntax

- **Optional fields**: `[fieldName]` adds `omitempty` to JSON tag
- **Pointers**: `{*type}` or `{?type}` (equivalent)
- **Default values**: `fieldName=value` or `fieldName="value"`

### Validation constraints

Stack these tags on the line(s) after a `@param` or `@field`. They emit kubebuilder validation markers on the generated Go struct and JSON-schema entries in `values.schema.json`.

```yaml
## @param {int} port - Port number
## @minimum 1
## @maximum 65535
port: 8080

## @param {string} name - DNS-compatible name
## @minLength 1
## @maxLength 63
## @pattern ^[a-z0-9-]+$
name: ""

## @param {[]string} tags - Tag list
## @minItems 1
## @maxItems 10
tags: []

## @param {string} storageClass - StorageClass used to store the data.
## @immutable
storageClass: ""
```

Available constraints: `@minimum`, `@maximum`, `@exclusiveMinimum`, `@exclusiveMaximum`, `@minLength`, `@maxLength`, `@pattern`, `@minItems`, `@maxItems`, `@immutable`.

**Placement matters.** Every constraint attaches to the most-recent `@param` or `@field` declaration. Place constraints **immediately after** the `@param`/`@field` header and **before** the YAML value line. If a constraint appears after the YAML value (e.g. floating between two `@param` blocks), it still attaches to the preceding `@param` for backwards compatibility, but `cozyvalues-gen` prints

```
cozyvalues-gen: :: warning: constraint on this line still attaches to "" across an intervening YAML value line; move it to immediately after the @param/@field header for clarity
```

so the misplacement is visible in `make generate` output. The warning never fails the build — fix the placement to silence it.

`@immutable` is a flag (no argument). It emits a CEL `XValidation` rule (`self == oldSelf`) at the property level. **Caveat**: per Kubernetes `x-kubernetes-validations` semantics, a property-level rule is evaluated only when the property is present in both `oldSelf` and `self`. For optional/omitempty/pointer fields the rule therefore enforces *immutable once set* rather than *immutable from creation* — the field can still be added on a subsequent update if it was absent on create. To enforce *immutable from creation* make the field required (omit `[name]` brackets and pointer markers).

## Supported value types

| Annotation token | Go type | JSON Schema | Examples |
| ------------------------------ | ------------------------------------------ | ----------------------- | ------------------------------------ |
| `string` | `string` | string | `"hello"` |
| `bool` | `bool` | boolean | `true` |
| `int`, `int32`, `int64` | matching signed integer | number | `42` |
| `float32`, `float64` | matching float | number | `3.14` |
| `quantity` | `resource.Quantity` | string | `"500Mi"`, `"100m"`, `"4Gi"` |
| `duration` | `metav1.Duration` | string | `"5m"`, `"1h30m"` |
| `time` | `metav1.Time` | string (RFC 3339) | `"2025-08-07T12:00:00Z"` |
| `object` | `k8sRuntime.RawExtension` | any JSON/YAML | `{"aaa": 123, "foo": "bar"}` |
| `emptyobject` | empty struct (`struct{}`) **–** no fields | `{}` | `{}` |
| `intOrString` | `intstr.IntOrString` | `anyOf` int or string | `100`, `"100"` (PostgreSQL params) |
| `*` | pointer to that primitive (`nil` allowed) | primitive or `null` | `"asd"`, `null` … |
| `` | generated struct | object | declared from `@field` annotations |
| `*` | pointer to generated struct | object or `null` | `null` |
| `[]` | slice / YAML sequence | list | `[]string`, `[]*int`, `[]CustomType` |
| `map[string]` | map / YAML mapping | object | keys are always **strings** |

### String-format aliases

These tokens map to a plain `string` field, **plus** `format: ""` in the OpenAPI schema:

| `format` | Example value |
| --------------- | -------------------------------------- |
| `bsonobjectid` | `507f1f77bcf86cd799439011` |
| `uri` | `https://grafana.example.com` |
| `email` | `user@example.com` |
| `hostname` | `db.internal` |
| `ipv4` | `192.168.0.10` |
| `ipv6` | `2001:db8::1` |
| `cidr` | `10.0.0.0/24` |
| `mac` | `00:1A:2B:3C:4D:5E` |
| `uuid`, `uuid3`, `uuid4`, `uuid5` | `550e8400-e29b-41d4-a716-446655440000` |
| `isbn`, `isbn10`, `isbn13` | `9783161484100` |
| `creditcard` | `4242 4242 4242 4242` |
| `ssn` | `123-45-6789` |
| `hexcolor` | `#ff8800` |
| `rgbcolor` | `rgb(255,136,0)` |
| `byte` | `SGVsbG8=` (base64) |
| `password` | *(hidden by most UIs)* |
| `date` | `2025-08-07` |

> **Tip:** use any alias exactly like a regular type, e.g.
> ```yaml
> ## @param apiURL {uri} External URL of the API
> apiURL: ""
> ```

---

Created for the Cozystack project. 🚀