package releasekit import ( "context" "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 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 the intended tag object was pushed successfully // or observed remotely. PublicationPublished PublicationState = PublicationState(publish.Published) // PublicationConflict means an authoritative guard or later observation found // conflicting state. PublicationConflict PublicationState = PublicationState(publish.Conflict) // PublicationUnknown means publication could not be determined from the available evidence. PublicationUnknown PublicationState = PublicationState(publish.Unknown) ) type PublicationPhase string const ( // PublicationPreflight identifies local and remote candidate inspection. PublicationPreflight PublicationPhase = PublicationPhase(publish.Preflight) // PublicationValidation identifies the standard suite and additional checks. PublicationValidation PublicationPhase = PublicationPhase(publish.Validation) // PublicationTagCreation identifies creation and inspection of the local annotated tag. PublicationTagCreation PublicationPhase = PublicationPhase(publish.TagCreation) // PublicationPush identifies the remote tag push attempt. PublicationPush PublicationPhase = PublicationPhase(publish.Push) // PublicationReconciliation identifies immediate observation after a push error. PublicationReconciliation PublicationPhase = PublicationPhase(publish.Reconciliation) // PublicationComplete identifies a successful tag push. PublicationComplete PublicationPhase = PublicationPhase(publish.Complete) ) // PublicationResult describes the publication state reached by this call. type PublicationResult struct { RepositoryDir string // absolute source repository path. ModuleDir string // absolute selected module directory. ModulePath string // selected module's declared Go path. Tag string // complete selected Git tag. Version string // selected stable version CandidateCommit string // captured main commit Endpoint string // captured effective push URL, which may contain credentials Phase PublicationPhase // last operation phase reached 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 succeeds RecordError error // recording failure, separate from publication outcome and returned error } // After publication preflight succeeds, Publish runs one offline Go test suite // for the captured candidate. // Validation.Go.Race enables the race detector for that suite, // Validation.Go.FullVet runs go vet afterward instead of test-time vet, and // Validation.Go.CompileTargets compiles all packages for each selected target // with cgo disabled after tests and vet. Compilation produces no artifacts and // does not execute target binaries. The selected formatting, distribution, // file-size, and Markdown checks then run before AdditionalChecks. Markdown is // disabled when nil and enabled by a non-nil specification; outside-checkout // destinations are reported as out of scope unless boundary enforcement is // selected. Submodule contents remain out of scope. ExpectedPushURL, when // nonempty, is compared exactly with the resolved effective push URL before // validation; a mismatch returns ErrUnexpectedPushURL. It then calls // AdditionalChecks when supplied. // It optionally builds selected targets in temporary storage outside the // worktree and pushes the exact annotated tag object to the selected remote. // It returns a result with errors: preflight failures are not_attempted, failed // authoritative guards are conflict, and errors after local tag creation but // before push are not_published. A failed push gets one bounded authoritative // 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 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{ RepositoryDir: candidateInput.RepositoryDir, ModuleDir: candidateInput.ModuleDir, Product: candidateInput.Product, Version: candidateInput.Version, Remote: request.Remote, ExpectedPushURL: request.ExpectedPushURL, RecordDir: request.PublicationRecordDir, Validation: candidateInput.Validation, AdditionalChecks: candidateInput.AdditionalChecks, AfterValidate: candidateInput.AfterValidate, Output: candidateInput.Output, }) return PublicationResult{ RepositoryDir: result.RepositoryDir, ModuleDir: result.ModuleDir, ModulePath: result.ModulePath, Tag: result.Tag, Version: result.Version, CandidateCommit: result.CandidateCommit, Endpoint: result.Endpoint, Phase: PublicationPhase(result.Phase), TagObject: result.TagObject, State: PublicationState(result.State), Evidence: publicEvidence(result.Evidence), RecordPath: result.RecordPath, RecordError: publicRecoveryError(result.RecordError, ""), }, convertValidationError(err) }