Separate example setup from synthetic test releases

This commit is contained in:
2026-10-10 14:27:47 +00:00
parent c09c7a2ac7
commit 8552f92ddb
10 changed files with 165 additions and 10 deletions

View File

@@ -0,0 +1,54 @@
package main
import (
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
func TestMultiModuleExampleSetupUsesCurrentSourceTool(t *testing.T) {
root := cliRepositoryRoot(t)
repository := newCLIRepository(t)
copyExampleTree(t, filepath.Join(root, "examples", "multi-module"), repository)
const module = "gitea.maximumdirect.net/eric/ReleaseKit"
environment := append(os.Environ(), "GOTOOLCHAIN=local", "GOWORK=off", "GOPROXY=off", "GOSUMDB=off", "GOFLAGS=")
goCommand := func(directory string, args ...string) string {
t.Helper()
command := exec.Command("go", args...)
command.Dir, command.Env = directory, environment
output, err := command.CombinedOutput()
if err != nil {
t.Fatalf("go %q: %v\n%s", args, err, output)
}
return string(output)
}
selections := []struct {
directory, profile, product, version string
}{
{".", "releasekit-root.json", "Example Consumer", "v1.2.3"},
{"integrations/ckconfig", "releasekit-ckconfig.json", "Example Consumer Integration", "v1.2.3"},
{"integrations/core/v2", "releasekit-core-v2.json", "Example Consumer Core v2", "v2.1.0"},
}
for _, selected := range selections {
directory := filepath.Join(repository, filepath.FromSlash(selected.directory))
if selected.directory != "integrations/core/v2" {
writeRepositoryFile(t, repository, selected.directory+"/source.go", "package candidate\n")
}
goCommand(directory, "mod", "edit", "-require="+module+"@v0.0.0", "-replace="+module+"="+root, "-tool="+module+"/cmd/releasekit")
goCommand(directory, "mod", "tidy")
writeRepositoryFile(t, repository, selected.directory+"/docs/releases/"+selected.version+".md", "# "+selected.product+" "+selected.version+"\n\nSource verification fixture.\n")
}
cliGitRun(t, repository, "add", ".")
cliGitRun(t, repository, "commit", "-m", "Select current source in disposable example")
for _, selected := range selections {
output := goCommand(filepath.Join(repository, filepath.FromSlash(selected.directory)), "tool", "releasekit", "check", "--config", selected.profile, selected.version)
if !strings.Contains(output, "is valid") {
t.Fatalf("source-selected check output=%s", output)
}
}
if status := cliGitOutput(t, repository, "status", "--porcelain"); status != "" {
t.Fatalf("source verification changed committed fixture: %s", status)
}
}

View File

@@ -316,6 +316,13 @@ func newWorkflowRepository(t *testing.T, example string) string {
t.Fatal(err)
}
copyExampleTree(t, example, repository)
for _, selection := range []struct{ directory, module string }{
{".", "example.com/multi-module-consumer"},
{"integrations/ckconfig", "example.com/multi-module-consumer/integrations/ckconfig"},
{"integrations/core/v2", "example.com/multi-module-consumer/integrations/core/v2"},
} {
writeRepositoryFile(t, repository, selection.directory+"/go.mod", workflowModuleFile(selection.module, "v0.2.197"))
}
cliGitRun(t, repository, "init", "--initial-branch=main")
cliGitRun(t, repository, "config", "user.name", "ReleaseKit Test")
cliGitRun(t, repository, "config", "user.email", "releasekit@example.test")

View File

@@ -9,12 +9,16 @@ maintainers without adding imports to application or library code.
From the consumer module's root, select the ReleaseKit version to adopt:
```sh
go get -tool gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@v0.2.0
: "${RELEASEKIT_TOOL_VERSION:?Set the released ReleaseKit version to adopt}"
go get -tool "gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@${RELEASEKIT_TOOL_VERSION}"
go mod tidy
go tool releasekit version
```
Replace `v0.2.0` with the intended release. Go records the executable package in
Select a release that implements the API, profile, and workflow you are adopting.
The module-release interface requires a release containing that feature;
pre-feature versions through v0.3.0 use their corresponding historical interface.
Go records the executable package in
a `tool` directive and the module version in a `require` directive. The tool
declaration retains the dependency through `go mod tidy`. Commit the resulting
`go.mod` and `go.sum` changes. To upgrade, repeat the command with the chosen
@@ -38,7 +42,8 @@ Consumers importing the root `releasekit` API or
required imports and select the module version:
```sh
go get gitea.maximumdirect.net/eric/ReleaseKit@v0.2.0
: "${RELEASEKIT_TOOL_VERSION:?Set the released ReleaseKit version to adopt}"
go get "gitea.maximumdirect.net/eric/ReleaseKit@${RELEASEKIT_TOOL_VERSION}"
go mod tidy
```
@@ -52,3 +57,10 @@ supports both tool and ordinary package dependencies. It builds ReleaseKit from
the tagged consumer's module selection, so the committed module files also
govern CI delivery and retries. Registering the CLI as a tool is sufficient for
consumers that use ReleaseKit only for maintainer commands.
Upgrade the module-selected tool and workflow together. For a tag created before
that upgrade, retry with the workflow matching the tool recorded at that tag.
Keep its immutable module files and tag intact. See the
[delivery guide](delivery.md#woodpecker-tag-workflows) for tagged-source bootstrap
and the [example's source verification](../../examples/multi-module/README.md#local-source-verification)
for testing an unreleased checkout in a disposable consumer repository.

View File

@@ -185,6 +185,11 @@ a different toolchain. The tag's `go.mod` must select ReleaseKit as a module
dependency. For CLI-only consumers, use the versioned Go tool dependency
described in the [adoption guide](adoption.md). Ordinary package dependencies
also work with this template.
Select a tool release implementing this workflow's interface before adopting it;
the [adoption guide](adoption.md#ci-adoption) owns coordinated tool/workflow
upgrades. Retries of older tags use the workflow matching their recorded tool.
Configure the Woodpecker repository secret `releasekit_gitea_token`; the
template maps it to `RELEASEKIT_GITEA_TOKEN` for delivery. The repository needs
a `delivery` profile. Page-only and binary behavior both use this template; the

View File

@@ -64,6 +64,13 @@ Update callers, profiles, receipts, and CI declarations together for this
clean interface cutover; compatibility shims and legacy receipt readers are
not provided.
Select this feature's ReleaseKit release in each consumer module before adopting
the new profiles and workflows. Upgrade its tool declaration and workflow
together: pre-feature tools through v0.3.0 require their historical profiles and
flags. Historical tag retries use the workflow matching the tool recorded at
that tag. Preserve the immutable
tag and module files when retrying.
- Set `ModuleDir` in Go requests or `module_dir` in profiles for a nested
module. The selected directory must contain its own `go.mod`; module paths
and release tags are read from that declaration, not inferred from a folder
@@ -102,3 +109,11 @@ For current behavior, see the [API and consumer guides](../consumers/),
[CLI contract](../cli.md), [configuration reference](../config.md),
[Gitea integration](../integrations/gitea.md), and
[ReleaseKit release procedure](../release.md).
## Release preparation
Once this release's version is selected, record it in the maintained multi-module
example's tool and require directives, and move these notes to its release-note
path. Example setup currently selects a compatible version explicitly; disposable
fixtures can verify current source before publication. Synthetic dependency
versions belong to generated test metadata and local fixture proxies.

View File

@@ -293,7 +293,16 @@ coverage.
## Issue 9: Separate synthetic bootstrap versions from maintained examples (P2)
Status: open. Category: broken adoption example and incomplete cutover guidance.
Status: complete. Category: broken adoption example and incomplete cutover guidance.
**Completion:** Maintained module skeletons no longer pin synthetic releases.
Example setup explicitly selects compatible released tooling and documents source
verification in disposable checkouts. Workflow fixtures generate their synthetic
declarations. Current-source tool registration and all three example profiles,
including native version injection, pass offline; mapped launchers/workflows and
tagged-tool retries retain isolated fixtures. Adoption and migration guidance
cover coordinated tool/workflow upgrades and historical retries. The pending
release notes record concrete example pins as normal version-selection work.
**Evidence:** All three maintained
[multi-module declarations](../../examples/multi-module/) require ReleaseKit

View File

@@ -12,6 +12,28 @@ the launcher from that checkout.
The sample modules declare Go 1.26.0, matching the current ReleaseKit consumer
minimum.
## Select the release tool
The module files are setup skeletons. Set `RELEASEKIT_TOOL_VERSION` to a released
ReleaseKit version containing module-release support, then register that tool in
each consumer module before running the launcher or workflow:
```sh
: "${RELEASEKIT_TOOL_VERSION:?Select a ReleaseKit release with module-release support}"
for module_dir in . integrations/ckconfig integrations/core/v2; do
go -C "$module_dir" get -tool "gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit@${RELEASEKIT_TOOL_VERSION}"
go -C "$module_dir" mod tidy
done
```
Review and commit the generated tool, dependency, and checksum declarations.
Release preparation records the chosen compatible version in these maintained
module files. The feature roadmap leaves that release version to release
preparation. The [adoption guide](../../docs/consumers/adoption.md) owns tool
registration and coordinated tool/workflow upgrades.
## Module mapping and publication
`release-modules.tsv` is literal tab-separated text with four columns:
1. Local selector.
@@ -71,3 +93,40 @@ page-only. Before enabling the workflow, configure each selected profile's
`delivery` destination and add the Woodpecker repository secret
`releasekit_gitea_token`; the workflow exposes it as
`RELEASEKIT_GITEA_TOKEN` only in the delivery step.
Retries use the selected tag's module files and matching workflow. Tags whose
tool predates this interface use their corresponding historical workflow.
## Local source verification
For verification before a compatible release is published, copy this example
into a disposable consumer checkout. Set `RELEASEKIT_SOURCE` to the absolute
path of a prepared ReleaseKit checkout, then select its source in those fixture
modules:
```sh
: "${RELEASEKIT_SOURCE:?Set the absolute ReleaseKit checkout path}"
for module_dir in . integrations/ckconfig integrations/core/v2; do
go -C "$module_dir" mod edit \
-require=gitea.maximumdirect.net/eric/ReleaseKit@v0.0.0 \
-replace="gitea.maximumdirect.net/eric/ReleaseKit=$RELEASEKIT_SOURCE" \
-tool=gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit
GOTOOLCHAIN=local GOWORK=off go -C "$module_dir" mod tidy
done
```
Here `v0.0.0` is a fixture placeholder resolved by the local replacement.
Keep these declarations in the disposable checkout. Add representative product
source and each selected product's module-local release note, then commit the
fixture and run the source-selected tool without publishing:
```sh
go tool releasekit check --config releasekit-root.json v1.2.3
go -C integrations/ckconfig tool releasekit check --config releasekit-ckconfig.json v1.2.3
go -C integrations/core/v2 tool releasekit check --config releasekit-core-v2.json v2.1.0
```
These commands use the repository-root profile paths even when invoked from a
child module. The core profile also verifies the native binary and injected
version. Prepared dependencies allow this verification with `GOPROXY=off` and
`GOSUMDB=off`.

View File

@@ -1,5 +1,3 @@
module example.com/multi-module-consumer
go 1.26.0
require gitea.maximumdirect.net/eric/ReleaseKit v0.2.197

View File

@@ -1,5 +1,3 @@
module example.com/multi-module-consumer/integrations/ckconfig
go 1.26.0
require gitea.maximumdirect.net/eric/ReleaseKit v0.2.197

View File

@@ -1,5 +1,3 @@
module example.com/multi-module-consumer/integrations/core/v2
go 1.26.0
require gitea.maximumdirect.net/eric/ReleaseKit v0.2.197