Keep push recovery on captured endpoint
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
releasekit "gitea.maximumdirect.net/eric/ReleaseKit"
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/git"
|
||||
)
|
||||
|
||||
const releaseNote = "# Sample App v1.2.3\n\nA source release.\n\nUpgrade notes stay intact.\n"
|
||||
@@ -163,6 +164,47 @@ func TestPublishLostAcknowledgmentConfirmsExactRemoteObject(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishLostAcknowledgmentWithChangedEndpointRemainsUnknown(t *testing.T) {
|
||||
repo := newPublishFixture(t)
|
||||
base := t.TempDir()
|
||||
emptyRemote := filepath.Join(base, "empty.git")
|
||||
gitRun(t, base, "init", "--bare", emptyRemote)
|
||||
wrapper := installGitWrapperWithMutationMode(t, repo, "lost-ack-rewrite", emptyRemote)
|
||||
t.Setenv("PATH", wrapper.bin+string(os.PathListSeparator)+os.Getenv("PATH"))
|
||||
|
||||
result, err := releasekit.Publish(context.Background(), releasekit.ReleaseRequest{
|
||||
RepositoryDir: repo.work,
|
||||
Product: "Sample App",
|
||||
Version: "v1.2.3",
|
||||
Validate: func(context.Context, releasekit.Candidate) error { return nil },
|
||||
})
|
||||
if err == nil || result.State != releasekit.PublicationUnknown || result.Phase != releasekit.PublicationReconciliation {
|
||||
t.Fatalf("result = %#v, error = %v", result, err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "scoped URL resolves") || !strings.Contains(err.Error(), "lost acknowledgment") {
|
||||
t.Fatalf("error does not preserve endpoint verification and push failures: %v", err)
|
||||
}
|
||||
if !errors.Is(err, git.ErrEndpointChanged) || !errors.Is(err, git.ErrRemoteStateUnreadable) {
|
||||
t.Fatalf("endpoint verification error identity was not preserved: %v", err)
|
||||
}
|
||||
var exitErr *exec.ExitError
|
||||
if !errors.As(err, &exitErr) || exitErr.ExitCode() != 77 {
|
||||
t.Fatalf("push cause identity was not preserved: %v", err)
|
||||
}
|
||||
if queries := countLines(t, wrapper.queryLog); queries != 3 {
|
||||
t.Fatalf("authoritative tag query count = %d, want no tag query after endpoint verification failed", queries)
|
||||
}
|
||||
if got := gitText(t, repo.work, "rev-parse", "refs/tags/v1.2.3"); got != result.TagObject {
|
||||
t.Fatalf("local tag object = %s, want retained object %s", got, result.TagObject)
|
||||
}
|
||||
if got := gitText(t, repo.bare, "rev-parse", "refs/tags/v1.2.3"); got != result.TagObject {
|
||||
t.Fatalf("original remote tag object = %s, want published object %s", got, result.TagObject)
|
||||
}
|
||||
if got := gitText(t, repo.bare, "rev-parse", "refs/tags/v1.2.3^{}"); got != repo.commit {
|
||||
t.Fatalf("original remote tag peels to %s, want candidate commit %s", got, repo.commit)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublishConflictingRemoteTagIsNotReportedAsAbsent(t *testing.T) {
|
||||
repo := newPublishFixture(t)
|
||||
wrapper := installGitWrapper(t, repo, "pass")
|
||||
@@ -393,6 +435,11 @@ if [ "$IS_PUSH" = "1" ]; then
|
||||
STATUS=$?
|
||||
: > "$PUSH_DONE"
|
||||
if [ "$MODE" = "lost-ack-cancel" ] && [ "$STATUS" = "0" ]; then kill -STOP $$; fi
|
||||
if [ "$MODE" = "lost-ack-rewrite" ] && [ "$STATUS" = "0" ]; then
|
||||
"$REAL_GIT" config --local "url.\"$MUTATE_OBJECT\".insteadOf" %s
|
||||
echo "lost acknowledgment after tag was accepted" >&2
|
||||
exit 77
|
||||
fi
|
||||
exit "$STATUS"
|
||||
fi
|
||||
if [ "$MODE" = "mutate-tag" ]; then
|
||||
@@ -406,7 +453,7 @@ if [ "$MODE" = "mutate-tag" ]; then
|
||||
esac
|
||||
fi
|
||||
exec "$REAL_GIT" "$@"
|
||||
`, shellQuote(realGit), shellQuote(queryLog), shellQuote(pushDone), shellQuote(mode), shellQuote(mutationObject))
|
||||
`, shellQuote(realGit), shellQuote(queryLog), shellQuote(pushDone), shellQuote(mode), shellQuote(mutationObject), shellQuote(repo.bare))
|
||||
if err := os.WriteFile(filepath.Join(bin, "git"), []byte(contents), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user