1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-23 07:19:41 +02:00

feat(gitops): support to list git repository refs and file tree [EE-2673] (#7100)

This commit is contained in:
Oscar Zhou 2022-09-21 17:47:02 +12:00 committed by GitHub
parent ef1d648c07
commit 5777c18297
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1673 additions and 187 deletions

View file

@ -32,7 +32,7 @@ func setup(t *testing.T) string {
}
func Test_ClonePublicRepository_Shallow(t *testing.T) {
service := Service{git: gitClient{preserveGitDirectory: true}} // no need for http client since the test access the repo via file system.
service := Service{git: NewGitClient(true)} // no need for http client since the test access the repo via file system.
repositoryURL := setup(t)
referenceName := "refs/heads/main"
@ -44,7 +44,7 @@ func Test_ClonePublicRepository_Shallow(t *testing.T) {
}
func Test_ClonePublicRepository_NoGitDirectory(t *testing.T) {
service := Service{git: gitClient{preserveGitDirectory: false}} // no need for http client since the test access the repo via file system.
service := Service{git: NewGitClient(false)} // no need for http client since the test access the repo via file system.
repositoryURL := setup(t)
referenceName := "refs/heads/main"
@ -56,7 +56,7 @@ func Test_ClonePublicRepository_NoGitDirectory(t *testing.T) {
}
func Test_cloneRepository(t *testing.T) {
service := Service{git: gitClient{preserveGitDirectory: true}} // no need for http client since the test access the repo via file system.
service := Service{git: NewGitClient(true)} // no need for http client since the test access the repo via file system.
repositoryURL := setup(t)
referenceName := "refs/heads/main"
@ -64,10 +64,14 @@ func Test_cloneRepository(t *testing.T) {
dir := t.TempDir()
t.Logf("Cloning into %s", dir)
err := service.cloneRepository(dir, cloneOptions{
repositoryUrl: repositoryURL,
referenceName: referenceName,
depth: 10,
err := service.cloneRepository(dir, cloneOption{
fetchOption: fetchOption{
baseOption: baseOption{
repositoryUrl: repositoryURL,
},
referenceName: referenceName,
},
depth: 10,
})
assert.NoError(t, err)
@ -75,7 +79,7 @@ func Test_cloneRepository(t *testing.T) {
}
func Test_latestCommitID(t *testing.T) {
service := Service{git: gitClient{preserveGitDirectory: true}} // no need for http client since the test access the repo via file system.
service := Service{git: NewGitClient(true)} // no need for http client since the test access the repo via file system.
repositoryURL := setup(t)
referenceName := "refs/heads/main"
@ -106,53 +110,196 @@ func getCommitHistoryLength(t *testing.T, err error, dir string) int {
return count
}
type testDownloader struct {
called bool
}
func Test_listRefsPrivateRepository(t *testing.T) {
ensureIntegrationTest(t)
func (t *testDownloader) download(_ context.Context, _ string, _ cloneOptions) error {
t.called = true
return nil
}
accessToken := getRequiredValue(t, "GITHUB_PAT")
username := getRequiredValue(t, "GITHUB_USERNAME")
func (t *testDownloader) latestCommitID(_ context.Context, _ fetchOptions) (string, error) {
return "", nil
}
client := NewGitClient(false)
type expectResult struct {
err error
refsCount int
}
func Test_cloneRepository_azure(t *testing.T) {
tests := []struct {
name string
url string
called bool
args baseOption
expect expectResult
}{
{
name: "Azure HTTP URL",
url: "https://Organisation@dev.azure.com/Organisation/Project/_git/Repository",
called: true,
name: "list refs of a real private repository",
args: baseOption{
repositoryUrl: privateGitRepoURL,
username: username,
password: accessToken,
},
expect: expectResult{
err: nil,
refsCount: 2,
},
},
{
name: "Azure SSH URL",
url: "git@ssh.dev.azure.com:v3/Organisation/Project/Repository",
called: true,
name: "list refs of a real private repository with incorrect credential",
args: baseOption{
repositoryUrl: privateGitRepoURL,
username: "test-username",
password: "test-token",
},
expect: expectResult{
err: ErrAuthenticationFailure,
},
},
{
name: "Something else",
url: "https://example.com",
called: false,
name: "list refs of a fake repository without providing credential",
args: baseOption{
repositoryUrl: privateGitRepoURL + "fake",
username: "",
password: "",
},
expect: expectResult{
err: ErrAuthenticationFailure,
},
},
{
name: "list refs of a fake repository",
args: baseOption{
repositoryUrl: privateGitRepoURL + "fake",
username: username,
password: accessToken,
},
expect: expectResult{
err: ErrIncorrectRepositoryURL,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
azure := &testDownloader{}
git := &testDownloader{}
s := &Service{azure: azure, git: git}
s.cloneRepository("", cloneOptions{repositoryUrl: tt.url, depth: 1})
// if azure API is called, git isn't and vice versa
assert.Equal(t, tt.called, azure.called)
assert.Equal(t, tt.called, !git.called)
refs, err := client.listRefs(context.TODO(), tt.args)
if tt.expect.err == nil {
assert.NoError(t, err)
if tt.expect.refsCount > 0 {
assert.Greater(t, len(refs), 0)
}
} else {
assert.Error(t, err)
assert.Equal(t, tt.expect.err, err)
}
})
}
}
func Test_listFilesPrivateRepository(t *testing.T) {
ensureIntegrationTest(t)
client := NewGitClient(false)
type expectResult struct {
shouldFail bool
err error
matchedCount int
}
accessToken := getRequiredValue(t, "GITHUB_PAT")
username := getRequiredValue(t, "GITHUB_USERNAME")
tests := []struct {
name string
args fetchOption
expect expectResult
}{
{
name: "list tree with real repository and head ref but incorrect credential",
args: fetchOption{
baseOption: baseOption{
repositoryUrl: privateGitRepoURL,
username: "test-username",
password: "test-token",
},
referenceName: "refs/heads/main",
},
expect: expectResult{
shouldFail: true,
err: ErrAuthenticationFailure,
},
},
{
name: "list tree with real repository and head ref but no credential",
args: fetchOption{
baseOption: baseOption{
repositoryUrl: privateGitRepoURL + "fake",
username: "",
password: "",
},
referenceName: "refs/heads/main",
},
expect: expectResult{
shouldFail: true,
err: ErrAuthenticationFailure,
},
},
{
name: "list tree with real repository and head ref",
args: fetchOption{
baseOption: baseOption{
repositoryUrl: privateGitRepoURL,
username: username,
password: accessToken,
},
referenceName: "refs/heads/main",
},
expect: expectResult{
err: nil,
matchedCount: 15,
},
},
{
name: "list tree with real repository but non-existing ref",
args: fetchOption{
baseOption: baseOption{
repositoryUrl: privateGitRepoURL,
username: username,
password: accessToken,
},
referenceName: "refs/fake/feature",
},
expect: expectResult{
shouldFail: true,
},
},
{
name: "list tree with fake repository ",
args: fetchOption{
baseOption: baseOption{
repositoryUrl: privateGitRepoURL + "fake",
username: username,
password: accessToken,
},
referenceName: "refs/fake/feature",
},
expect: expectResult{
shouldFail: true,
err: ErrIncorrectRepositoryURL,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
paths, err := client.listFiles(context.TODO(), tt.args)
if tt.expect.shouldFail {
assert.Error(t, err)
if tt.expect.err != nil {
assert.Equal(t, tt.expect.err, err)
}
} else {
assert.NoError(t, err)
if tt.expect.matchedCount > 0 {
assert.Greater(t, len(paths), 0)
}
}
})
}
}