Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 7acc246

Browse files
committedMay 2, 2023
updating tests
Signed-off-by: Michael Hoang <[email protected]>
1 parent b2357c7 commit 7acc246

File tree

9 files changed

+344
-309
lines changed

9 files changed

+344
-309
lines changed
 

‎README.md

+21-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ The Devfile Parser library is a Golang module that:
1212
2. writes to the devfile.yaml with the updated data.
1313
3. generates Kubernetes objects for the various devfile resources.
1414
4. defines util functions for the devfile.
15+
5. downloads resources from a parent devfile if specified in the devfile.yaml
1516

16-
## Private Repository Support
17+
## Private repository support
1718

1819
Tokens are required to be set in the following cases:
1920
1. parsing a devfile from a private repository
@@ -24,19 +25,28 @@ Set the token for the repository:
2425
```go
2526
parser.ParserArgs{
2627
...
27-
URL: <url-to-devfile-on-supported-git-provider>
28+
// URL must point to a devfile.yaml
29+
URL: <url-to-devfile-on-supported-git-provider-repo>/devfile.yaml
2830
Token: <repo-personal-access-token>
2931
...
3032
}
3133
```
3234
Note: The url must also be set with a supported git provider repo url.
3335

36+
Minimum token scope required:
37+
1. GitHub: Read access to code
38+
2. GitLab: Read repository
39+
3. Bitbucket: Read repository
40+
41+
Note: To select token scopes for GitHub, a fine-grained token is required.
42+
3443
For more information about personal access tokens:
3544
1. [GitHub docs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
3645
2. [GitLab docs](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token)
3746
3. [Bitbucket docs](https://support.atlassian.com/bitbucket-cloud/docs/repository-access-tokens/)
3847

3948
[1] Currently, this works under the assumption that the token can authenticate the devfile and the parent devfile; both devfiles are in the same repository.
49+
4050
[2] In this scenario, the token will be used to authenticate the main devfile.
4151

4252
## Usage
@@ -199,6 +209,15 @@ The function documentation can be accessed via [pkg.go.dev](https://pkg.go.dev/g
199209
}
200210
```
201211

212+
9. When parsing a devfile that contains a parent reference, if the parent uri is a supported git provider repo url with the correct personal access token, all resources from the parent git repo excluding the parent devfile.yaml will be downloaded to the location of the devfile being parsed. **Note: The URL must point to a devfile.yaml**
213+
```yaml
214+
schemaVersion: 2.2.0
215+
...
216+
parent:
217+
uri: <uri-to-parent-devfile>/devfile.yaml
218+
...
219+
```
220+
202221
## Projects using devfile/library
203222

204223
The following projects are consuming this library as a Golang dependency

‎pkg/devfile/parser/context/context.go

+5-8
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,6 @@ func NewURLDevfileCtx(url string) DevfileCtx {
7373
}
7474
}
7575

76-
// NewPrivateURLDevfileCtx returns a new DevfileCtx type object
77-
func NewPrivateURLDevfileCtx(url string, token string) DevfileCtx {
78-
return DevfileCtx{
79-
url: url,
80-
token: token,
81-
}
82-
}
83-
8476
// NewByteContentDevfileCtx set devfile content from byte data and returns a new DevfileCtx type object and error
8577
func NewByteContentDevfileCtx(data []byte) (d DevfileCtx, err error) {
8678
err = d.SetDevfileContentFromBytes(data)
@@ -166,6 +158,11 @@ func (d *DevfileCtx) GetToken() string {
166158
return d.token
167159
}
168160

161+
// SetToken sets the token for the devfile
162+
func (d *DevfileCtx) SetToken(token string) {
163+
d.token = token
164+
}
165+
169166
// SetAbsPath sets absolute file path for devfile
170167
func (d *DevfileCtx) SetAbsPath() (err error) {
171168
// Set devfile absolute path

‎pkg/devfile/parser/context/context_test.go

+2-6
Original file line numberDiff line numberDiff line change
@@ -88,16 +88,12 @@ func TestNewURLDevfileCtx(t *testing.T) {
8888
token = "fake-token"
8989
url = "https://github.com/devfile/registry/blob/main/stacks/go/2.0.0/devfile.yaml"
9090
)
91-
92-
{
93-
d := NewPrivateURLDevfileCtx(url, token)
94-
assert.Equal(t, "https://github.com/devfile/registry/blob/main/stacks/go/2.0.0/devfile.yaml", d.GetURL())
95-
assert.Equal(t, "fake-token", d.GetToken())
96-
}
9791
{
9892
d := NewURLDevfileCtx(url)
9993
assert.Equal(t, "https://github.com/devfile/registry/blob/main/stacks/go/2.0.0/devfile.yaml", d.GetURL())
10094
assert.Equal(t, "", d.GetToken())
95+
d.SetToken(token)
96+
assert.Equal(t, "fake-token", d.GetToken())
10197
}
10298
}
10399

‎pkg/devfile/parser/parse.go

+29-14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"encoding/json"
2121
"fmt"
2222
"github.com/devfile/library/v2/pkg/git"
23+
"github.com/hashicorp/go-multierror"
2324
"io/ioutil"
2425
"net/url"
2526
"os"
@@ -49,34 +50,49 @@ import (
4950

5051
// downloadGitRepoResources is exposed as a global variable for the purpose of running mock tests
5152
var downloadGitRepoResources = func(url string, destDir string, httpTimeout *int, token string) error {
53+
var returnedErr error
54+
5255
gitUrl, err := git.NewGitUrlWithURL(url)
5356
if err != nil {
5457
return err
5558
}
5659

57-
if gitUrl.IsGitProviderRepo() && gitUrl.IsFile {
58-
stackDir, err := ioutil.TempDir(os.TempDir(), fmt.Sprintf("git-resources"))
60+
if gitUrl.IsGitProviderRepo() {
61+
if !gitUrl.IsFile || gitUrl.Revision == "" || !strings.Contains(gitUrl.Path, OutputDevfileYamlPath) {
62+
return fmt.Errorf("error getting devfile from url: failed to retrieve %s", url)
63+
}
64+
65+
stackDir, err := os.MkdirTemp("", fmt.Sprintf("git-resources"))
5966
if err != nil {
6067
return fmt.Errorf("failed to create dir: %s, error: %v", stackDir, err)
6168
}
62-
defer os.RemoveAll(stackDir)
69+
70+
defer func(path string) {
71+
err := os.RemoveAll(path)
72+
if err != nil {
73+
returnedErr = multierror.Append(returnedErr, err)
74+
}
75+
}(stackDir)
6376

6477
if !gitUrl.IsPublic(httpTimeout) {
6578
err = gitUrl.SetToken(token, httpTimeout)
6679
if err != nil {
67-
return err
80+
returnedErr = multierror.Append(returnedErr, err)
81+
return returnedErr
6882
}
6983
}
7084

7185
err = gitUrl.CloneGitRepo(stackDir)
7286
if err != nil {
73-
return err
87+
returnedErr = multierror.Append(returnedErr, err)
88+
return returnedErr
7489
}
7590

7691
dir := path.Dir(path.Join(stackDir, gitUrl.Path))
7792
err = git.CopyAllDirFiles(dir, destDir)
7893
if err != nil {
79-
return err
94+
returnedErr = multierror.Append(returnedErr, err)
95+
return returnedErr
8096
}
8197
}
8298

@@ -163,15 +179,15 @@ func ParseDevfile(args ParserArgs) (d DevfileObj, err error) {
163179
} else if args.Path != "" {
164180
d.Ctx = devfileCtx.NewDevfileCtx(args.Path)
165181
} else if args.URL != "" {
166-
if args.Token != "" {
167-
d.Ctx = devfileCtx.NewPrivateURLDevfileCtx(args.URL, args.Token)
168-
} else {
169-
d.Ctx = devfileCtx.NewURLDevfileCtx(args.URL)
170-
}
182+
d.Ctx = devfileCtx.NewURLDevfileCtx(args.URL)
171183
} else {
172184
return d, errors.Wrap(err, "the devfile source is not provided")
173185
}
174186

187+
if args.Token != "" {
188+
d.Ctx.SetToken(args.Token)
189+
}
190+
175191
tool := resolverTools{
176192
defaultNamespace: args.DefaultNamespace,
177193
registryURLs: args.RegistryURLs,
@@ -475,10 +491,9 @@ func parseFromURI(importReference v1.ImportReference, curDevfileCtx devfileCtx.D
475491
}
476492

477493
token := curDevfileCtx.GetToken()
494+
d.Ctx = devfileCtx.NewURLDevfileCtx(newUri)
478495
if token != "" {
479-
d.Ctx = devfileCtx.NewPrivateURLDevfileCtx(newUri, token)
480-
} else {
481-
d.Ctx = devfileCtx.NewURLDevfileCtx(newUri)
496+
d.Ctx.SetToken(token)
482497
}
483498

484499
destDir := path.Dir(curDevfileCtx.GetAbsPath())

‎pkg/devfile/parser/parse_test.go

+187-170
Large diffs are not rendered by default.

‎pkg/git/git.go

+21-16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package git
1818
import (
1919
"fmt"
2020
"net/url"
21+
"os"
2122
"os/exec"
2223
"path/filepath"
2324
"strings"
@@ -30,19 +31,19 @@ const (
3031
BitbucketHost string = "bitbucket.org"
3132
)
3233

33-
type Url struct {
34+
type GitUrl struct {
3435
Protocol string // URL scheme
3536
Host string // URL domain name
3637
Owner string // name of the repo owner
3738
Repo string // name of the repo
3839
Revision string // branch name, tag name, or commit id
3940
Path string // path to a directory or file in the repo
40-
token string // used for authenticating a private repo
41+
token string // authenticates private repo actions for parent devfiles
4142
IsFile bool // defines if the URL points to a file in the repo
4243
}
4344

4445
// NewGitUrlWithURL NewGitUrl creates a GitUrl from a string url
45-
func NewGitUrlWithURL(url string) (Url, error) {
46+
func NewGitUrlWithURL(url string) (GitUrl, error) {
4647
gitUrl, err := ParseGitUrl(url)
4748
if err != nil {
4849
return gitUrl, err
@@ -52,8 +53,8 @@ func NewGitUrlWithURL(url string) (Url, error) {
5253

5354
// ParseGitUrl extracts information from a support git url
5455
// Only supports git repositories hosted on GitHub, GitLab, and Bitbucket
55-
func ParseGitUrl(fullUrl string) (Url, error) {
56-
var g Url
56+
func ParseGitUrl(fullUrl string) (GitUrl, error) {
57+
var g GitUrl
5758
err := ValidateURL(fullUrl)
5859
if err != nil {
5960
return g, err
@@ -81,7 +82,7 @@ func ParseGitUrl(fullUrl string) (Url, error) {
8182
return g, err
8283
}
8384

84-
func (g *Url) GetToken() string {
85+
func (g *GitUrl) GetToken() string {
8586
return g.token
8687
}
8788

@@ -106,7 +107,7 @@ var execute = func(baseDir string, cmd CommandType, args ...string) ([]byte, err
106107
return []byte(""), fmt.Errorf(unsupportedCmdMsg, string(cmd))
107108
}
108109

109-
func (g *Url) CloneGitRepo(destDir string) error {
110+
func (g *GitUrl) CloneGitRepo(destDir string) error {
110111
exist := CheckPathExists(destDir)
111112
if !exist {
112113
return fmt.Errorf("failed to clone repo, destination directory: '%s' does not exists", destDir)
@@ -140,14 +141,18 @@ func (g *Url) CloneGitRepo(destDir string) error {
140141
if g.Revision != "" {
141142
_, err := execute(destDir, "git", "switch", "--detach", "origin/"+g.Revision)
142143
if err != nil {
144+
err = os.RemoveAll(destDir)
145+
if err != nil {
146+
return err
147+
}
143148
return fmt.Errorf("failed to switch repo to revision. repo dir: %v, revision: %v", destDir, g.Revision)
144149
}
145150
}
146151

147152
return nil
148153
}
149154

150-
func (g *Url) parseGitHubUrl(url *url.URL) error {
155+
func (g *GitUrl) parseGitHubUrl(url *url.URL) error {
151156
var splitUrl []string
152157
var err error
153158

@@ -209,7 +214,7 @@ func (g *Url) parseGitHubUrl(url *url.URL) error {
209214
return err
210215
}
211216

212-
func (g *Url) parseGitLabUrl(url *url.URL) error {
217+
func (g *GitUrl) parseGitLabUrl(url *url.URL) error {
213218
var splitFile, splitOrg []string
214219
var err error
215220

@@ -257,7 +262,7 @@ func (g *Url) parseGitLabUrl(url *url.URL) error {
257262
return err
258263
}
259264

260-
func (g *Url) parseBitbucketUrl(url *url.URL) error {
265+
func (g *GitUrl) parseBitbucketUrl(url *url.URL) error {
261266
var splitUrl []string
262267
var err error
263268

@@ -295,7 +300,7 @@ func (g *Url) parseBitbucketUrl(url *url.URL) error {
295300

296301
// SetToken validates the token with a get request to the repo before setting the token
297302
// Defaults token to empty on failure.
298-
func (g *Url) SetToken(token string, httpTimeout *int) error {
303+
func (g *GitUrl) SetToken(token string, httpTimeout *int) error {
299304
err := g.validateToken(HTTPRequestParams{Token: token, Timeout: httpTimeout})
300305
if err != nil {
301306
g.token = ""
@@ -307,7 +312,7 @@ func (g *Url) SetToken(token string, httpTimeout *int) error {
307312

308313
// IsPublic checks if the GitUrl is public with a get request to the repo using an empty token
309314
// Returns true if the request succeeds
310-
func (g *Url) IsPublic(httpTimeout *int) bool {
315+
func (g *GitUrl) IsPublic(httpTimeout *int) bool {
311316
err := g.validateToken(HTTPRequestParams{Token: "", Timeout: httpTimeout})
312317
if err != nil {
313318
return false
@@ -317,7 +322,7 @@ func (g *Url) IsPublic(httpTimeout *int) bool {
317322

318323
// validateToken makes a http get request to the repo with the GitUrl token
319324
// Returns an error if the get request fails
320-
func (g *Url) validateToken(params HTTPRequestParams) error {
325+
func (g *GitUrl) validateToken(params HTTPRequestParams) error {
321326
var apiUrl string
322327

323328
switch g.Host {
@@ -341,14 +346,14 @@ func (g *Url) validateToken(params HTTPRequestParams) error {
341346
}
342347

343348
// GitRawFileAPI returns the endpoint for the git providers raw file
344-
func (g *Url) GitRawFileAPI() string {
349+
func (g *GitUrl) GitRawFileAPI() string {
345350
var apiRawFile string
346351

347352
switch g.Host {
348353
case GitHubHost, RawGitHubHost:
349354
apiRawFile = fmt.Sprintf("https://raw.githubusercontent.com/%s/%s/%s/%s", g.Owner, g.Repo, g.Revision, g.Path)
350355
case GitLabHost:
351-
apiRawFile = fmt.Sprintf("https://gitlab.com/api/v4/projects/%s%%2F%s/repository/files/%s/raw", g.Owner, g.Repo, g.Path)
356+
apiRawFile = fmt.Sprintf("https://gitlab.com/api/v4/projects/%s%%2F%s/repository/files/%s/raw?ref=%s", g.Owner, g.Repo, g.Path, g.Revision)
352357
case BitbucketHost:
353358
apiRawFile = fmt.Sprintf("https://api.bitbucket.org/2.0/repositories/%s/%s/src/%s/%s", g.Owner, g.Repo, g.Revision, g.Path)
354359
}
@@ -357,7 +362,7 @@ func (g *Url) GitRawFileAPI() string {
357362
}
358363

359364
// IsGitProviderRepo checks if the url matches a repo from a supported git provider
360-
func (g *Url) IsGitProviderRepo() bool {
365+
func (g *GitUrl) IsGitProviderRepo() bool {
361366
switch g.Host {
362367
case GitHubHost, RawGitHubHost, GitLabHost, BitbucketHost:
363368
return true

‎pkg/git/git_test.go

+56-84
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,41 @@ import (
2525
)
2626

2727
func Test_ParseGitUrl(t *testing.T) {
28+
invalidUrlError := "URL is invalid"
29+
invalidUrlPathError := "url path to directory or file should contain*"
30+
missingUserAndRepoError := "url path should contain <user>/<repo>*"
31+
32+
invalidGitHostError := "url host should be a valid GitHub, GitLab, or Bitbucket host*"
33+
invalidGitHubPathError := "url path should contain <owner>/<repo>/<tree or blob>/<branch>/<path/to/file/or/directory>*"
34+
invalidGitHubRawPathError := "raw url path should contain <owner>/<repo>/<branch>/<path/to/file>*"
35+
36+
invalidGitLabPathError := "url path to directory or file should contain <blob or tree or raw>/<branch>/<path/to/file/or/directory>*"
37+
missingGitLabKeywordError := "url path should contain 'blob' or 'tree' or 'raw'*"
38+
39+
invalidBitbucketPathError := "url path should contain path to directory or file*"
40+
missingBitbucketKeywordError := "url path should contain 'raw' or 'src'*"
41+
2842
tests := []struct {
2943
name string
3044
url string
31-
wantUrl Url
45+
wantUrl GitUrl
3246
wantErr string
3347
}{
3448
{
3549
name: "should fail with empty url",
3650
url: "",
37-
wantErr: "URL is invalid",
51+
wantErr: invalidUrlError,
3852
},
3953
{
4054
name: "should fail with invalid git host",
4155
url: "https://google.ca/",
42-
wantErr: "url host should be a valid GitHub, GitLab, or Bitbucket host*",
56+
wantErr: invalidGitHostError,
4357
},
4458
// GitHub
4559
{
4660
name: "should parse GitHub repo with root path",
4761
url: "https://github.com/devfile/library",
48-
wantUrl: Url{
62+
wantUrl: GitUrl{
4963
Protocol: "https",
5064
Host: "github.com",
5165
Owner: "devfile",
@@ -58,7 +72,7 @@ func Test_ParseGitUrl(t *testing.T) {
5872
{
5973
name: "should parse GitHub repo with root path and tag",
6074
url: "https://github.com/devfile/library/tree/v2.2.0",
61-
wantUrl: Url{
75+
wantUrl: GitUrl{
6276
Protocol: "https",
6377
Host: "github.com",
6478
Owner: "devfile",
@@ -71,7 +85,7 @@ func Test_ParseGitUrl(t *testing.T) {
7185
{
7286
name: "should parse GitHub repo with root path and revision",
7387
url: "https://github.com/devfile/library/tree/0ce592a416fb185564516353891a45016ac7f671",
74-
wantUrl: Url{
88+
wantUrl: GitUrl{
7589
Protocol: "https",
7690
Host: "github.com",
7791
Owner: "devfile",
@@ -84,12 +98,12 @@ func Test_ParseGitUrl(t *testing.T) {
8498
{
8599
name: "should fail with only GitHub host",
86100
url: "https://github.com/",
87-
wantErr: "url path should contain <user>/<repo>*",
101+
wantErr: missingUserAndRepoError,
88102
},
89103
{
90104
name: "should parse GitHub repo with file path",
91105
url: "https://github.com/devfile/library/blob/main/devfile.yaml",
92-
wantUrl: Url{
106+
wantUrl: GitUrl{
93107
Protocol: "https",
94108
Host: "github.com",
95109
Owner: "devfile",
@@ -102,7 +116,7 @@ func Test_ParseGitUrl(t *testing.T) {
102116
{
103117
name: "should parse GitHub repo with raw file path",
104118
url: "https://raw.githubusercontent.com/devfile/library/main/devfile.yaml",
105-
wantUrl: Url{
119+
wantUrl: GitUrl{
106120
Protocol: "https",
107121
Host: "raw.githubusercontent.com",
108122
Owner: "devfile",
@@ -115,38 +129,38 @@ func Test_ParseGitUrl(t *testing.T) {
115129
{
116130
name: "should fail with missing GitHub repo",
117131
url: "https://github.com/devfile",
118-
wantErr: "url path should contain <user>/<repo>*",
132+
wantErr: missingUserAndRepoError,
119133
},
120134
{
121135
name: "should fail with missing GitHub blob",
122136
url: "https://github.com/devfile/library/main/devfile.yaml",
123-
wantErr: "url path to directory or file should contain*",
137+
wantErr: invalidUrlPathError,
124138
},
125139
{
126140
name: "should fail with missing GitHub tree",
127141
url: "https://github.com/devfile/library/main/tests/yamls",
128-
wantErr: "url path to directory or file should contain*",
142+
wantErr: invalidUrlPathError,
129143
},
130144
{
131145
name: "should fail with just GitHub tree",
132146
url: "https://github.com/devfile/library/tree",
133-
wantErr: "url path should contain <owner>/<repo>/<tree or blob>/<branch>/<path/to/file/or/directory>*",
147+
wantErr: invalidGitHubPathError,
134148
},
135149
{
136150
name: "should fail with just GitHub blob",
137151
url: "https://github.com/devfile/library/blob",
138-
wantErr: "url path should contain <owner>/<repo>/<tree or blob>/<branch>/<path/to/file/or/directory>*",
152+
wantErr: invalidGitHubPathError,
139153
},
140154
{
141155
name: "should fail with invalid GitHub raw file path",
142156
url: "https://raw.githubusercontent.com/devfile/library/devfile.yaml",
143-
wantErr: "raw url path should contain <owner>/<repo>/<branch>/<path/to/file>*",
157+
wantErr: invalidGitHubRawPathError,
144158
},
145159
// Gitlab
146160
{
147161
name: "should parse GitLab repo with root path",
148162
url: "https://gitlab.com/gitlab-org/gitlab-foss",
149-
wantUrl: Url{
163+
wantUrl: GitUrl{
150164
Protocol: "https",
151165
Host: "gitlab.com",
152166
Owner: "gitlab-org",
@@ -159,12 +173,12 @@ func Test_ParseGitUrl(t *testing.T) {
159173
{
160174
name: "should fail with only GitLab host",
161175
url: "https://gitlab.com/",
162-
wantErr: "url path should contain <user>/<repo>*",
176+
wantErr: missingUserAndRepoError,
163177
},
164178
{
165179
name: "should parse GitLab repo with file path",
166180
url: "https://gitlab.com/gitlab-org/gitlab-foss/-/blob/master/README.md",
167-
wantUrl: Url{
181+
wantUrl: GitUrl{
168182
Protocol: "https",
169183
Host: "gitlab.com",
170184
Owner: "gitlab-org",
@@ -177,23 +191,23 @@ func Test_ParseGitUrl(t *testing.T) {
177191
{
178192
name: "should fail with missing GitLab repo",
179193
url: "https://gitlab.com/gitlab-org",
180-
wantErr: "url path should contain <user>/<repo>*",
194+
wantErr: missingUserAndRepoError,
181195
},
182196
{
183197
name: "should fail with missing GitLab keywords",
184198
url: "https://gitlab.com/gitlab-org/gitlab-foss/-/master/directory/README.md",
185-
wantErr: "url path should contain 'blob' or 'tree' or 'raw'*",
199+
wantErr: missingGitLabKeywordError,
186200
},
187201
{
188202
name: "should fail with missing GitLab file or directory path",
189203
url: "https://gitlab.com/gitlab-org/gitlab-foss/-/tree/master",
190-
wantErr: "url path to directory or file should contain <blob or tree or raw>/<branch>/<path/to/file/or/directory>*",
204+
wantErr: invalidGitLabPathError,
191205
},
192206
// Bitbucket
193207
{
194208
name: "should parse Bitbucket repo with root path",
195209
url: "https://bitbucket.org/fake-owner/fake-public-repo",
196-
wantUrl: Url{
210+
wantUrl: GitUrl{
197211
Protocol: "https",
198212
Host: "bitbucket.org",
199213
Owner: "fake-owner",
@@ -206,12 +220,12 @@ func Test_ParseGitUrl(t *testing.T) {
206220
{
207221
name: "should fail with only Bitbucket host",
208222
url: "https://bitbucket.org/",
209-
wantErr: "url path should contain <user>/<repo>*",
223+
wantErr: missingUserAndRepoError,
210224
},
211225
{
212226
name: "should parse Bitbucket repo with file path",
213227
url: "https://bitbucket.org/fake-owner/fake-public-repo/src/main/README.md",
214-
wantUrl: Url{
228+
wantUrl: GitUrl{
215229
Protocol: "https",
216230
Host: "bitbucket.org",
217231
Owner: "fake-owner",
@@ -224,7 +238,7 @@ func Test_ParseGitUrl(t *testing.T) {
224238
{
225239
name: "should parse Bitbucket file path with nested path",
226240
url: "https://bitbucket.org/fake-owner/fake-public-repo/src/main/directory/test.txt",
227-
wantUrl: Url{
241+
wantUrl: GitUrl{
228242
Protocol: "https",
229243
Host: "bitbucket.org",
230244
Owner: "fake-owner",
@@ -237,7 +251,7 @@ func Test_ParseGitUrl(t *testing.T) {
237251
{
238252
name: "should parse Bitbucket repo with raw file path",
239253
url: "https://bitbucket.org/fake-owner/fake-public-repo/raw/main/README.md",
240-
wantUrl: Url{
254+
wantUrl: GitUrl{
241255
Protocol: "https",
242256
Host: "bitbucket.org",
243257
Owner: "fake-owner",
@@ -250,17 +264,17 @@ func Test_ParseGitUrl(t *testing.T) {
250264
{
251265
name: "should fail with missing Bitbucket repo",
252266
url: "https://bitbucket.org/fake-owner",
253-
wantErr: "url path should contain <user>/<repo>*",
267+
wantErr: missingUserAndRepoError,
254268
},
255269
{
256270
name: "should fail with invalid Bitbucket directory or file path",
257271
url: "https://bitbucket.org/fake-owner/fake-public-repo/main/README.md",
258-
wantErr: "url path should contain path to directory or file*",
272+
wantErr: invalidBitbucketPathError,
259273
},
260274
{
261275
name: "should fail with missing Bitbucket keywords",
262276
url: "https://bitbucket.org/fake-owner/fake-public-repo/main/test/README.md",
263-
wantErr: "url path should contain 'raw' or 'src'*",
277+
wantErr: missingBitbucketKeywordError,
264278
},
265279
}
266280

@@ -281,12 +295,12 @@ func Test_ParseGitUrl(t *testing.T) {
281295
func Test_GetGitRawFileAPI(t *testing.T) {
282296
tests := []struct {
283297
name string
284-
g Url
298+
g GitUrl
285299
want string
286300
}{
287301
{
288302
name: "Github url",
289-
g: Url{
303+
g: GitUrl{
290304
Protocol: "https",
291305
Host: "github.com",
292306
Owner: "devfile",
@@ -298,19 +312,19 @@ func Test_GetGitRawFileAPI(t *testing.T) {
298312
},
299313
{
300314
name: "GitLab url",
301-
g: Url{
315+
g: GitUrl{
302316
Protocol: "https",
303317
Host: "gitlab.com",
304318
Owner: "gitlab-org",
305319
Repo: "gitlab",
306-
Revision: "master",
320+
Revision: "v15.11.0-ee",
307321
Path: "README.md",
308322
},
309-
want: "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/repository/files/README.md/raw",
323+
want: "https://gitlab.com/api/v4/projects/gitlab-org%2Fgitlab/repository/files/README.md/raw?ref=v15.11.0-ee",
310324
},
311325
{
312326
name: "Bitbucket url",
313-
g: Url{
327+
g: GitUrl{
314328
Protocol: "https",
315329
Host: "bitbucket.org",
316330
Owner: "owner",
@@ -322,7 +336,7 @@ func Test_GetGitRawFileAPI(t *testing.T) {
322336
},
323337
{
324338
name: "Empty GitUrl",
325-
g: Url{},
339+
g: GitUrl{},
326340
want: "",
327341
},
328342
}
@@ -338,7 +352,7 @@ func Test_GetGitRawFileAPI(t *testing.T) {
338352
}
339353

340354
func Test_IsPublic(t *testing.T) {
341-
publicGitUrl := Url{
355+
publicGitUrl := GitUrl{
342356
Protocol: "https",
343357
Host: "github.com",
344358
Owner: "devfile",
@@ -347,7 +361,7 @@ func Test_IsPublic(t *testing.T) {
347361
token: "fake-token",
348362
}
349363

350-
privateGitUrl := Url{
364+
privateGitUrl := GitUrl{
351365
Protocol: "https",
352366
Host: "github.com",
353367
Owner: "not",
@@ -360,7 +374,7 @@ func Test_IsPublic(t *testing.T) {
360374

361375
tests := []struct {
362376
name string
363-
g Url
377+
g GitUrl
364378
want bool
365379
}{
366380
{
@@ -387,43 +401,16 @@ func Test_IsPublic(t *testing.T) {
387401

388402
func Test_CloneGitRepo(t *testing.T) {
389403
tempInvalidDir := t.TempDir()
390-
tempDirGitHub := t.TempDir()
391-
tempDirGitLab := t.TempDir()
392-
tempDirBitbucket := t.TempDir()
393404

394-
invalidGitUrl := Url{
405+
invalidGitUrl := GitUrl{
395406
Protocol: "",
396407
Host: "",
397408
Owner: "nonexistent",
398409
Repo: "nonexistent",
399410
Revision: "nonexistent",
400411
}
401412

402-
validPublicGitHubUrl := Url{
403-
Protocol: "https",
404-
Host: "github.com",
405-
Owner: "devfile",
406-
Repo: "library",
407-
Revision: "main",
408-
}
409-
410-
validPublicGitLabUrl := Url{
411-
Protocol: "https",
412-
Host: "gitlab.com",
413-
Owner: "mike-hoang",
414-
Repo: "public-testing-repo",
415-
Revision: "main",
416-
}
417-
418-
validPublicBitbucketUrl := Url{
419-
Protocol: "https",
420-
Host: "bitbucket.org",
421-
Owner: "mike-hoang",
422-
Repo: "public-testing-repo",
423-
Revision: "master",
424-
}
425-
426-
invalidPrivateGitHubRepo := Url{
413+
invalidPrivateGitHubRepo := GitUrl{
427414
Protocol: "https",
428415
Host: "github.com",
429416
Owner: "fake-owner",
@@ -438,7 +425,7 @@ func Test_CloneGitRepo(t *testing.T) {
438425

439426
tests := []struct {
440427
name string
441-
gitUrl Url
428+
gitUrl GitUrl
442429
destDir string
443430
wantErr string
444431
}{
@@ -460,21 +447,6 @@ func Test_CloneGitRepo(t *testing.T) {
460447
destDir: tempInvalidDir,
461448
wantErr: privateRepoBadTokenErr,
462449
},
463-
{
464-
name: "should be able to clone valid public github url",
465-
gitUrl: validPublicGitHubUrl,
466-
destDir: tempDirGitHub,
467-
},
468-
{
469-
name: "should be able to clone valid public gitlab url",
470-
gitUrl: validPublicGitLabUrl,
471-
destDir: tempDirGitLab,
472-
},
473-
{
474-
name: "should be able to clone valid public bitbucket url",
475-
gitUrl: validPublicBitbucketUrl,
476-
destDir: tempDirBitbucket,
477-
},
478450
}
479451

480452
for _, tt := range tests {

‎pkg/git/mock.go

+20-7
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,43 @@ var mockExecute = func(baseDir string, cmd CommandType, args ...string) ([]byte,
4444
u, _ := url.Parse(args[1])
4545
password, hasPassword := u.User.Password()
4646

47+
resourceFile, err := os.Create(filepath.Clean(baseDir) + "/resource.file")
48+
if err != nil {
49+
return nil, fmt.Errorf("failed to create test resource: %v", err)
50+
}
51+
4752
// private repository
4853
if hasPassword {
4954
switch password {
5055
case "valid-token":
51-
_, err := os.Create(filepath.Clean(baseDir) + "/private-repo-resource.txt")
56+
_, err := resourceFile.WriteString("private repo\n")
5257
if err != nil {
53-
return nil, fmt.Errorf("failed to create test resource: %v", err)
58+
return nil, fmt.Errorf("failed to write to test resource: %v", err)
5459
}
55-
return []byte("test"), nil
60+
return []byte(""), nil
5661
default:
5762
return []byte(""), fmt.Errorf("not a valid token")
5863
}
5964
}
60-
// public repository
61-
_, err := os.Create(filepath.Clean(baseDir) + "/public-repo-resource.txt")
65+
66+
_, err = resourceFile.WriteString("public repo\n")
6267
if err != nil {
63-
return nil, fmt.Errorf("failed to create test resource: %v", err)
68+
return nil, fmt.Errorf("failed to write to test resource: %v", err)
6469
}
65-
return []byte("test"), nil
70+
return []byte(""), nil
6671
}
6772

6873
if len(args) > 0 && args[0] == "switch" {
6974
revision := strings.TrimPrefix(args[2], "origin/")
7075
if revision != "invalid-revision" {
76+
resourceFile, err := os.OpenFile(filepath.Clean(baseDir)+"/resource.file", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
77+
if err != nil {
78+
return nil, fmt.Errorf("failed to open test resource: %v", err)
79+
}
80+
_, err = resourceFile.WriteString("git switched")
81+
if err != nil {
82+
return nil, fmt.Errorf("failed to write to test resource: %v", err)
83+
}
7184
return []byte("git switched to revision"), nil
7285
}
7386
return []byte(""), fmt.Errorf("failed to switch revision")

‎pkg/util/util.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -1100,7 +1100,7 @@ func DownloadInMemory(params HTTPRequestParams) ([]byte, error) {
11001100
ResponseHeaderTimeout: HTTPRequestResponseTimeout,
11011101
}, Timeout: HTTPRequestResponseTimeout}
11021102

1103-
var g git.Url
1103+
var g git.GitUrl
11041104
var err error
11051105

11061106
if IsGitProviderRepo(params.URL) {
@@ -1113,7 +1113,7 @@ func DownloadInMemory(params HTTPRequestParams) ([]byte, error) {
11131113
return downloadInMemoryWithClient(params, httpClient, g)
11141114
}
11151115

1116-
func downloadInMemoryWithClient(params HTTPRequestParams, httpClient HTTPClient, g git.Url) ([]byte, error) {
1116+
func downloadInMemoryWithClient(params HTTPRequestParams, httpClient HTTPClient, g git.GitUrl) ([]byte, error) {
11171117
var url string
11181118
url = params.URL
11191119
req, err := http.NewRequest("GET", url, nil)
@@ -1128,6 +1128,7 @@ func downloadInMemoryWithClient(params HTTPRequestParams, httpClient HTTPClient,
11281128
return nil, err
11291129
}
11301130
if !g.IsPublic(params.Timeout) {
1131+
// check that the token is valid before adding to the header
11311132
err = g.SetToken(params.Token, params.Timeout)
11321133
if err != nil {
11331134
return nil, err

0 commit comments

Comments
 (0)
Please sign in to comment.