Finish publication recovery workflow
This commit is contained in:
55
docs/cli.md
55
docs/cli.md
@@ -1,6 +1,6 @@
|
||||
# Command line
|
||||
|
||||
ReleaseKit currently provides six commands. The exit statuses below belong
|
||||
ReleaseKit currently provides eight commands. The exit statuses below belong
|
||||
to the native executable. `go run` examples are convenient for source execution,
|
||||
but the Go driver maps a nonzero child exit status to 1. Use the built executable
|
||||
or `./scripts/release` for publication when distinct statuses are needed.
|
||||
@@ -75,7 +75,7 @@ Unsupported argument sequences print usage to standard error.
|
||||
Publish a source tag:
|
||||
|
||||
```sh
|
||||
go run ./cmd/releasekit publish [--repo DIR] [--config FILE] [--expected-module DIR] VERSION
|
||||
go run ./cmd/releasekit publish [--repo DIR] [--config FILE] [--expected-module DIR] [--record-dir DIR] VERSION
|
||||
```
|
||||
|
||||
`publish` reads the same product, remote, validation, and additional-check
|
||||
@@ -138,13 +138,62 @@ mismatches fail during preflight before Go validation or tag creation. Git URL
|
||||
rewrites are resolved first, and the push URL is used when fetch and push URLs
|
||||
differ. `check` ignores this field.
|
||||
|
||||
The command automatically saves available publication evidence in the repository's
|
||||
private attempt store. Use `--record-dir DIR` to select another directory; a
|
||||
relative override is resolved from the source repository root. Standard error
|
||||
reports the absolute saved record path or a recording warning separately from
|
||||
the publication result. Recording failure does not change publication status.
|
||||
When publication fails and a record was saved, the CLI also prints a copyable
|
||||
`reconcile --record` command for that exact record. The command uses the running
|
||||
executable's absolute path, so it remains usable when the executable is not on
|
||||
`PATH`; if that executable is no longer available, use another supported
|
||||
ReleaseKit CLI.
|
||||
|
||||
The command returns status 0 for confirmed publication, 1 for a known
|
||||
publication failure or conflict, 2 for usage, profile, or invalid-version
|
||||
errors, and 3 when the push outcome remains unknown. Unknown status must be
|
||||
resolved against the authoritative remote before retrying. The
|
||||
resolved with the explicit-record recovery operation below before retrying. The
|
||||
[maintainer procedure](release.md) selects the repository profile and gives
|
||||
the source-release workflow.
|
||||
|
||||
## Recover a saved publication attempt or discover local attempts
|
||||
|
||||
```sh
|
||||
releasekit reconcile --record FILE [--json]
|
||||
releasekit publication-attempts [--repo DIR] [--record-dir DIR] [--json]
|
||||
```
|
||||
|
||||
`reconcile` requires one explicitly selected record and reads a relative `FILE`
|
||||
from the invoking directory. It observes the endpoint and tag stored in that
|
||||
record; it does not load a profile, inspect the current candidate or local tag,
|
||||
run checks, or change repository state. `publication-attempts` lists records in
|
||||
the selected store without querying remotes or choosing an attempt. An omitted
|
||||
`--repo` means the current directory. Its relative `--record-dir` is resolved
|
||||
from the selected repository root; an absolute directory can be listed outside
|
||||
a checkout. The selected directory must already exist. Discovery reports usable
|
||||
records and per-record diagnostics together when some records cannot be read.
|
||||
|
||||
By default, both operations print human-readable output. `--json` writes one
|
||||
structured document to standard output after valid arguments, including for
|
||||
reconciliation and discovery failures. Recovery does not run candidate checks
|
||||
or make hosted delivery requests. It reads the record's captured endpoint, while
|
||||
using current supported transport settings for its recorded remote name.
|
||||
|
||||
| Recovery command result | Status |
|
||||
| --- | --- |
|
||||
| Reconciliation observes the intended publication | 0 |
|
||||
| Reconciliation observes absence or conflict | 1 |
|
||||
| Reconciliation cannot read or decode the selected record, or has an invocation error | 2 |
|
||||
| Reconciliation remains unknown, including missing evidence or cancellation | 3 |
|
||||
| Discovery completes without record diagnostics, including an existing empty store | 0 |
|
||||
| Discovery is incomplete or fails, including cancellation | 1 |
|
||||
| Discovery argument or usage error | 2 |
|
||||
|
||||
The CLI JSON schema and safe evidence fields are documented in the
|
||||
[publication record format](integrations/publication-records.md). Recovery
|
||||
guidance for storage, older evidence, and retry decisions is in the
|
||||
[maintainer procedure](release.md#resolve-publication-failures).
|
||||
|
||||
Build selected application targets:
|
||||
|
||||
```sh
|
||||
|
||||
@@ -123,3 +123,53 @@ against the captured endpoint before retrying; see the [maintainer procedure](..
|
||||
for the recovery steps. The result's endpoint is the exact URL and can contain
|
||||
credentials; handle it accordingly. The [CLI contract](../cli.md) documents
|
||||
command output and exit statuses.
|
||||
|
||||
## Retain and reconcile publication evidence
|
||||
|
||||
`Publish` automatically attempts to save one private record for each invocation.
|
||||
The default store is under the repository's Git common directory, so linked
|
||||
worktrees share it. `ReleaseRequest.PublicationRecordDir` can override the
|
||||
directory; relative overrides resolve from the source repository root. The CLI
|
||||
equivalent is `publish --record-dir DIR`. ReleaseKit creates its owned storage
|
||||
directories privately and creates record files with owner-only permissions;
|
||||
existing directory permissions are left as they are. The caller owns storage
|
||||
retention and removal.
|
||||
|
||||
The saved endpoint is retained exactly for later observation and may include
|
||||
credentials. Treat records, `PublicationEvidence`, and `PublicationResult` as
|
||||
sensitive. Store overrides in a location with suitable access controls, avoid
|
||||
printing raw endpoint values, and remove records when their recovery value has
|
||||
expired. Diagnostic errors and CLI output apply credential redaction; the
|
||||
private record and typed evidence preserve the raw endpoint.
|
||||
|
||||
Recording failure is reported in `PublicationResult.RecordError`, separately
|
||||
from `Publish`'s return error and publication state. A successful push remains
|
||||
successful if storage fails, but the saved handoff is unavailable. Callers can
|
||||
still pass `result.Evidence` directly to `ReconcilePublication` when it contains
|
||||
the required identity. For example:
|
||||
|
||||
```go
|
||||
func observe(ctx context.Context, result releasekit.PublicationResult) (releasekit.PublicationReconciliationResult, error) {
|
||||
return releasekit.ReconcilePublication(ctx, result.Evidence)
|
||||
}
|
||||
```
|
||||
|
||||
The evidence is populated as publication identity becomes available, including
|
||||
partial evidence on some earlier failures. An abrupt process termination before
|
||||
the save point can leave no record; removed storage also removes the handoff.
|
||||
Records from older attempts may lack the tag object, endpoint, or other identity
|
||||
needed for a conclusive observation.
|
||||
|
||||
Use `LoadPublicationEvidence(path)` to read one explicit record,
|
||||
`ListPublicationAttempts(ctx, request)` to discover readable records and
|
||||
per-record diagnostics in a local directory, or `ReconcilePublication(ctx,
|
||||
evidence)` to observe a selected endpoint. Listing does not query remotes, and
|
||||
neither listing nor reconciliation changes saved records. Recovery does not
|
||||
infer the attempt from current HEAD, local tags, module files, or profiles.
|
||||
`ReconcilePublication` returns a nil error for a completed `published`,
|
||||
`not_published`, or `conflict` observation; unresolved `unknown` results include
|
||||
a typed error that retains the underlying cause. See the
|
||||
[GoDoc](../../recovery.go) for the exported fields and error kinds, the
|
||||
[CLI guide](../cli.md) for command statuses, and the
|
||||
[record format guide](../integrations/publication-records.md) for supported
|
||||
stored and structured formats.
|
||||
|
||||
111
docs/integrations/publication-records.md
Normal file
111
docs/integrations/publication-records.md
Normal file
@@ -0,0 +1,111 @@
|
||||
# Publication records and recovery output
|
||||
|
||||
This guide describes the supported private publication-record envelope and the
|
||||
versioned JSON documents emitted by the recovery CLI. The
|
||||
[publication consumer guide](../consumers/publish.md) owns storage placement,
|
||||
permissions, retention, and sensitive-data handling. The
|
||||
[CLI reference](../cli.md) owns command behavior, path selection, and exit
|
||||
statuses; the exported Go contract is documented in [GoDoc](../../recovery.go).
|
||||
|
||||
## Private attempt record
|
||||
|
||||
Each saved attempt is one complete JSON document with this versioned envelope:
|
||||
|
||||
```json
|
||||
{
|
||||
"format_version": 1,
|
||||
"evidence": {
|
||||
"repository_dir": "/work/project",
|
||||
"module_dir": "/work/project",
|
||||
"module_path": "example.com/project",
|
||||
"version": "v1.2.3",
|
||||
"tag": "v1.2.3",
|
||||
"candidate_commit": "<full Git object ID>",
|
||||
"tag_object": "<full Git object ID>",
|
||||
"endpoint": "ssh://git.example/owner/project.git",
|
||||
"remote": "origin",
|
||||
"recorded_at": "2026-11-02T12:00:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The format version is an integer. Evidence fields may be absent when publication
|
||||
stopped before they were captured; loading preserves that partial evidence and
|
||||
does not fill fields from the current checkout. Additional fields in a
|
||||
supported version are ignored. A missing or unsupported version, malformed or
|
||||
multiple JSON documents, or fields with invalid structural types are reported
|
||||
as record-format errors. The codec supports version 1; no migration from an
|
||||
unsupported version is performed.
|
||||
|
||||
The `endpoint` value is stored exactly as captured and may contain credentials.
|
||||
Private records are sensitive. Do not copy them into public logs or source
|
||||
control. For their location, permissions, and lifecycle, see the
|
||||
[publication consumer guide](../consumers/publish.md#retain-and-reconcile-publication-evidence).
|
||||
|
||||
## Recovery CLI JSON
|
||||
|
||||
After valid command arguments, `--json` emits one JSON document to standard
|
||||
output for both successful and failed recovery operations. Each document has
|
||||
`schema_version: 1` and a `command` name. These are CLI presentation documents,
|
||||
not private attempt records or a Go serialization of public structs.
|
||||
|
||||
`reconcile` includes `record_path`, safe `evidence`, and `state` when a record
|
||||
was read. Available `observed_tag_object` and `observed_commit` fields are
|
||||
included when present. A `diagnostic` is included for unresolved observation
|
||||
or record loading failure. Loading failure omits evidence, state, and observed
|
||||
IDs.
|
||||
|
||||
`publication-attempts` includes `record_dir`, an `attempts` array with each
|
||||
`record_path` and safe `evidence`, and a `diagnostics` array. A top-level
|
||||
`diagnostic` describes enumeration or cancellation failure. Both arrays are
|
||||
present when empty so consumers can decode the same shape for empty stores.
|
||||
|
||||
For example, an unresolved reconciliation can have this shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"command": "reconcile",
|
||||
"record_path": "/private/attempt-abc.json",
|
||||
"evidence": {
|
||||
"repository_dir": "/work/project",
|
||||
"module_path": "example.com/project",
|
||||
"version": "v1.2.3",
|
||||
"tag": "v1.2.3",
|
||||
"candidate_commit": "<full Git object ID>",
|
||||
"tag_object": "<full Git object ID>",
|
||||
"endpoint": "ssh://git.example/owner/project.git",
|
||||
"remote": "origin"
|
||||
},
|
||||
"state": "unknown",
|
||||
"diagnostic": {
|
||||
"kind": "remote_observation",
|
||||
"message": "<credential-safe diagnostic>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A discovery document always contains both arrays, including for an empty store:
|
||||
|
||||
```json
|
||||
{
|
||||
"schema_version": 1,
|
||||
"command": "publication-attempts",
|
||||
"record_dir": "/private/publication-attempts",
|
||||
"attempts": [],
|
||||
"diagnostics": []
|
||||
}
|
||||
```
|
||||
|
||||
CLI evidence uses the private record's snake-case field names. Endpoint strings
|
||||
in CLI output are credential-redacted; the private record and typed
|
||||
`PublicationEvidence` retain the exact endpoint. A diagnostic contains `kind`
|
||||
and safe `message`, with `record_path` and `missing_fields` when applicable.
|
||||
Raw Go errors and private record contents are not emitted as JSON fields.
|
||||
|
||||
Consumers should select attempts by their returned record paths and evidence.
|
||||
The listing order is deterministic by path, not a recommendation to choose the
|
||||
first or newest attempt. Unknown fields may be added in later CLI schema
|
||||
versions; reject unsupported `schema_version` values rather than interpreting
|
||||
them as version 1. See the [CLI reference](../cli.md#recover-a-saved-publication-attempt-or-discover-local-attempts)
|
||||
for invocation and status behavior.
|
||||
@@ -11,12 +11,14 @@ two Go facades and a command-line interface:
|
||||
- `buildinfo` is the small runtime facade. `Version` reports the injected
|
||||
application version, the main-module version when available, or `dev`.
|
||||
- `cmd/releasekit` is the executable interface. Its `version`, `check`,
|
||||
`publish`, `build`, `deliver`, and `ci-deliver` commands adapt profiles and
|
||||
command output to the supported library operations.
|
||||
`publish`, `reconcile`, `publication-attempts`, `build`, `deliver`, and
|
||||
`ci-deliver` commands adapt profiles and command output to the supported
|
||||
library operations.
|
||||
|
||||
See the [CLI contract](../cli.md), [configuration reference](../config.md),
|
||||
[candidate check guide](../consumers/check.md),
|
||||
[source publication guide](../consumers/publish.md),
|
||||
[publication record format](../integrations/publication-records.md),
|
||||
[build guide](../consumers/build.md),
|
||||
[delivery guide](../consumers/delivery.md), and
|
||||
[runtime version guide](../consumers/runtime-version.md) for task-oriented use.
|
||||
@@ -49,7 +51,7 @@ reports these implemented packages:
|
||||
| `internal/preparation` | Coordination for expected-commit tag checkout and Go module dependency preparation. |
|
||||
| `internal/releaseidentity` | Committed-object and working-tree module selection, declaration reading, and semantic-version-to-tag derivation. |
|
||||
| `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, pre-push evidence recording, saved-attempt discovery, later observation, and recovery state. |
|
||||
| `internal/runtimeinfo` | Injected version selection and cached fallback metadata lookup for the runtime facade. |
|
||||
| `internal/versioncontract` | Shared stable-version rules and linker-symbol identity. |
|
||||
|
||||
@@ -75,6 +77,18 @@ it does not consult neighboring files or traverse submodule checkouts.
|
||||
See the [shared validation guide](validation.md) for checker, Go command, and
|
||||
candidate-file integration mechanics.
|
||||
|
||||
Publication records and recovery follow a separate path from candidate
|
||||
validation. `internal/publish` captures and saves attempt evidence before the
|
||||
tag push, lists local records, and observes explicitly selected evidence through
|
||||
`internal/git`; the root facade owns the reusable Go evidence and result types.
|
||||
The CLI's `reconcile` and `publication-attempts` commands load, present, and
|
||||
select records without loading a profile or choosing an attempt automatically.
|
||||
These operations do not rerun candidate checks or hosted delivery and do not
|
||||
change local or remote state. The [publication consumer guide](../consumers/publish.md)
|
||||
owns storage and API use; the [record format guide](../integrations/publication-records.md)
|
||||
owns the private and CLI JSON formats; the [CLI contract](../cli.md) owns command
|
||||
semantics and statuses.
|
||||
|
||||
The root facade selects the backend explicitly and passes a configured
|
||||
`internal/forge.Backend` into `internal/delivery`. Delivery performs cheap
|
||||
request and source checks, then read-only backend preflight before managed
|
||||
@@ -102,6 +116,7 @@ not a separate release matrix:
|
||||
| Piped child-process exchanges and cancellation cleanup | `internal/process` | `TestStartPipedExchangesBeforeInputEOFAndPreservesSettings`, `TestStartPipedCancellationAfterReadinessReapsChild`, `TestStartPipedPreservesNonzeroExit` |
|
||||
| Authoritative endpoint and exact annotated tag publication | `releasekit.Publish`, `internal/publish`, `internal/git` | `TestPublishPushesOnlyTheCapturedAnnotatedTag`, `TestPublishRejectsUnexpectedPushURLBeforeValidation`, `TestPublishComparesExpectedURLWithResolvedInsteadOfDestination`, `TestPublishExpectedPushURLUsesPushURLWhenFetchAndPushDiffer`, `TestCheckIgnoresExpectedPushURL`, `TestResolveUsesPushURLAndQueriesWithoutMutation` |
|
||||
| Publication partial and uncertain recovery | `internal/publish`, `internal/git` | `TestPublishRejectedPushKeepsLocalTagAndReportsNotPublished`, `TestPublishLostAcknowledgmentConfirmsExactRemoteObject`, `TestPublishLostAcknowledgmentWithChangedEndpointRemainsUnknown`, `TestPublishUnavailableReconciliationRemainsUnknownAndPreservesPushError` |
|
||||
| Saved attempt recording, discovery, explicit later reconciliation, and read-only recovery | `releasekit`, `internal/publish`, `internal/git`, `cmd/releasekit` | `TestLostPublicationOutputCanBeRecoveredFromExplicitRecords`, `TestBuiltPublishRecoveryCommandSelectsItsRecordAmongOtherAttempts`, `TestRecoveryFacadeLoadsPartialEvidenceAndPreservesCause`, `TestRecoveryFacadeErrorUnwrapsCancellation`, `TestListPublicationAttemptsReadsExplicitExternalStore` |
|
||||
| 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` |
|
||||
| Explicit destination selection, standalone and automatic preflight, and delivery ordering | `releasekit`, `internal/delivery`, `internal/gitea`, CLI | `TestDeliveryForgeSelectionIsExplicit`, `TestPreflightDeliveryChecksAuthenticatedRepositoryWithoutCheckout`, `TestPreflightDeliveryPreservesPublicFailureKindsAndCauses`, `TestAutomaticPreflightFailurePrecedesPrebuiltArtifactHashing`, `TestDeliverUnavailablePreflightStopsBeforeManagedBuild`, `TestCIDeliverUnavailablePreflightStopsBeforeDependencyPreparation`, `TestCIDeliverPageOnlyReportsUnavailablePreflightWithStatusOne` |
|
||||
| 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` |
|
||||
|
||||
@@ -124,48 +124,65 @@ the complete checked-in release note. Report its result separately from the
|
||||
completed source release. For failed or uncertain delivery, follow the recovery
|
||||
instructions below using the same immutable version.
|
||||
|
||||
## Resolve failures
|
||||
## Resolve publication failures
|
||||
|
||||
A failed push triggers a URL-resolution check against the captured endpoint,
|
||||
then at most one exact authoritative tag query. If the endpoint no longer
|
||||
resolves to itself, recovery reports `unknown` without querying the rewritten
|
||||
destination. An exact tag-object match confirms publication even when Git
|
||||
reported an error. A proven absent tag is `not_published`; a different object
|
||||
is a conflict; an unreadable query is `unknown`. The command retains its local
|
||||
tag and reports the state, phase,
|
||||
candidate commit, tag object, and captured publication endpoint when available.
|
||||
Do not retry an unknown result until you resolve the authoritative ref at that
|
||||
exact endpoint. Copy the reported endpoint value into the variable below using
|
||||
normal shell quoting; retain the version and tag object from the same result.
|
||||
The command checks that Git URL rewriting still resolves this value to itself;
|
||||
the manual check below applies the same rule before querying:
|
||||
Each publication invocation attempts to save its captured identity before the
|
||||
tag push. The CLI reports the saved record path separately from publication
|
||||
success or failure and, after a push or immediate-reconciliation error, prints a
|
||||
copyable command that selects that exact record. Run that command to make a
|
||||
separate later observation:
|
||||
|
||||
```sh
|
||||
releasekit_endpoint='COPY_CAPTURED_ENDPOINT'
|
||||
releasekit_version='vX.Y.Z'
|
||||
test "$(git ls-remote --get-url -- "$releasekit_endpoint")" = "$releasekit_endpoint" &&
|
||||
git ls-remote --refs -- "$releasekit_endpoint" "refs/tags/$releasekit_version"
|
||||
'/path/to/releasekit' reconcile --record '/absolute/path/to/attempt-record.json'
|
||||
```
|
||||
|
||||
A failed URL-equality check or remote query leaves the outcome unresolved.
|
||||
Correct transport configuration before continuing. The reported endpoint may
|
||||
be different from `origin`'s fetch URL or its current push URL; querying either
|
||||
of those does not establish absence at the captured endpoint.
|
||||
The saved evidence fixes the original endpoint and tag identity. Later recovery
|
||||
uses current supported transport settings for the recorded remote name, but it
|
||||
does not substitute the current remote URL, inspect the local tag or current
|
||||
HEAD, load a profile, rerun checks, or change repository state. A completed
|
||||
observation reports `published`, `not_published`, or `conflict`; an incomplete
|
||||
observation reports `unknown` with diagnostic context. Resolve an unknown result
|
||||
by correcting the identified endpoint rewrite, transport configuration, or
|
||||
missing evidence. For incomplete saved identity, select another record with the
|
||||
required fields or use complete typed evidence through the Go API.
|
||||
|
||||
Compare the returned object ID with the tag object reported by the command.
|
||||
An exact match confirms publication. If the ref is absent, the version was not
|
||||
published; only then may you deliberately remove the unpublished local tag
|
||||
with `git tag -d vX.Y.Z` before correcting the candidate or retrying. Do not
|
||||
move, overwrite, or delete a tag that exists remotely. If a different object
|
||||
uses the version, choose a new version after resolving the conflict.
|
||||
If command output was lost, list local attempts and explicitly select the
|
||||
matching record by its module, full tag, and saved identity:
|
||||
|
||||
If local tag inspection fails after creation, the reported ref may remain even
|
||||
when no tag object ID was obtained. Inspect that ref before recovery.
|
||||
```sh
|
||||
releasekit publication-attempts --repo "$PWD"
|
||||
releasekit reconcile --record '/absolute/path/from-the-list/attempt-record.json'
|
||||
```
|
||||
|
||||
Discovery only reads the local store. It neither queries remotes nor chooses an
|
||||
attempt automatically. Use a supported ReleaseKit CLI if the executable named
|
||||
in the printed handoff command is no longer available. An older record may lack
|
||||
the endpoint, tag-object ID, candidate commit, or another field required for a
|
||||
conclusive result.
|
||||
|
||||
A later observation that the tag is absent describes the remote at that time;
|
||||
it does not prove the version was never published. Never reuse a version known
|
||||
to have been published, and preserve published tags and contents as immutable.
|
||||
Keep removal of an unpublished local tag, candidate correction, and retry as
|
||||
explicit operator decisions after reviewing the record and authoritative
|
||||
remote state. A conflicting object requires resolving the conflict and selecting
|
||||
an unused version when appropriate; do not move, overwrite, or delete a
|
||||
published tag.
|
||||
|
||||
If record storage fails, ReleaseKit reports the recording warning separately;
|
||||
the warning does not change the actual publication outcome. The saved handoff is
|
||||
then unavailable. A Go caller that retained `PublicationResult.Evidence` can
|
||||
still pass that typed evidence directly to `ReconcilePublication`. Process
|
||||
termination before the record is written, removed storage, and older incomplete
|
||||
records can leave no sufficient saved evidence for later recovery.
|
||||
|
||||
Later reconciliation adds no successful-push read-back, polling, CI, consumer
|
||||
installation, or hosted-delivery gate. Hosted page delivery remains separate.
|
||||
|
||||
If validation or a guard fails before this invocation pushes, correct and
|
||||
commit the candidate, publish `main`, and run the command again. A retained
|
||||
local tag still requires the authoritative-state check above before removal;
|
||||
a concurrent publisher may already have published the version. The prepared
|
||||
local tag still requires reviewing the selected record and authoritative state
|
||||
before deciding whether to remove it. The prepared
|
||||
Woodpecker workflow builds the CLI from the tagged checkout, then uses
|
||||
`ci-deliver` for page-only delivery. To activate it after configuring the
|
||||
destination and secret, copy it to `.woodpecker/releasekit-source-delivery.yml`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Publication reconciliation implementation plan
|
||||
|
||||
Status: ready for implementation.
|
||||
Status: complete.
|
||||
|
||||
Implement the target and resolved decisions in the
|
||||
[feature roadmap](publication-reconciliation.md). The original
|
||||
@@ -471,6 +471,8 @@ launchers and source bootstrap working without adding consumer-owned recording.
|
||||
|
||||
## Stage 8: Finish assembled coverage and canonical documentation
|
||||
|
||||
**Completed:** 2026-11-02
|
||||
|
||||
**Outcome:** The full feature works across process boundaries, with supported
|
||||
contracts and a short consumer recovery workflow.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user