Fix release destination handling and verification example

This commit is contained in:
2026-09-28 01:42:06 +00:00
parent d750e7325c
commit a36ed3deba
4 changed files with 69 additions and 7 deletions

View File

@@ -180,10 +180,12 @@ Only when useful or requested, read back the remote tag or retrieve the exact
version into a new module without a local `replace` directive. These checks
are optional and non-gating. Do not poll CI or wait for module propagation.
Private-host credentials must already be configured. For direct-origin
verification, use a temporary consumer module and check the exact module path
verification, set the version to the release just published (replace the sample
below), then use a temporary consumer module and check the exact module path
and version reported by `go list -m`:
```sh
release_version=v0.5.0
consumer_dir=$(mktemp -d)
(
cd "$consumer_dir"

View File

@@ -1,5 +1,25 @@
# Release Workflow Review Findings
Status: both findings addressed. The original findings below are retained as
review history until normal release-preparation retirement.
## Resolution and verification
- Publication, fetch, and recovery now use the same validated named `origin`.
Pushes retain exact refspecs and disabled implicit tags, and override the
remote's mirror default for that invocation only. No new gate was introduced.
- A disposable-Git regression failed against the original publisher and passes
with the fix for normal publication and lost main/tag push responses. It also
checks that broad push defaults do not publish or delete unrelated refs and
that the rewrite destination receives no refs.
- Optional consumer verification explicitly initializes the selected version.
Executing the documented block with a local Go stub verified the exact module
argument with both an initially unset and an initially stale version variable,
without network retrieval.
- Focused publication tests passed. Final validation passed: Bash syntax,
whitespace review, and the Go 1.25.14 release checker (race suite including
documentation links, full vet, and both Linux target builds).
Reviewed implementation through `3d0093e` against the release roadmap and
completed implementation plan. The ordinary Go 1.25.14 release checker passed
(offline race suite, full vet, Linux amd64/arm64 builds), as did Bash syntax

View File

@@ -108,7 +108,8 @@ func (f *releaseFixture) run(version, behavior, validatorAction string) (string,
if [ "${CONFIGKIT_GIT_BEHAVIOR-}" = main-unknown ] || [ "${CONFIGKIT_GIT_BEHAVIOR-}" = tag-unknown ]; then
if [ "${1-}" = ls-remote ] && [ -f "$CONFIGKIT_GIT_MARKER" ]; then exit 37; fi
fi
if [ "${1-}" = push ]; then
case "$*" in
push\ *|-c\ remote.origin.mirror=false\ push\ *)
case "$*" in
*refs/heads/main*)
case "${CONFIGKIT_GIT_BEHAVIOR-}" in
@@ -126,7 +127,8 @@ if [ "${1-}" = push ]; then
tag-unknown) : > "$CONFIGKIT_GIT_MARKER"; exit 37 ;;
esac ;;
esac
fi
;;
esac
exec "$CONFIGKIT_REAL_GIT" "$@"
`
if err := os.WriteFile(filepath.Join(bin, "git"), []byte(wrapper), 0700); err != nil {
@@ -320,3 +322,38 @@ func TestReleasePublicationRecovery(t *testing.T) {
})
}
}
func TestReleasePublicationUsesValidatedDestination(t *testing.T) {
for _, behavior := range []string{"success", "main-lost", "tag-lost"} {
t.Run(behavior, func(t *testing.T) {
f := newReleaseFixture(t)
other := filepath.Join(t.TempDir(), "other.git")
f.git("init", "-q", "--bare", other)
f.git("remote", "set-url", "--push", "origin", f.remote)
f.git("config", "url."+other+".pushInsteadOf", f.remote)
// These defaults must not broaden the explicit release refspecs when
// publishing through the validated named remote.
f.git("config", "remote.origin.mirror", "true")
f.git("config", "remote.origin.push", "refs/heads/*:refs/heads/*")
f.git("branch", "unrelated", f.base)
f.git("tag", "-a", "-m", "Unrelated", "v0.8.0", f.base)
f.git("--git-dir="+f.remote, "update-ref", "refs/heads/keep", f.base)
out, err := f.run("v0.9.0", behavior, "")
if err != nil {
t.Fatalf("publish: %v\n%s", err, out)
}
if f.validations() != 1 || f.remoteRef("refs/heads/main") != f.candidate ||
f.remoteRef("refs/tags/v0.9.0") != f.git("rev-parse", "refs/tags/v0.9.0") {
t.Fatal("publication did not reach the validated destination")
}
if f.remoteRef("refs/heads/keep") != f.base ||
f.remoteRef("refs/heads/unrelated") != "" || f.remoteRef("refs/tags/v0.8.0") != "" {
t.Fatal("publication changed unrelated refs")
}
if refs := f.git("--git-dir="+other, "for-each-ref", "--format=%(refname)"); refs != "" {
t.Fatalf("publication reached the rewrite destination: %s", refs)
}
})
}
}

View File

@@ -36,7 +36,7 @@ check_unused_version() {
read_remote_ref() {
local ref=$1 response result
if response=$(git ls-remote --refs --exit-code "$remote_url" "$ref" 2>/dev/null); then
if response=$(git ls-remote --refs --exit-code origin "$ref" 2>/dev/null); then
[[ "$response" == *$'\t'"$ref" ]] || return 3
printf '%s\n' "${response%%$'\t'*}"
else
@@ -78,7 +78,7 @@ else
((result == 2)) && fail "authoritative main is absent"
fail "cannot read authoritative main; publication status is unknown"
fi
git fetch --no-tags "$remote_url" refs/heads/main >/dev/null ||
git fetch --no-tags origin refs/heads/main >/dev/null ||
fail "cannot fetch authoritative main"
fetched_main=$(git rev-parse --verify FETCH_HEAD) || fail "cannot inspect fetched main"
git merge-base --is-ancestor "$fetched_main" "$candidate" ||
@@ -88,7 +88,10 @@ git merge-base --is-ancestor "$fetched_main" "$candidate" ||
check_candidate "after validation"
check_unused_version
if git push --no-follow-tags "$remote_url" "$candidate:refs/heads/main"; then
# Use the named remote whose resolved destinations were checked above: a literal
# URL can apply pushInsteadOf even when origin's explicit push URL does not.
# Disable mirror defaults as well as implicit tags; publish only our refspec.
if git -c remote.origin.mirror=false push --no-follow-tags origin "$candidate:refs/heads/main"; then
:
else
if observed_main=$(read_remote_ref refs/heads/main); then
@@ -113,7 +116,7 @@ tag_type=$(git cat-file -t "refs/tags/$version") ||
tag_oid=$(git rev-parse --verify "refs/tags/$version") ||
fail "main is at $candidate; cannot identify local tag $version"
if git push --no-follow-tags "$remote_url" "refs/tags/$version:refs/tags/$version"; then
if git -c remote.origin.mirror=false push --no-follow-tags origin "refs/tags/$version:refs/tags/$version"; then
:
else
if observed_tag=$(read_remote_ref "refs/tags/$version"); then