Complete module release documentation

This commit is contained in:
2026-10-10 04:03:42 +00:00
parent b49c1f379e
commit 90559fe01b
18 changed files with 260 additions and 45 deletions

View File

@@ -8,6 +8,13 @@ tagged-source delivery API, and the `version`, `check`, `publish`, `build`,
maintainer procedure and prepared Woodpecker workflow for hosted note-page maintainer procedure and prepared Woodpecker workflow for hosted note-page
delivery are documented. ReleaseKit does not declare binary deliverables. delivery are documented. ReleaseKit does not declare binary deliverables.
Release operations can select one Go module within a repository. The repository
root remains the default; a selected module's declared import path and physical
directory determine its complete Git tag and module-local release note. See the
[candidate check](docs/consumers/check.md),
[publication](docs/consumers/publish.md), and
[multi-module example](examples/multi-module/).
See the [consumer adoption guide](docs/consumers/adoption.md) to add ReleaseKit See the [consumer adoption guide](docs/consumers/adoption.md) to add ReleaseKit
as a versioned Go tool or package dependency, and the as a versioned Go tool or package dependency, and the
[v0.1.0 release note](docs/releases/v0.1.0.md) for the initial baseline. [v0.1.0 release note](docs/releases/v0.1.0.md) for the initial baseline.

View File

@@ -26,7 +26,7 @@ type Candidate struct {
ModulePath string ModulePath string
Tag string Tag string
Commit string Commit string
Version string Version string // selected stable semantic version.
} }
// ReleaseRequest contains the inputs used to validate and optionally build one // ReleaseRequest contains the inputs used to validate and optionally build one
@@ -38,7 +38,7 @@ type ReleaseRequest struct {
// the repository root. // the repository root.
ModuleDir string ModuleDir string
Product string Product string
Version string Version string // stable semantic version, independent of the derived Git tag.
Remote string Remote string
// ExpectedPushURL optionally requires Publish's resolved push URL to match // ExpectedPushURL optionally requires Publish's resolved push URL to match
// this string exactly before validation or tag creation. Check ignores this // this string exactly before validation or tag creation. Check ignores this
@@ -56,8 +56,10 @@ type ReleaseRequest struct {
// preserves the current validation behavior. // preserves the current validation behavior.
type ValidationSpec struct { type ValidationSpec struct {
// SharedFiles adds repository-relative committed files to optional file // SharedFiles adds repository-relative committed files to optional file
// checks. Nil selects the optional defaults; an empty non-nil slice selects // checks. Nil selects the optional root COPYRIGHT, LICENSE, and
// none. Explicit files are checked for presence even when file checks are off. // docs/oss/attribution.md defaults; an empty non-nil slice selects none.
// Explicit files replace the defaults and must exist even when file checks
// are off.
SharedFiles []string SharedFiles []string
Go GoValidationSpec Go GoValidationSpec
// GoFormat checks the formatting of committed regular Go source files. It // GoFormat checks the formatting of committed regular Go source files. It

View File

@@ -51,7 +51,8 @@ type DeliveryRequest struct {
ModuleDir string ModuleDir string
Product string Product string
Version string Version string
// ExpectedTag optionally binds delivery to the full tag that triggered a CI event. // ExpectedTag optionally requires the full CI event tag to match the
// selected module's derived tag before building or making hosted requests.
ExpectedTag string ExpectedTag string
Destination GiteaDestination Destination GiteaDestination
// Build selects binaries to build in temporary storage outside the checkout. // Build selects binaries to build in temporary storage outside the checkout.
@@ -70,8 +71,8 @@ type DeliveryResult struct {
RepositoryDir string RepositoryDir string
ModuleDir string ModuleDir string
ModulePath string ModulePath string
Tag string Tag string // complete derived Git tag.
Version string Version string // selected stable semantic version.
CandidateCommit string CandidateCommit string
ReleaseURL string ReleaseURL string
State DeliveryState State DeliveryState

View File

@@ -9,7 +9,7 @@ The current profile fields are:
| Field | Required | Behavior | | Field | Required | Behavior |
| --- | --- | --- | | --- | --- | --- |
| `product` | Yes | Product name used by release operations. | | `product` | Yes | Product name used by release operations. |
| `module_dir` | No | Repository-relative physical Go module directory; omission selects `.` (the repository root). | | `module_dir` | No | Repository-relative physical Go module directory with its own `go.mod`; omission selects `.` (the repository root). |
| `remote` | No | Selected Git remote; defaults to `origin`. | | `remote` | No | Selected Git remote; defaults to `origin`. |
| `expected_push_url` | No | Exact effective push URL required by `publish`; ignored by local `check`. | | `expected_push_url` | No | Exact effective push URL required by `publish`; ignored by local `check`. |
| `checks` | No | Ordered additional child commands, each with an argument vector and optional environment map. | | `checks` | No | Ordered additional child commands, each with an argument vector and optional environment map. |
@@ -17,6 +17,13 @@ The current profile fields are:
| `build` | No | Optional main package, binary name, and selected `GOOS/GOARCH` target strings. | | `build` | No | Optional main package, binary name, and selected `GOOS/GOARCH` target strings. |
| `delivery` | No | Optional Gitea `base_url`, `owner`, `repository`, and `token_env` settings for tagged-source delivery. | | `delivery` | No | Optional Gitea `base_url`, `owner`, `repository`, and `token_env` settings for tagged-source delivery. |
`module_dir` names the selected module's physical location in the repository;
ReleaseKit reads its declared import path from that module's own `go.mod`. The
physical directory and declared path are distinct: a declared `/v2` module can
live either at `integrations/core` or `integrations/core/v2`, while both use the
same full release tag. Root-only profiles can omit `module_dir` and do not need
a module map.
Each check requires a nonempty `args` array whose first element names the Each check requires a nonempty `args` array whose first element names the
executable. Arguments are passed directly to the child process; ReleaseKit does executable. Arguments are passed directly to the child process; ReleaseKit does
not parse a shell command string. Select a shell explicitly when a check needs not parse a shell command string. Select a shell explicitly when a check needs
@@ -30,10 +37,13 @@ target requires the package and binary name; each target is written as one
The optional `validation` object selects shared checks implemented by ReleaseKit. The optional `validation` object selects shared checks implemented by ReleaseKit.
`validation.shared_files` is a committed file list resolved from the repository `validation.shared_files` is a committed file list resolved from the repository
root. Omission or `null` uses the optional defaults for enabled file checks; root. Omission or `null` uses `COPYRIGHT`, `LICENSE`, and
`[]` selects no shared files. Each explicit file must exist in the candidate, `docs/oss/attribution.md` when present for enabled file checks; `[]` selects no
even when no file checks are enabled. Paths are literal and have no glob shared files. An explicit list replaces those defaults. Each explicit file must
semantics. This field does not enable any checks. exist in the candidate, even when no file checks are enabled. Paths are literal,
repository-relative files with no glob semantics and may select a file outside
the chosen module. ReleaseKit deduplicates them with module inputs by path. This
field does not enable any checks.
`validation.go.race` enables the race detector for the single standard Go test `validation.go.race` enables the race detector for the single standard Go test
suite. `validation.go.full_vet` runs a separate native `go vet` pass after that suite. `validation.go.full_vet` runs a separate native `go vet` pass after that
suite succeeds; ReleaseKit disables test-time vet for that suite to avoid suite succeeds; ReleaseKit disables test-time vet for that suite to avoid
@@ -191,8 +201,10 @@ credentials. An optional `--expected-module` checks a launcher's module
selection against the profile. It runs `go mod download` only when the profile selection against the profile. It runs `go mod download` only when the profile
has selected build targets; source-only delivery does not need application has selected build targets; source-only delivery does not need application
dependencies. Default preparation may access the network and may update dependencies. Default preparation may access the network and may update
`go.sum`. The command takes CI values as arguments, so profile settings remain `go.sum`. For binary tagged delivery, prepare and commit that module's sums
independent of Woodpecker environment variable names. See the before tagging so dependency preparation leaves the tagged checkout clean. The
command takes CI values as arguments, so profile settings remain independent of
Woodpecker environment variable names. See the
[CLI contract](cli.md) for the invocation and exit statuses. [CLI contract](cli.md) for the invocation and exit statuses.
This application dependency preparation is separate from bootstrapping the This application dependency preparation is separate from bootstrapping the

View File

@@ -20,10 +20,11 @@ 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 `go.mod` and `go.sum` changes. To upgrade, repeat the command with the chosen
version and review the module changes. version and review the module changes.
Go tool dependencies require Go 1.24 or later, together with a toolchain that The Go tool dependency feature requires Go 1.24 or later. The current ReleaseKit
satisfies the selected ReleaseKit version and its dependencies. Tools share the module declares a Go 1.26.0 minimum, so use Go 1.26.0 or later for the current
consumer's module graph: their requirements participate in dependency version release. Tool dependencies share the consumer's module graph: their requirements
selection and can raise the consumer module's Go minimum. See the participate in dependency version selection and can raise the consumer module's
Go minimum. See the
[Go tool dependency reference](https://go.dev/ref/mod#go-mod-file-tool). [Go tool dependency reference](https://go.dev/ref/mod#go-mod-file-tool).
Run `go tool releasekit` from within the consumer module to use its selected Run `go tool releasekit` from within the consumer module to use its selected

View File

@@ -21,6 +21,17 @@ if err != nil {
fmt.Println(result.Version, result.Commit) fmt.Println(result.Version, result.Commit)
``` ```
Set `ReleaseRequest.ModuleDir` to select a nested module using a
repository-relative physical directory; omission or `.` selects the root
module. ReleaseKit reads that module's committed `go.mod` and returns its
physical `ModuleDir`, declared `ModulePath`, semantic `Version`, and complete
`Tag` in the candidate and result. A physical `/v2` directory is removed from
the tag prefix only when the declared module path also ends in `/v2`. For
example, both `integrations/core/v2` and `integrations/core` can declare
`example.com/project/integrations/core/v2` and use the tag
`integrations/core/v2.1.0`. The release note lives under the physical module at
`<module>/docs/releases/<version>.md`.
The repository must have a clean index and worktree on `main`, and the selected The repository must have a clean index and worktree on `main`, and the selected
version must be stable `vMAJOR.MINOR.PATCH`. The committed version must be stable `vMAJOR.MINOR.PATCH`. The committed
`docs/releases/<version>.md` note must have a first Markdown H1 containing the `docs/releases/<version>.md` note must have a first Markdown H1 containing the
@@ -79,7 +90,19 @@ standard suite, selected vet/format/distribution checks, or Markdown navigation
checks in `AdditionalChecks` or profile `checks`. Keep release-note rules and checks in `AdditionalChecks` or profile `checks`. Keep release-note rules and
consumer-specific assertions—such as tests of maintained examples—in those consumer-specific assertions—such as tests of maintained examples—in those
product-owned checks. product-owned checks.
ReleaseKit calls `AdditionalChecks` once after shared validation when supplied. The `Candidate` supplies both `RepositoryDir` and `ModuleDir`, plus the declared
`ModulePath`, semantic `Version`, and full `Tag`; use its module directory for
module-local product checks. ReleaseKit calls `AdditionalChecks` once after
shared validation when supplied.
`ValidationSpec.SharedFiles` adds committed, repository-relative files to
ReleaseKit's optional file checks without enabling any checks. A nil slice
selects the optional defaults `COPYRIGHT`, `LICENSE`, and
`docs/oss/attribution.md`, when present; a non-nil empty slice selects none.
Explicit files replace those defaults, must exist even when file checks are
disabled, and may be in another module. Combined inputs are deduplicated by
repository-relative path.
It does not download a different toolchain automatically. If race prerequisites It does not download a different toolchain automatically. If race prerequisites
are unavailable, the `go-test` check fails rather than being skipped; a selected are unavailable, the `go-test` check fails rather than being skipped; a selected
full-vet failure is reported as `go-vet`. The suite uses the Go host target, full-vet failure is reported as `go-vet`. The suite uses the Go host target,

View File

@@ -27,7 +27,7 @@ or hosted content.
```go ```go
err := releasekit.PrepareTaggedCheckout(ctx, releasekit.TaggedCheckoutRequest{ err := releasekit.PrepareTaggedCheckout(ctx, releasekit.TaggedCheckoutRequest{
RepositoryDir: repositoryDir, RepositoryDir: repositoryDir,
Version: version, Tag: "integrations/example/v1.2.3",
ExpectedCommit: ciCommit, ExpectedCommit: ciCommit,
}) })
if err != nil { if err != nil {
@@ -42,11 +42,18 @@ module with workspace discovery disabled and the available compatible local Go
toolchain. toolchain.
The operation may use the network and updates the Go module cache while The operation may use the network and updates the Go module cache while
preserving the caller's proxy, private-module, credential, and cache settings. preserving the caller's proxy, private-module, credential, and cache settings.
If checksums are missing, Go may update `go.sum`; see the If checksums are missing, Go may update `go.sum`. For binary CI delivery, prepare
and commit the selected module's `go.sum` before tagging: delivery verifies the
tagged source remains clean after dependency preparation. See the
[Go Modules Reference](https://go.dev/ref/mod#go-mod-download). Cancellation [Go Modules Reference](https://go.dev/ref/mod#go-mod-download). Cancellation
and command errors are returned. Page-only profiles do not need dependency and command errors are returned. Page-only profiles do not need dependency
preparation. preparation.
Set `TaggedCheckoutRequest.VerifyOnly` when a bootstrap step already fetched and
detached the event tag. This mode checks the exact tag, expected commit, `HEAD`,
and clean worktree without fetching or changing the checkout. Both modes require
the full `Tag` and expected commit.
## Command line ## Command line
Add a Gitea destination to the profile: Add a Gitea destination to the profile:
@@ -199,10 +206,21 @@ without another fetch or checkout. It loads the tagged profile and downloads
application dependencies only when build targets are selected; it builds and application dependencies only when build targets are selected; it builds and
delivers those targets with the note page. Source-only profiles skip application delivers those targets with the note page. Source-only profiles skip application
dependency downloads and binary work. Dependency preparation for binaries may dependency downloads and binary work. Dependency preparation for binaries may
use the network and may update an uncommitted checksum file in the checkout. A use the network. Prepare and commit the selected module's `go.sum` before
tagging; an uncommitted change makes the later delivery source check fail. A
retry still uses the same immutable tag and that tag's module settings, even retry still uses the same immutable tag and that tag's module settings, even
after the default branch selects a newer ReleaseKit version. after the default branch selects a newer ReleaseKit version.
The root-only [`tag-delivery.yml`](../../examples/woodpecker/tag-delivery.yml)
keeps the small default profile and root-module bootstrap. For consumers that
release several modules from one repository, copy the contents of the maintained
[multi-module example](../../examples/multi-module/) to the consumer repository
root and use its [`woodpecker.yml`](../../examples/multi-module/woodpecker.yml),
[`release-modules.tsv`](../../examples/multi-module/release-modules.tsv), and
shared selector. The event tag chooses one row from the tagged checkout; the
profile and physical module must agree, and ReleaseKit verifies the derived tag.
The example covers source-only integration pages and a binary core module.
If the application does not declare ReleaseKit as a module dependency, install If the application does not declare ReleaseKit as a module dependency, install
the executable separately and invoke the same `ci-deliver` command. For the executable separately and invoke the same `ci-deliver` command. For
ReleaseKit's own source workflow, the maintained ReleaseKit's own source workflow, the maintained

View File

@@ -6,6 +6,7 @@ annotated source tag:
```go ```go
result, err := releasekit.Publish(ctx, releasekit.ReleaseRequest{ result, err := releasekit.Publish(ctx, releasekit.ReleaseRequest{
RepositoryDir: "/work/project", RepositoryDir: "/work/project",
ModuleDir: "integrations/example",
Product: "Example", Product: "Example",
Version: "v1.2.3", Version: "v1.2.3",
ExpectedPushURL: "ssh://git.example/owner/example.git", ExpectedPushURL: "ssh://git.example/owner/example.git",
@@ -19,9 +20,22 @@ result, err := releasekit.Publish(ctx, releasekit.ReleaseRequest{
if err != nil { if err != nil {
return err return err
} }
fmt.Println(result.Version, result.CandidateCommit, result.TagObject) fmt.Println(result.ModulePath, result.Version, result.Tag, result.CandidateCommit, result.TagObject)
``` ```
`ModuleDir` is a repository-relative physical module directory; omit it or use
`.` for a root-module release. ReleaseKit reads the selected module's committed
declaration and derives the complete Git tag from its declared module path and
physical location. `Version` remains the stable semantic version. The note is
`<module>/docs/releases/<version>.md`; an on-disk `/v2` directory is part of
the note path but is removed from the tag prefix only when the module path ends
in `/v2`. `PublicationResult` returns the absolute `ModuleDir`, declared
`ModulePath`, complete `Tag`, and existing commit and tag-object evidence.
The optional `ValidationSpec.SharedFiles` selects additional committed files
for enabled file checks. Its nil and empty-slice behavior is described in the
[candidate check guide](check.md#local-candidate-check).
Publication captures a clean candidate on `main`, validates its committed Publication captures a clean candidate on `main`, validates its committed
release note, and checks the selected remote before running candidate checks. release note, and checks the selected remote before running candidate checks.
Set `ExpectedPushURL` to require the effective push destination to match an Set `ExpectedPushURL` to require the effective push destination to match an

View File

@@ -13,10 +13,19 @@ the `Authorization: token …` request header and is not included in errors or
results. The base URL must use HTTP or HTTPS and cannot contain URL credentials, results. The base URL must use HTTP or HTTPS and cannot contain URL credentials,
a query, or a fragment. a query, or a fragment.
The selected module derives a complete tag from its semantic version and The selected module derives a complete tag from its semantic version, declared
physical repository-relative directory. For example, version `v1.2.3` in module path, and physical repository-relative directory. For example, version
`integrations/ckconfig` uses `integrations/ckconfig/v1.2.3`; a root module uses `v1.2.3` in `integrations/ckconfig` uses
`v1.2.3`. The client first reads `integrations/ckconfig/v1.2.3`; a root module uses `v1.2.3`. A `/v2` module
stored at `integrations/core/v2` uses `integrations/core/v2.1.0`; the same
declared module stored at `integrations/core` derives the same tag. ReleaseKit
removes a final physical `/v2` directory from the tag prefix only when the
module declaration has that `/v2` suffix. A module-local note stays at
`<module>/docs/releases/<version>.md`, including a physical `/v2` directory.
Shared license files remain at the repository root. Use the complete derived
tag as the immutable source ref in note links, with paths rooted at the
repository; license footer links target the root `COPYRIGHT`, `LICENSE`, and
`docs/oss/attribution.md` files. The client first reads
`/api/v1/repos/{owner}/{repo}/tags/{tag}` and requires the hosted tag's commit `/api/v1/repos/{owner}/{repo}/tags/{tag}` and requires the hosted tag's commit
SHA to equal the captured source commit. It then reads SHA to equal the captured source commit. It then reads
`/api/v1/repos/{owner}/{repo}/releases/tags/{tag}`. A matching existing page `/api/v1/repos/{owner}/{repo}/releases/tags/{tag}`. A matching existing page

View File

@@ -25,7 +25,7 @@ Go declarations and GoDoc remain the owners of exact exported contracts.
## Module and dependencies ## Module and dependencies
The module is `gitea.maximumdirect.net/eric/ReleaseKit`, with Go language The module is `gitea.maximumdirect.net/eric/ReleaseKit`, with Go language
version `1.25.0`. `go.mod` requires `golang.org/x/mod` and Goldmark for internal version `1.26.0`. `go.mod` requires `golang.org/x/mod` and Goldmark for internal
validation; public facades do not expose either dependency. `go list ./...` validation; public facades do not expose either dependency. `go list ./...`
reports these implemented packages: reports these implemented packages:
@@ -46,6 +46,7 @@ reports these implemented packages:
| `internal/tempdir` | Disposable system temporary storage outside source worktrees. | | `internal/tempdir` | Disposable system temporary storage outside source worktrees. |
| `internal/process` | Cancellable child-process execution, including owned stdin/stdout pipes for serialized exchanges, with per-command environment overlays and removals. | | `internal/process` | Cancellable child-process execution, including owned stdin/stdout pipes for serialized exchanges, with per-command environment overlays and removals. |
| `internal/preparation` | Coordination for expected-commit tag checkout and Go module dependency preparation. | | `internal/preparation` | Coordination for expected-commit tag checkout and Go module dependency preparation. |
| `internal/releaseidentity` | Shared module selection, declaration reading, and semantic-version-to-tag derivation for committed and working-tree operations. |
| `internal/validation` | Shared Go validation with optional race, full-vet, and static package-compilation target selections, formatting, workspace-file and filesystem-replacement checks, per-blob size limits, and selected Markdown destination and fragment checking; `internal/candidate` retains capture, callback sequencing, and local-state rechecks. | | `internal/validation` | Shared Go validation with optional race, full-vet, and static package-compilation target selections, formatting, workspace-file and filesystem-replacement checks, per-blob size limits, and selected Markdown destination and fragment checking; `internal/candidate` retains capture, callback sequencing, and local-state rechecks. |
| `internal/publish` | Publication guards, one validation run, annotated tag creation, push, and recovery state. | | `internal/publish` | Publication guards, one validation run, annotated tag creation, push, and recovery state. |
| `internal/runtimeinfo` | Injected version selection and cached fallback metadata lookup for the runtime facade. | | `internal/runtimeinfo` | Injected version selection and cached fallback metadata lookup for the runtime facade. |
@@ -90,8 +91,9 @@ not a separate release matrix:
| Cross-builds, version smoke checks, module paths, empty target sets, and partial outputs | `releasekit.Build`, `internal/build`, `internal/artifact`, `internal/tempdir`, `buildinfo` | `TestBuildCreatesSelectedTargetsAndInjectsVersion`, `TestBuildUsesNestedWorkingTreeModuleAndModuleRelativeOutput`, `TestBuildResolvesDirtyWorkingTreeDeclaration`, `TestBuildWithNoTargetsDoesNotInvokeCompiler`, `TestBuildReturnsPartialArtifactsAfterTargetFailure`, `TestNormalizeSettingsKeepsBuildInputsAndNormalizesTargets`, `TestOutsideFallsBackWhenTemporaryDirectoryIsInsideWorktree` | | Cross-builds, version smoke checks, module paths, empty target sets, and partial outputs | `releasekit.Build`, `internal/build`, `internal/artifact`, `internal/tempdir`, `buildinfo` | `TestBuildCreatesSelectedTargetsAndInjectsVersion`, `TestBuildUsesNestedWorkingTreeModuleAndModuleRelativeOutput`, `TestBuildResolvesDirtyWorkingTreeDeclaration`, `TestBuildWithNoTargetsDoesNotInvokeCompiler`, `TestBuildReturnsPartialArtifactsAfterTargetFailure`, `TestNormalizeSettingsKeepsBuildInputsAndNormalizesTargets`, `TestOutsideFallsBackWhenTemporaryDirectoryIsInsideWorktree` |
| Page-only and managed or prebuilt binary delivery | `releasekit.Deliver`, `internal/delivery`, `internal/gitea`, CLI | `TestDeliverPageOnlySkipsBuildAndHostedAssets`, `TestDeliverUsesCommittedModuleIdentityForSeparatePages`, `TestDeliverRejectsPrebuiltArtifactsForAnotherModuleBeforeHostedRequests`, `TestDeliverManagedBuildUploadsArtifactsAndCleansTemporaryOutput`, `TestDeliverBinaryConsumerWithBuildinfoAndSelectedTargets`, `TestDeliverPrebuiltArtifactsRemainCallerOwned`, `TestDeliverRejectsSameSizePrebuiltTamperingBeforeHostedWrites`, `TestDeliverManagedBuildFailureCleansTemporaryOutputBeforeHostedWrites`, `TestDeliverManagedBuildCancellationCleansTemporaryOutput`, `TestDeliverBuildsTaggedArtifactsAndReusesAssets`, `TestDeliverRejectsTamperedAssetsAndStaleReceiptBeforeRemoteWrites`, `TestEnsureReleaseEscapesSlashContainingTag` | | Page-only and managed or prebuilt binary delivery | `releasekit.Deliver`, `internal/delivery`, `internal/gitea`, CLI | `TestDeliverPageOnlySkipsBuildAndHostedAssets`, `TestDeliverUsesCommittedModuleIdentityForSeparatePages`, `TestDeliverRejectsPrebuiltArtifactsForAnotherModuleBeforeHostedRequests`, `TestDeliverManagedBuildUploadsArtifactsAndCleansTemporaryOutput`, `TestDeliverBinaryConsumerWithBuildinfoAndSelectedTargets`, `TestDeliverPrebuiltArtifactsRemainCallerOwned`, `TestDeliverRejectsSameSizePrebuiltTamperingBeforeHostedWrites`, `TestDeliverManagedBuildFailureCleansTemporaryOutputBeforeHostedWrites`, `TestDeliverManagedBuildCancellationCleansTemporaryOutput`, `TestDeliverBuildsTaggedArtifactsAndReusesAssets`, `TestDeliverRejectsTamperedAssetsAndStaleReceiptBeforeRemoteWrites`, `TestEnsureReleaseEscapesSlashContainingTag` |
| Tagged checkout and build dependency preparation | `releasekit.PrepareTaggedCheckout`, `releasekit.PrepareBuildDependencies`, `internal/preparation`, `internal/git`, `internal/gotool` | `TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches`, `TestPrepareTaggedCheckoutRejectsWrongCommitBeforeCheckout`, `TestPrepareTaggedCheckoutReportsLocalCheckoutConflict`, `TestPrepareTaggedCheckoutReportsConflictingLocalTag`, `TestPrepareBuildDependenciesUsesSelectedModuleDirectory`, `TestPrepareBuildDependenciesPreservesPreparationEnvironment`, `TestPrepareBuildDependenciesPropagatesCommandFailure`, `TestPrepareBuildDependenciesPropagatesCancellation` | | Tagged checkout and build dependency preparation | `releasekit.PrepareTaggedCheckout`, `releasekit.PrepareBuildDependencies`, `internal/preparation`, `internal/git`, `internal/gotool` | `TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches`, `TestPrepareTaggedCheckoutRejectsWrongCommitBeforeCheckout`, `TestPrepareTaggedCheckoutReportsLocalCheckoutConflict`, `TestPrepareTaggedCheckoutReportsConflictingLocalTag`, `TestPrepareBuildDependenciesUsesSelectedModuleDirectory`, `TestPrepareBuildDependenciesPreservesPreparationEnvironment`, `TestPrepareBuildDependenciesPropagatesCommandFailure`, `TestPrepareBuildDependenciesPropagatesCancellation` |
| Shared module identity and tag derivation | `internal/releaseidentity`, `internal/candidate`, `internal/build`, `internal/delivery` | `TestDeriveUsesModuleDeclarationAndPhysicalLayout`, `TestCommittedAndWorkingTreeDeclarationsUseTheirOwnSources`, `TestSelectedNestedModuleDoesNotRequireRootDeclaration`, `TestBuildResolvesDirtyWorkingTreeDeclaration`, `TestDeliverUsesCommittedModuleIdentityForSeparatePages` |
| Page, manifest, asset comparison, and additive retry outcomes | `internal/gitea` | `TestEnsureReleaseCreatesMissingPageFromCommittedNote`, `TestInspectAssetsDetectsSameNameAndSizeWithDifferentBytes`, `TestUploadMissingPartialFailureThenRerunOnlyMissingAssets` | | Page, manifest, asset comparison, and additive retry outcomes | `internal/gitea` | `TestEnsureReleaseCreatesMissingPageFromCommittedNote`, `TestInspectAssetsDetectsSameNameAndSizeWithDifferentBytes`, `TestUploadMissingPartialFailureThenRerunOnlyMissingAssets` |
| CLI profiles and prepared Woodpecker sequences | `cmd/releasekit`, `cmd/releasekit/internal/cli`, `examples/woodpecker/` | `TestLoadSettingsRejectsInvalidProfiles`, `TestWoodpeckerTagDeliveryTemplate`, `TestWoodpeckerTagDeliveryUsesTaggedModuleVersion`, `TestWoodpeckerSourceDeliveryTemplateSelfBootstraps`, `TestReleaseKitSourceDeliveryWorkflowFromTaggedCheckout` | | CLI profiles and prepared Woodpecker sequences | `cmd/releasekit`, `cmd/releasekit/internal/cli`, `examples/woodpecker/`, `examples/multi-module/` | `TestLoadSettingsRejectsInvalidProfiles`, `TestWoodpeckerTagDeliveryTemplate`, `TestWoodpeckerTagDeliveryUsesTaggedModuleVersion`, `TestWoodpeckerSourceDeliveryTemplateSelfBootstraps`, `TestReleaseKitSourceDeliveryWorkflowFromTaggedCheckout`, `TestMultiModuleSelectorMapsSelectorsAndTags`, `TestMultiModuleLauncherUsesSelectedModuleAndProfile`, `TestMultiModuleWoodpeckerDelivery` |
Run the complete suite with `go test ./...`. The public API and import boundary Run the complete suite with `go test ./...`. The public API and import boundary
check is `go run ./internal/apicheck`. Local HTTP and Git fixtures exercise check is `go run ./internal/apicheck`. Local HTTP and Git fixtures exercise

View File

@@ -27,6 +27,19 @@ on parse or inspection errors. It runs before product checks and build callbacks
`Request.ReadCandidateTree` lets selected file checks request candidate `Request.ReadCandidateTree` lets selected file checks request candidate
contents; the Go-only path does not enumerate the tree. contents; the Go-only path does not enumerate the tree.
## Selected validation inputs
`CandidateTree` keeps the full committed repository lookup separate from the
ordered file input set. The selected module's committed regular-file inputs
exclude independently released nested modules, while vendored contents stay
in scope. Explicit shared-file selections are normalized from repository-root
paths, added as individual files, and deduplicated with module inputs by path.
File-size exclusions are normalized from the selected module directory. Link
resolution can still inspect a committed destination outside the selected input
set without adding that destination's content to the checks. The public
selection, nil/empty behavior, and profile path bases belong to the
[configuration reference](../config.md) and the root facade's GoDoc.
The workspace-file check uses that same candidate inventory and reports blob The workspace-file check uses that same candidate inventory and reports blob
entries named go.work or go.work.sum, including nested paths and symlink blobs. entries named go.work or go.work.sum, including nested paths and symlink blobs.
It does not read workspace contents or depend on the workspace selected for Go It does not read workspace contents or depend on the workspace selected for Go

View File

@@ -28,16 +28,12 @@ The maintained [source-delivery image](../examples/woodpecker/releasekit-source-
and [consumer template image](../examples/woodpecker/tag-delivery.yml) follow the and [consumer template image](../examples/woodpecker/tag-delivery.yml) follow the
chosen build toolchain; update them together when that selection changes. chosen build toolchain; update them together when that selection changes.
The current consumer minimum is declared in [go.mod](../go.mod). When preparing The current consumer minimum is Go 1.26.0, declared in [go.mod](../go.mod).
a release that raises it to Go 1.26, the normal declaration is: Keep it for a release unless release preparation deliberately selects a newer
series under the [Go support policy](policy/release.md#consumer-minimum-and-release-toolchain).
```sh When increasing it, update `go.mod` to the first stable version of the selected
go mod edit -go=1.26.0 series, or to a higher patch when a dependency or specific fix requires one.
``` Make module changes before committing the candidate. Minimum increases must fit the
Retain any higher patch minimum required by dependencies or a specific fix.
Make module changes before committing the candidate. A release preserving the
existing minimum keeps its current declaration. Minimum increases must fit the
[compatibility policy](policy/release.md#versioning-and-compatibility); before [compatibility policy](policy/release.md#versioning-and-compatibility); before
v1.0.0, an increase belongs in a minor release. v1.0.0, an increase belongs in a minor release.

View File

@@ -1,6 +1,6 @@
# Implementation plan: individual Go module releases # Implementation plan: individual Go module releases
Status: ready for implementation. Status: complete; all 15 stages implemented and locally verified.
## Objective and authority ## Objective and authority
@@ -756,6 +756,17 @@ evidence describe the complete implemented feature.
record the full-suite and compiled API check results, and confirm that the record the full-suite and compiled API check results, and confirm that the
implemented examples and canonical documentation agree with the current API. implemented examples and canonical documentation agree with the current API.
**Completed:** Updated facade GoDoc, consumer and CLI/configuration guidance,
Gitea and internal ownership documents, recovery guidance, and maintained
examples for module selection, full tags, path bases, shared files, preparation,
and receipt ownership. Added pending next-release notes with migration guidance
and corrected the current Go minimum facts. Audited acceptance coverage against
the stage-owned tests and reviewed ReleaseKit's root release procedure against
the adopted release policy; no new release gates were added. Verified
`go test ./...`, `go run ./internal/apicheck`, local links and heading fragments
in 13 changed Markdown documents, multi-module shell/config/module syntax, and
`git diff --check`.
### Acceptance coverage audit ### Acceptance coverage audit
| Requirement | Primary stage/evidence owner | | Requirement | Primary stage/evidence owner |

View File

@@ -0,0 +1,100 @@
# Pending notes for the next release
Status: pending release preparation. This feature does not select a release
version or move this draft to `docs/releases/<version>.md`.
## Release individual Go modules
ReleaseKit operations can now select one Go module within a Git repository.
Omitted module selection retains the repository-root default. A selected module
is identified by both its repository-relative physical directory and its own
declared module path. ReleaseKit derives a semantic version's complete Git tag
from that identity, including Go's `/v2` major-version convention. For example,
`v2.1.0` for a module declared as `example.com/project/integrations/core/v2`
uses `integrations/core/v2.1.0`, whether the module is physically stored at
`integrations/core` or `integrations/core/v2`. Its release note stays at the
physical module's `docs/releases/v2.1.0.md` path.
The public `Check`, `Publish`, `Build`, and `Deliver` requests add `ModuleDir`;
results expose the resolved module directory, declared module path, and complete
tag alongside existing commit and outcome evidence. `Version` remains the
stable semantic version used in note titles, binary version output, and asset
names. Git publication and hosted delivery use the complete tag. Product
commands receive both repository and module paths, and candidate callbacks
receive the module identity.
`ValidationSpec.SharedFiles` and profile `validation.shared_files` allow a
repository-relative list of committed shared files to join optional file
checks. Omission or `null` selects the available root `COPYRIGHT`, `LICENSE`,
and `docs/oss/attribution.md` defaults; an explicit list replaces those
defaults, and `[]` selects none. Explicit files must exist even when file
checks are disabled. This selection does not enable a check.
Profiles add `module_dir` for physical module selection. The CLI's `ci-deliver`
now takes a full Git `TAG`; its final path component supplies the semantic
version. The optional `--prepared` mode verifies an already prepared checkout
without fetching or checking it out again. `--expected-module` binds a mapped
launcher selection to the selected profile. The public tagged-checkout request
renames `Version` to `Tag` and adds `VerifyOnly`; dependency preparation now
takes a `DependencyPreparationRequest` with repository and module directories.
`DeliveryRequest.ExpectedTag` binds delivery to the exact CI event tag before
building artifacts or contacting Gitea.
The private `.releasekit-build.json` receipt now requires schema version 1 and
binds artifacts to the module directory, declared module path, semantic
version, complete tag, source commit, normalized build settings, and artifact
declarations. Older and unversioned receipts are rejected; rebuild with the
updated `build` command before using `deliver --assets DIR`.
The maintained [multi-module example](../../examples/multi-module/) shares a
four-column `release-modules.tsv` and POSIX selector between its local launcher
and mapped Woodpecker workflow. The workflow verifies and detaches the triggering
tag before reading the mapping, profile, module files, or ReleaseKit version.
Retries therefore use the original tagged source after the default branch
changes. Root-only consumers can keep the ordinary profile and the simpler
[root tag workflow](../../examples/woodpecker/tag-delivery.yml) without a map.
## Consumer migration
Update callers, profiles, receipts, and CI declarations together for this
clean interface cutover; compatibility shims and legacy receipt readers are
not provided.
- 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
name. Keep `Version` as a semantic version in ordinary commands and API calls.
- Update reads of result identity to use `ModuleDir`, `ModulePath`, and `Tag`
where needed. Product commands can use `RELEASEKIT_REPOSITORY_DIR` and
`RELEASEKIT_MODULE_DIR` to distinguish repository-level work from
module-local checks.
- Replace `TaggedCheckoutRequest.Version` with the complete `Tag`. Set
`VerifyOnly` when a bootstrap step already verified and detached the event
checkout. Change `PrepareBuildDependencies` calls to pass a
`DependencyPreparationRequest`.
- Add `module_dir` and, when needed, `validation.shared_files` to profiles.
Recheck profile-relative and repository-relative paths. Prepare and commit
each binary module's `go.sum` before tagging so dependency preparation leaves
the tagged source clean for delivery verification.
- Change `ci-deliver VERSION` invocations to pass the full event `TAG` and
required `--commit OID`. Maintained bootstraps should use `--prepared` after
verifying the tag and commit. A mapped launcher should pass
`--expected-module DIR`; the profile remains the source of selection.
- Regenerate existing build receipts with the new `build` command before
prebuilt delivery. Do not edit old receipts into the new format.
- Root-module validation now excludes independently released nested modules
from module-scoped file checks. Run a nested module's checks from that module
when it is the release unit. Nested module fixtures remain available to the
parent module's product tests.
ReleaseKit's current consumer minimum remains Go 1.26.0. Root-module releases
retain their existing note path, unprefixed tags, profile defaults, and small
root-only workflow. A successful push of the intended source tag remains the
source-release completion point; hosted page and asset delivery remains
asynchronous and may be retried from the same immutable tag. No live-service,
deployment, or consumer-rollout gate is introduced.
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).

View File

@@ -9,6 +9,9 @@ Copy the contents of this directory into a consumer repository root, keeping
the listed module directories and profile paths at those locations, then run the listed module directories and profile paths at those locations, then run
the launcher from that checkout. the launcher from that checkout.
The sample modules declare Go 1.26.0, matching the current ReleaseKit consumer
minimum.
`release-modules.tsv` is literal tab-separated text with four columns: `release-modules.tsv` is literal tab-separated text with four columns:
1. Local selector. 1. Local selector.
@@ -64,4 +67,7 @@ the literal event tag before selecting the module, copies that module's metadata
outside the checkout, and builds the ReleaseKit version selected there. It then outside the checkout, and builds the ReleaseKit version selected there. It then
uses `ci-deliver --prepared` with the mapped profile and expected physical module. uses `ci-deliver --prepared` with the mapped profile and expected physical module.
The `core-v2` profile demonstrates binary delivery; the other profiles are The `core-v2` profile demonstrates binary delivery; the other profiles are
page-only. 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.

View File

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

View File

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

View File

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