Skip to content

Commit b4fbc84

Browse files
committed
preflight: if the repo has no remote, skip push & cleanup
This is useful for a pipeline that defines e.g. /path/to/codebase/.git as the repository, with a buildkite-agent running on that local machine. Changes to the that git repo don't need to be pushed anywhere.
1 parent 2a9bbea commit b4fbc84

5 files changed

Lines changed: 62 additions & 13 deletions

File tree

cmd/preflight/preflight.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func (c *PreflightCmd) Run(kongCtx *kong.Context, globals cli.GlobalFlags) error
151151
}
152152
}
153153

154-
if !c.NoCleanup {
154+
if !c.NoCleanup && !result.PushSkipped {
155155
fmt.Fprintf(os.Stderr, "Cleaning up remote branch %s...\n", result.Branch)
156156
if cleanupErr := preflight.Cleanup(wt.Filesystem.Root(), result.Ref, globals.EnableDebug()); cleanupErr != nil {
157157
fmt.Fprintf(os.Stderr, "Warning: failed to delete remote branch %s: %v\n", result.Ref, cleanupErr)

cmd/preflight/render.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,9 @@ func snapshotLines(result *internalpreflight.SnapshotResult) []string {
197197
lines = append(lines, fmt.Sprintf(" %s %s", file.StatusSymbol(), file.Path))
198198
}
199199
}
200+
if result.PushSkipped {
201+
lines = append(lines, "Warning: no remote \"origin\" found; push skipped")
202+
}
200203
return lines
201204
}
202205

cmd/preflight/render_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ func TestTTYRenderer_SetSnapshot(t *testing.T) {
3535
assertLineEquals(t, lines, " - old/file.txt")
3636
}
3737

38+
func TestTTYRenderer_SetSnapshot_WithWarning(t *testing.T) {
39+
lines := captureTTYLines(t, func(r *ttyRenderer) {
40+
r.setSnapshot(&internalpreflight.SnapshotResult{
41+
Commit: "1234567890abcdef",
42+
Ref: "refs/heads/bk/preflight/abc123",
43+
PushSkipped: true,
44+
})
45+
})
46+
47+
assertLineContains(t, lines, "Warning:", "push skipped")
48+
}
49+
3850
func TestTTYRenderer_RenderStatus_AllRunningJobs(t *testing.T) {
3951
startedAt := buildkite.Timestamp{Time: time.Now().Add(-2 * time.Minute)}
4052
lines := captureTTYLines(t, func(r *ttyRenderer) {

internal/preflight/snapshot.go

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ type FileChange struct {
1616

1717
// SnapshotResult holds the output of a successful snapshot operation.
1818
type SnapshotResult struct {
19-
Commit string
20-
Ref string
21-
Branch string
22-
Files []FileChange
19+
Commit string
20+
Ref string
21+
Branch string
22+
Files []FileChange
23+
PushSkipped bool
2324
}
2425

2526
// StatusSymbol returns a human-readable symbol for the file change status.
@@ -111,17 +112,23 @@ func Snapshot(dir string, preflightID uuid.UUID, opts ...SnapshotOption) (*Snaps
111112
}
112113
}
113114

114-
// Push the commit to the remote branch.
115-
refspec := fmt.Sprintf("%s:%s", commit, ref)
116-
if err := gitRun(dir, env, cfg.debug, "push", "origin", refspec); err != nil {
117-
return nil, err
115+
var pushSkipped bool
116+
if _, err := gitOutput(dir, env, cfg.debug, "remote", "get-url", "origin"); err != nil {
117+
pushSkipped = true
118+
} else {
119+
// Push the commit to the remote branch.
120+
refspec := fmt.Sprintf("%s:%s", commit, ref)
121+
if err := gitRun(dir, env, cfg.debug, "push", "origin", refspec); err != nil {
122+
return nil, err
123+
}
118124
}
119125

120126
return &SnapshotResult{
121-
Commit: commit,
122-
Ref: ref,
123-
Branch: branch,
124-
Files: files,
127+
Commit: commit,
128+
Ref: ref,
129+
Branch: branch,
130+
Files: files,
131+
PushSkipped: pushSkipped,
125132
}, nil
126133
}
127134

internal/preflight/snapshot_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,33 @@ func TestDiffFiles(t *testing.T) {
326326
}
327327
}
328328

329+
func TestSnapshot_NoRemote(t *testing.T) {
330+
worktree := initTestRepo(t)
331+
332+
// Remove the origin remote.
333+
runGit(t, worktree, "remote", "remove", "origin")
334+
335+
// Add a change so we exercise the commit path too.
336+
if err := os.WriteFile(filepath.Join(worktree, "README.md"), []byte("# changed\n"), 0o644); err != nil {
337+
t.Fatal(err)
338+
}
339+
340+
preflightID := uuid.MustParse("00000000-0000-0000-0000-000000000010")
341+
result, err := Snapshot(worktree, preflightID)
342+
if err != nil {
343+
t.Fatalf("Snapshot() error: %v", err)
344+
}
345+
346+
if !result.PushSkipped {
347+
t.Error("expected PushSkipped to be true when no remote exists")
348+
}
349+
350+
// The commit should still be valid.
351+
if len(result.Commit) != 40 {
352+
t.Errorf("expected 40-char SHA, got %q", result.Commit)
353+
}
354+
}
355+
329356
func TestSnapshot_CleanWorktree(t *testing.T) {
330357
worktree := initTestRepo(t)
331358

0 commit comments

Comments
 (0)