diff --git a/plugins/heph-go/skills/heph-go/references/go-plugin.md b/plugins/heph-go/skills/heph-go/references/go-plugin.md index 6d29636..ee961f9 100644 --- a/plugins/heph-go/skills/heph-go/references/go-plugin.md +++ b/plugins/heph-go/skills/heph-go/references/go-plugin.md @@ -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( @@ -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`. @@ -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: @@ -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 diff --git a/website/docs/plugins/go.md b/website/docs/plugins/go.md index ee98e82..6bd9b3e 100644 --- a/website/docs/plugins/go.md +++ b/website/docs/plugins/go.md @@ -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` | @@ -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( @@ -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