fix(strategy): scope empty-remote guard to configured remotes; document staleness limit · Entire

fix(strategy): scope empty-remote guard to configured remotes; document staleness limit

b5ddba3→main·

karthik-rameshkumar·3d ago·2 files·+35 added/-0 removed

Addresses two trail-review findings on the local-ref guard:

Test adds a bare-URL case asserting the guard publishes (does not defer).

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Changes

2

186 unmodified lines  
187  
188  
189  
190  
191  
192  
193  
194  
195  
196  
197  
198  
199  
200  
201  
202  
203  
204  
205  
206  
207  
208  
209  
210  
211  
212  
213  
214  
215  
216  
217  
218  
219  
220  
221  
222  
223  
224

186 unmodified lines

if ps.hasCheckpointURL() {
        return false
    }

// The hazard only arises for a configured remote (the `git remote add
    // origin …` then first-push flow). Pushing straight to a bare URL hands that
    // URL to the hook as the remote arg, and git never records a
    // refs/remotes/<url>/* tracking ref for it — so a tracking-ref check would
    // defer the metadata forever. Publish for a non-configured (URL) target
    // rather than strand it; the first-branch scenario always uses a named
    // remote.
    if !isConfiguredRemote(ctx, ps.remote) {
        return false
    }

// Known limitation, accepted for the no-network design: a tracking ref left
    // over from before a remote was deleted and recreated empty under the same
    // URL reads as "established", so v1 would publish to the now-empty remote.
    // Detecting that requires asking the remote — the network round trip we
    // deliberately avoid here. The scenario is rare and its default branch is
    // recoverable by resetting it on the forge.
    return !remoteHasTrackingRefs(ctx, ps.remote)
}

// isConfiguredRemote reports whether name is a configured git remote, as
// opposed to a bare URL that git passes through verbatim when a push targets a
// URL directly. Local and best-effort (reads config, no network); any error is
// treated as "not a configured remote".
func isConfiguredRemote(ctx context.Context, name string) bool {
    if name == "" {
        return false
    }
    return exec.CommandContext(ctx, "git", "remote", "get-url", name).Run() == nil
}

// remoteHasTrackingRefs reports whether any refs/remotes/<remote>/* ref exists
// locally. Its presence means the remote has been fetched from or pushed to
// before and so already has at least one branch. Local-only and best-effort:

Mcmd/entire/cli/strategy/manual_commit_push.go+29

36 unmodified lines  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48

36 unmodified lines

require.True(t, deferCheckpointPushOnEmptyRemote(ctx, ps),
        "a remote with no tracking refs must defer")

// A push straight to a bare URL is not a configured remote; git never records
    // a tracking ref for it, so the guard must publish rather than defer forever.
    require.False(t,
        deferCheckpointPushOnEmptyRemote(ctx, pushSettings{remote: "https://example.invalid/repo.git"}),
        "a bare-URL push target must not defer")

// git records a remote-tracking ref after the first successful push; simulate
    // that locally (no network). The remote is now established → publish.
    run("update-ref", "refs/remotes/origin/main", "HEAD")

Mcmd/entire/cli/strategy/manual_commit_push_test.go+6