Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 43 additions & 10 deletions plugins/heph-go/skills/heph-go/references/go-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,13 @@ target(
**Rule of thumb:** code the package *imports* → `go_src`; files a test *reads* →
`go_test_data`.

## `provider_state` — per-subtree configuration
## `provider_state` — per-package configuration

`provider_state(provider="go", ...)` placed in a BUILD file configures the go
provider for that package **and every descendant package**. When the same key is
set at multiple depths, the **deepest (closest) ancestor wins** — set a default
high and override it in a leaf.
provider for that package. `go_codegen_root` and `go_codegen_deps` always extend
to descendant packages. `test` and `link` apply to the exact declaring package by
default; set `recursive = True` to extend them to descendants. When the same key
applies at multiple depths, the **deepest (closest) applicable declaration wins**.

```python title="BUILD"
provider_state(
Expand All @@ -203,18 +204,20 @@ provider_state(

| Key | Type | Effect |
|-------------------|------------------------|--------|
| `go_codegen_root` | `bool` | When `True` on an ancestor, `go_src` targets are searched across the whole subtree rooted here (matched by package prefix) instead of only the leaf package. Use when one generator feeds many descendant packages. The deepest ancestor with this flag whose package is a prefix of the target's package is chosen. |
| `go_codegen_deps` | `list[string]` | Explicit codegen target addresses injected into every descendant package's analysis/build sandbox. For generators that aren't labelled `go_src`. Honored independently of `go_codegen_root` (a BUILD setting only this still injects them). The closest ancestor carrying it wins. |
| `test` | `bool \| struct(...)` | `False` stops test-target generation for this subtree; `True` / unset runs them. The struct form configures `test`/`xtest` run targets — env vars and pre-run shell lines — package-scoped only. See below. |
| `go_codegen_root` | `bool` | When `True` on an ancestor, `go_src` targets are searched across the whole subtree rooted here (matched by package prefix) instead of only the leaf package. Use when one generator feeds many descendant packages. The deepest ancestor with this flag whose package is a prefix of the target's package is chosen. Always applies to descendants, independent of `recursive`. |
| `go_codegen_deps` | `list[string]` | Explicit codegen target addresses injected into every descendant package's analysis/build sandbox. For generators that aren't labelled `go_src`. Honored independently of `go_codegen_root` (a BUILD setting only this still injects them). The closest ancestor carrying it wins. Always applies to descendants, independent of `recursive`. |
| `test` | `bool \| struct(...)` | `False` stops test-target generation for this package; `True` / unset runs them. The struct form configures `test`/`xtest` run targets — env vars and pre-run shell lines. Package-scoped by default; add `recursive = True` to extend to descendants. See below. |
| `link` | `struct(...)` | Link settings for a `main` package's `build` (binary) target: `flags`, `deps`, `runtime_deps`. Package-scoped by default; add `recursive = True` to extend to descendants. See below. |
| `recursive` | `bool` | When `True`, extends this state's `test` and `link` config to all descendant packages. `go_codegen_root` and `go_codegen_deps` are unaffected — they always apply to descendants. |

### `test` — skipping and environment

**Bool form** (inherited down the package tree — the deepest ancestor wins):
**Bool form** (applies to the exact declaring package by default; add `recursive = True` to extend to descendants — the closest applicable declaration wins):

- `test = False` — disables test-target generation for this package and all descendants.
- `test = False` — disables test-target generation for this package (and descendants if `recursive = True`).
- `test = True` — (default) enables them. Overrides an ancestor's `test = False`.

**Struct form** (package-scoped only — does **not** affect descendants):
**Struct form** (applies to the exact declaring package by default; add `recursive = True` to extend to descendants):

Configures the generated `test`/`xtest` run targets. A struct-form
state also re-enables tests even when an ancestor set `test = False`.
Expand All @@ -240,6 +243,35 @@ provider_state(
| `runtime_pass_env` | `list[string]` | no | Like `pass_env` but excluded from the cache key. |
| `pre_run` | `list[string]` | yes | Shell lines run before the test binary. When non-empty, the target switches from the `exec` driver to the `bash` driver so the lines execute as shell. |

### `link` — binary link configuration

The `link` struct configures the `build` (binary) target generated for a
`package main`. Package-scoped by default; add `recursive = True` to extend to
descendant packages.

When multiple applicable states carry `link`, their values accumulate
shallow-to-deep: a recursive ancestor's flags, deps, and runtime deps are
collected first, then the package's own.

```python title="BUILD"
provider_state(
provider = "go",
link = {
"flags": ["-X main.version=1.2.3", "-s"],
"deps": ["//embed:assets"],
"runtime_deps": ["//data:config"],
},
)
```

| Field | Type | Hashed | Description |
|----------------|----------------|--------|-------------|
| `flags` | `list[string]` | yes | Extra flags passed verbatim to `go tool link`, inserted before `-o`. Use for `-X` linker vars, stripping flags (`-s`, `-w`), etc. |
| `deps` | `list[string]` | yes | Target addresses staged into the link sandbox as hashed inputs. `flags` can reference their outputs. |
| `runtime_deps` | `list[string]` | no | Target addresses staged with the binary at run time only. Not hashed — they do not affect the cache key. |

Unknown keys in the `link` map are rejected with a clear error naming the unrecognized field.

### How `go_src`/codegen resolution actually composes

For each package, the package sandbox source set is:
Expand All @@ -266,6 +298,7 @@ driver (so its runtime re-glob matches Go's resolution).
| Wrong/old third-party version compiled | `go.mod` version drift vs the generated `@version` address | Reconcile `go.mod`; the address (and thus cache key) follows the pinned version. |
| Non-reproducible builds across machines | using `gotool = "host"` | Switch to a pinned version: `gotool: "1.26.4"` and add `checksums`. |
| SDK checksum mismatch | `checksums` entry doesn't match the tarball | Look up the correct SHA-256 at https://go.dev/dl/?mode=json. |
| `test = False` unexpectedly not disabling descendants | missing `recursive = True` | Add `recursive = True` to the `provider_state` to extend to descendants. |

## Verification commands

Expand Down
67 changes: 51 additions & 16 deletions website/docs/plugins/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ generates targets for it — you don't write `target()` calls for Go code. For a
package it produces:

| Target | Builds | Labels |
|-----------|--------|--------|
|-----------|--------|---------|
| `:build` | The library or, for `package main`, the binary. | |
| `:test` | The package's tests. | `test`, `go-test` |

Expand Down Expand Up @@ -290,41 +290,47 @@ graph, never by hand:
Because the module and version are part of the address, a dependency bump
changes the address and invalidates only the targets that import it.

## provider_state — per-subtree configuration
## provider_state — per-package configuration

`provider_state(provider="go", ...)` placed in a BUILD file configures the Go
provider for that package and every descendant package. When the same key is set
at multiple depths, the deepest (closest) ancestor wins.
provider for that package. `go_codegen_root` and `go_codegen_deps` always extend
to descendant packages. `test` and `link` apply to the exact declaring package by
default; add `recursive = True` to extend them to descendants. When the same key
applies at multiple depths, the deepest (closest) declaration wins.

### Recognized keys

| Key | Type | Effect |
|-------------------|----------------------|----------|
| `go_codegen_root` | `bool` | When `True` on an ancestor, `go_src` targets are searched across the whole subtree rooted here instead of only the leaf package. Use when one generator feeds many descendant packages. |
| `go_codegen_deps` | `list[string]` | Explicit codegen target addresses injected into every descendant package's sandbox. For generators not labelled `go_src`. The closest ancestor carrying it wins. |
| `test` | `bool \| struct(...)` | Controls test-target generation and configuration for this package and descendants. See below. |
| `go_codegen_root` | `bool` | When `True` on an ancestor, `go_src` targets are searched across the whole subtree rooted here instead of only the leaf package. Use when one generator feeds many descendant packages. Always applies to descendants, independent of `recursive`. |
| `go_codegen_deps` | `list[string]` | Explicit codegen target addresses injected into every descendant package's sandbox. For generators not labelled `go_src`. The closest ancestor carrying it wins. Always applies to descendants, independent of `recursive`. |
| `test` | `bool \| struct(...)` | Controls test-target generation and configuration. Applies to the exact package by default; add `recursive = True` to extend to descendants. See below. |
| `link` | `struct(...)` | Link settings for a `main` package's `build` (binary) target. Applies to the exact package by default; add `recursive = True` to extend to descendants. See [Link configuration](#link-configuration). |
| `recursive` | `bool` | When `True`, extends this state's `test` and `link` config to all descendant packages. `go_codegen_root` and `go_codegen_deps` are unaffected — they always apply to descendants. |

### Skipping tests

`test = False` disables test-target generation for this package and all
descendants. A deeper `test = True` (or the struct form) re-enables them — the
closest ancestor wins.
`test = False` disables test-target generation for the exact declaring package.
Add `recursive = True` to disable across the whole subtree. A deeper `test = True`
(or the struct form) re-enables them — the closest applicable ancestor wins.

```python title="BUILD"
# Disable tests for this subtree:
# Disable tests for this package only:
provider_state(provider = "go", test = False)

# Disable tests for this package and all descendants:
provider_state(provider = "go", recursive = True, test = False)

# Re-enable in a subdirectory:
provider_state(provider = "go", test = True)
```

### Test environment

The struct form configures the generated `test`/`xtest` run
targets. Unlike the boolean form, it is **package-scoped**: it applies only to
the exact package where the `provider_state` lives — descendants are not
affected. A struct-form state also re-enables tests even when an ancestor set
`test = False`.
The struct form configures the generated `test`/`xtest` run targets. Like the
boolean form, it applies to the exact declaring package by default. Add
`recursive = True` to extend it to descendants. A struct-form state also
re-enables tests even when an ancestor set `test = False`.

```python title="BUILD"
provider_state(
Expand All @@ -347,6 +353,35 @@ provider_state(
| `runtime_pass_env` | `list[string]` | no | Like `pass_env` but excluded from the cache key. |
| `pre_run` | `list[string]` | yes | Shell lines run before the test binary. When non-empty, the target switches from the `exec` driver to the `bash` driver so the lines execute as shell. |

### Link configuration

The `link` struct configures the `build` (binary) target generated for a
`package main`. It applies to the exact declaring package by default; add
`recursive = True` to extend it to descendant packages.

When multiple applicable states carry `link`, their values accumulate
shallow-to-deep: a recursive ancestor's flags, deps, and runtime deps are
collected first, then the package's own.

```python title="BUILD"
provider_state(
provider = "go",
link = {
"flags": ["-X main.version=1.2.3", "-s"],
"deps": ["//embed:assets"],
"runtime_deps": ["//data:config"],
},
)
```

| Field | Type | Hashed | Description |
|----------------|----------------|--------|-------------|
| `flags` | `list[string]` | yes | Extra flags passed verbatim to `go tool link`, inserted before `-o`. Use for `-X` linker vars, stripping flags (`-s`, `-w`), etc. |
| `deps` | `list[string]` | yes | Target addresses staged into the link sandbox as hashed inputs. `flags` can reference their outputs. |
| `runtime_deps` | `list[string]` | no | Target addresses staged with the binary at run time only. Not hashed — they do not affect the cache key. |

Unknown keys in the `link` map are rejected with a clear error naming the unrecognized field.

## Claude Code plugin

`heph-go` is a [Claude Code](https://claude.com/claude-code) plugin focused on Go
Expand Down
Loading