Finish publication recovery workflow

This commit is contained in:
2026-11-02 19:37:29 +00:00
parent 6915a86132
commit 599ad81bec
10 changed files with 697 additions and 76 deletions

View File

@@ -6,18 +6,23 @@ import (
"go.maximumdirect.net/releasekit/internal/publish"
)
// PublicationState describes one publication attempt or a later observation.
type PublicationState string
const (
// PublicationNotAttempted means no tag push was attempted.
PublicationNotAttempted PublicationState = PublicationState(publish.NotAttempted)
// PublicationNotPublished means this invocation knows the tag was not published.
// PublicationNotPublished means the operation established that its tag was
// not published or was absent at observation time. It does not establish that
// the version was never published.
PublicationNotPublished PublicationState = PublicationState(publish.NotPublished)
// PublicationPublished means Git reported a successful push of the intended tag object.
// PublicationPublished means the intended tag object was pushed successfully
// or observed remotely.
PublicationPublished PublicationState = PublicationState(publish.Published)
// PublicationConflict means an authoritative branch or tag guard failed.
// PublicationConflict means an authoritative guard or later observation found
// conflicting state.
PublicationConflict PublicationState = PublicationState(publish.Conflict)
// PublicationUnknown means a tag push failed and its remote outcome is unresolved.
// PublicationUnknown means publication could not be determined from the available evidence.
PublicationUnknown PublicationState = PublicationState(publish.Unknown)
)
@@ -32,7 +37,7 @@ const (
PublicationTagCreation PublicationPhase = PublicationPhase(publish.TagCreation)
// PublicationPush identifies the remote tag push attempt.
PublicationPush PublicationPhase = PublicationPhase(publish.Push)
// PublicationReconciliation identifies the single authoritative tag query after a push error.
// PublicationReconciliation identifies immediate observation after a push error.
PublicationReconciliation PublicationPhase = PublicationPhase(publish.Reconciliation)
// PublicationComplete identifies a successful tag push.
PublicationComplete PublicationPhase = PublicationPhase(publish.Complete)
@@ -51,8 +56,8 @@ type PublicationResult struct {
TagObject string // local annotated tag object ID, when established; a local ref may remain even when empty
State PublicationState // publication outcome for this invocation
Evidence PublicationEvidence // typed evidence for later reconciliation; Endpoint may contain credentials
RecordPath string // absolute private record path when recording is available
RecordError error // recording failure, separate from publication outcome
RecordPath string // absolute private record path when recording succeeds
RecordError error // recording failure, separate from publication outcome and returned error
}
// After publication preflight succeeds, Publish runs one offline Go test suite
@@ -77,7 +82,11 @@ type PublicationResult struct {
// tag query: an exact object match confirms publication, absence is
// not_published, a different object is conflict, and an unreadable result is
// unknown. A nil error means publication is confirmed by the successful push
// or exact remote object match.
// or an exact remote object match. Publish records available attempt evidence
// before the tag push when local storage is available; recording failure is
// reported separately in PublicationResult.RecordError and does not change the
// publication outcome. PublicationResult.Evidence can be passed directly to
// ReconcilePublication even when no record was saved.
func Publish(ctx context.Context, request ReleaseRequest) (PublicationResult, error) {
candidateInput := candidateRequest(request)
result, err := publish.Publish(ctx, publish.Request{