github.com/bitrise-io/bitrise-step-update-gitops-repository@v0.0.0-20240426081835-1466be593380/pkg/gitops/local_repository_test.go (about) 1 package gitops 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path" 10 "testing" 11 12 "github.com/bitrise-io/go-steputils/stepconf" 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 var gitRepoCases = map[string]struct { 18 upstreamBranch string 19 repoURL string 20 }{ 21 "master of testhub.assert/test/foo": { 22 upstreamBranch: "master", 23 repoURL: "testhub.assert/test/foo", 24 }, 25 "staging of testhub.assert/test/bar": { 26 upstreamBranch: "staging", 27 repoURL: "testhub.assert/test/bar", 28 }, 29 } 30 31 func TestGitRepo(t *testing.T) { 32 ctx := context.Background() 33 34 for name, tc := range gitRepoCases { 35 t.Run(name, func(t *testing.T) { 36 upstreamPath, close := localUpstreamRepo(t, tc.upstreamBranch) 37 defer close() 38 39 // Initialize mock Github client. 40 wantPullRequestURL := fmt.Sprintf("https://%s/pr/15", tc.repoURL) 41 var gotHead, gotBase string 42 pr := &pullRequestOpenerMock{ 43 OpenPullRequestFunc: func(_ context.Context, p openPullRequestParams) (string, error) { 44 gotHead = p.head 45 gotBase = p.base 46 return wantPullRequestURL, nil 47 }, 48 } 49 50 repo, err := NewGitRepo(ctx, NewGitRepoParams{ 51 PullRequestOpener: pr, 52 GithubRepo: &githubRepo{ 53 url: stepconf.Secret(upstreamPath), 54 }, 55 Branch: tc.upstreamBranch, 56 }) 57 t.Run("create new local repository clone", func(t *testing.T) { 58 require.NoError(t, err, "newRepository") 59 }) 60 61 t.Run("repository is clean without changes", func(t *testing.T) { 62 clean, err := repo.workingDirectoryClean() 63 require.NoError(t, err) 64 require.True(t, clean) 65 }) 66 67 t.Run("repository is dirty after changes", func(t *testing.T) { 68 changePath := path.Join(repo.localPath(), "empty.go") 69 write(t, changePath, "package empty") 70 71 clean, err := repo.workingDirectoryClean() 72 require.NoError(t, err) 73 require.False(t, clean) 74 }) 75 76 t.Run("commit and push changes to upstream", func(t *testing.T) { 77 err := repo.gitCommitAndPush("test commit") 78 require.NoError(t, err, "commit and push") 79 80 clean, err := repo.workingDirectoryClean() 81 require.NoError(t, err, "working directory clean") 82 require.True(t, clean) 83 }) 84 85 t.Run("open pull request from a new branch", func(t *testing.T) { 86 require.NoError(t, repo.gitCheckoutNewBranch(), "new branch") 87 changePath := path.Join(repo.localPath(), "another.go") 88 write(t, changePath, "package another") 89 90 err := repo.gitCommitAndPush("another commit") 91 require.NoError(t, err, "commit and push another") 92 93 gotPullRequestURL, err := repo.openPullRequest(ctx, "", "") 94 require.NoError(t, err, "open pull request") 95 assert.Equal(t, wantPullRequestURL, gotPullRequestURL, "pr url") 96 97 assert.Equal(t, tc.upstreamBranch, gotBase, "pr base") 98 99 assert.NotEqual(t, gotBase, gotHead, "pr head != base") 100 wantHead, err := repo.currentBranch() 101 require.NoError(t, err, "current branch") 102 assert.Equal(t, wantHead, gotHead, "pr head = current branch") 103 }) 104 }) 105 } 106 } 107 108 func localUpstreamRepo(t *testing.T, branch string) (string, func()) { 109 repoPath, err := ioutil.TempDir("", "") 110 require.NoError(t, err, "new temp directory for local upstream") 111 readmePath := path.Join(repoPath, "README.md") 112 113 git(t, repoPath, "init") 114 git(t, repoPath, "checkout", "-b", branch) 115 write(t, readmePath, "A local upstream repository for testing.") 116 git(t, repoPath, "add", "--all") 117 git(t, repoPath, "commit", "-m", "initial commit") 118 // allow push from another git repository 119 git(t, repoPath, "config", "receive.denyCurrentBranch", "ignore") 120 121 return repoPath, func() { 122 os.RemoveAll(repoPath) 123 } 124 } 125 126 func write(t *testing.T, path, content string) { 127 err := ioutil.WriteFile(path, []byte(content), 0600) 128 require.NoError(t, err, "ioutil.WriteFile(%s)", path) 129 } 130 131 func git(t *testing.T, repoPath string, args ...string) { 132 // Change current directory to the repositorys local clone. 133 originalDir, err := os.Getwd() 134 require.NoError(t, err, "get current dir") 135 require.NoError(t, os.Chdir(repoPath), "change to upstream repo") 136 // Defer a revert of the current directory to the original one. 137 defer func() { 138 require.NoError(t, os.Chdir(originalDir), "change to original dir") 139 }() 140 141 cmd := exec.Command("git", args...) 142 require.NoError(t, cmd.Run(), "git %+v", args) 143 }