Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:

testing:
runs-on: ubuntu-latest
container: golang:1.24-alpine
container: golang:1.25-alpine
steps:
- name: Checkout repository
uses: actions/checkout@v6
Expand Down
13 changes: 11 additions & 2 deletions plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,19 @@ func (p Plugin) WriteToken() error {
}

// HandleRemote adds the git remote if required.
// If the remote already exists, it updates the URL instead.
func (p Plugin) HandleRemote(ctx context.Context) error {
Comment on lines 150 to 152
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There’s no test covering the new fallback behavior in HandleRemote (remote already exists -> update URL). Adding a unit test that sets up a temporary git repo, adds the remote once, and then calls HandleRemote again would verify the fix for #107 and prevent regressions.

Copilot uses AI. Check for mistakes.
if p.Config.Remote != "" {
if err := execute(repo.RemoteAdd(ctx, p.Config.RemoteName, p.Config.Remote)); err != nil {
return err
if repo.RemoteExists(ctx, p.Config.RemoteName) {
cmd := repo.RemoteSetURL(ctx, p.Config.RemoteName, p.Config.Remote)
if err := execute(cmd); err != nil {
return err
}
} else {
cmd := repo.RemoteAdd(ctx, p.Config.RemoteName, p.Config.Remote)
if err := execute(cmd); err != nil {
return err
}
}
}

Expand Down
62 changes: 62 additions & 0 deletions plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package main

import (
"context"
"os"
"os/exec"
"testing"
)

Expand Down Expand Up @@ -40,3 +42,63 @@ func TestPlugin_HandleRemote(t *testing.T) {
})
}
}

func TestPlugin_HandleRemote_ExistingRemote(t *testing.T) {
// Create a temporary git repo
tmpDir, err := os.MkdirTemp("", "drone-git-push-test")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)

// Save current dir and change to temp dir
origDir, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
defer func() {
_ = os.Chdir(origDir)
}()

if err := os.Chdir(tmpDir); err != nil {
t.Fatal(err)
}

// Initialize a git repo and add a remote
ctx := context.Background()
if out, err := exec.CommandContext(
ctx, "git", "init",
).CombinedOutput(); err != nil {
t.Fatalf("git init failed: %s, %v", out, err)
}
if out, err := exec.CommandContext(
ctx, "git", "remote", "add", "origin",
"git@github.com:old/repo.git",
).CombinedOutput(); err != nil {
t.Fatalf("git remote add failed: %s, %v", out, err)
}

// HandleRemote should succeed even though "origin" already exists
p := Plugin{
Config: Config{
RemoteName: "origin",
Remote: "git@github.com:new/repo.git",
},
}
if err := p.HandleRemote(ctx); err != nil {
t.Errorf("HandleRemote() with existing remote should not fail, got: %v", err)
}

// Verify the remote URL was updated
out, err := exec.CommandContext(
ctx, "git", "remote", "get-url", "origin",
).Output()
if err != nil {
t.Fatal(err)
}
got := string(out)
want := "git@github.com:new/repo.git\n"
if got != want {
t.Errorf("remote URL = %q, want %q", got, want)
}
}
24 changes: 24 additions & 0 deletions repo/remote.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ func RemoteRemove(ctx context.Context, name string) *exec.Cmd {
return cmd
}

// RemoteExists checks if a named remote already exists in a git repo.
func RemoteExists(ctx context.Context, name string) bool {
cmd := exec.CommandContext(
ctx,
"git",
"remote",
"get-url",
name)
return cmd.Run() == nil
}

// RemoteAdd adds an additional remote to a git repo.
func RemoteAdd(ctx context.Context, name, url string) *exec.Cmd {
cmd := exec.CommandContext(
Expand All @@ -31,6 +42,19 @@ func RemoteAdd(ctx context.Context, name, url string) *exec.Cmd {
return cmd
}

// RemoteSetURL updates the URL of an existing remote in a git repo.
func RemoteSetURL(ctx context.Context, name, url string) *exec.Cmd {
cmd := exec.CommandContext(
ctx,
"git",
"remote",
"set-url",
name,
url)

return cmd
}

// RemotePush pushs the changes from the local head to a remote branch..
func RemotePush(ctx context.Context, remote, branch string, force, followtags bool) *exec.Cmd {
return RemotePushNamedBranch(ctx, remote, "HEAD", branch, force, followtags)
Expand Down
15 changes: 15 additions & 0 deletions repo/remote_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package repo

import (
"context"
"testing"
)

Expand Down Expand Up @@ -45,3 +46,17 @@ func TestSanitizeInput(t *testing.T) {
})
}
}

func TestRemoteSetURL(t *testing.T) {
cmd := RemoteSetURL(context.Background(), "origin", "git@github.com:user/repo.git")
args := cmd.Args
expected := []string{"git", "remote", "set-url", "origin", "git@github.com:user/repo.git"}
if len(args) != len(expected) {
t.Fatalf("expected %d args, got %d", len(expected), len(args))
}
for i, arg := range args {
if arg != expected[i] {
t.Errorf("arg[%d] = %q, want %q", i, arg, expected[i])
}
}
}
Loading