Add publication recovery handoff to CLI

This commit is contained in:
2026-11-02 19:22:23 +00:00
parent 4afdd9b826
commit 6915a86132
6 changed files with 223 additions and 4 deletions

View File

@@ -72,8 +72,10 @@ func runCheckOrPublish(ctx context.Context, invocation cli.Invocation, stdout, s
return 2
}
request.ExpectedPushURL = settings.ExpectedPushURL
request.PublicationRecordDir = invocation.RecordDir
fmt.Fprintf(stderr, "validating and publishing module %s version %s\n", selectedModuleLabel(settings.ModuleDir), invocation.Version)
result, err := releasekit.Publish(ctx, request)
reportPublicationRecord(result, err, stderr)
if err != nil {
fmt.Fprintf(stderr, "publication state=%s phase=%s module=%s module-dir=%s version=%s tag=%s commit=%s tag-object=%s endpoint=%q: %s\n", result.State, result.Phase, result.ModulePath, result.ModuleDir, result.Version, result.Tag, result.CandidateCommit, result.TagObject, git.DisplayURL(result.Endpoint), candidateFailureText(err))
if errors.Is(err, releasekit.ErrInvalidVersion) {
@@ -99,6 +101,56 @@ func runCheckOrPublish(ctx context.Context, invocation cli.Invocation, stdout, s
return 0
}
func reportPublicationRecord(result releasekit.PublicationResult, publicationErr error, stderr io.Writer) {
if result.RecordError != nil {
fmt.Fprintf(stderr, "publication record warning: %s\n", git.DisplayError(result.RecordError))
}
if result.RecordPath == "" {
return
}
fmt.Fprintf(stderr, "publication record saved: %s\n", result.RecordPath)
if publicationErr == nil || !publicationOffersRecovery(result.Phase) {
return
}
command, err := publicationRecoveryCommand(result.RecordPath)
if err != nil {
fmt.Fprintf(stderr, "recovery command unavailable: %s\n", git.DisplayError(err))
fmt.Fprintln(stderr, "Use your selected supported ReleaseKit CLI with this record if the original executable is unavailable.")
return
}
fmt.Fprintf(stderr, "recovery command: %s\n", command)
fmt.Fprintln(stderr, "If this executable is unavailable, use your selected supported ReleaseKit CLI with the same record.")
}
func publicationOffersRecovery(phase releasekit.PublicationPhase) bool {
switch phase {
case releasekit.PublicationTagCreation, releasekit.PublicationPush, releasekit.PublicationReconciliation:
return true
default:
return false
}
}
func publicationRecoveryCommand(recordPath string) (string, error) {
executable, err := os.Executable()
if err != nil {
return "", fmt.Errorf("find current executable: %w", err)
}
executable, err = filepath.Abs(executable)
if err != nil {
return "", fmt.Errorf("resolve current executable path: %w", err)
}
recordPath, err = filepath.Abs(recordPath)
if err != nil {
return "", fmt.Errorf("resolve publication record path: %w", err)
}
return shellQuote(executable) + " reconcile --record " + shellQuote(recordPath), nil
}
func shellQuote(argument string) string {
return "'" + strings.ReplaceAll(argument, "'", "'\"'\"'") + "'"
}
func runBuild(ctx context.Context, invocation cli.Invocation, stdout, stderr io.Writer) int {
settings, err := cli.LoadSettings(invocation.Repository, invocation.ConfigPath)
if err != nil {