Skip to content

Commit 5f1ac57

Browse files
authored
[BUGFIX] - Submodules Source Fix (#799)
Fixing the source to correctly handle submodules
1 parent 7b40f79 commit 5f1ac57

File tree

2 files changed

+177
-24
lines changed

2 files changed

+177
-24
lines changed

cmd/source/source.go

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,6 @@ func Run(ctx context.Context, source, destination string, timeout time.Duration,
8989
return errors.New("timeout can not be less than zero")
9090
}
9191

92-
unprefixed := strings.TrimPrefix(source, "git::")
93-
uri, err := url.Parse(unprefixed)
94-
if err != nil {
95-
return fmt.Errorf("failed to parse source url: %w", err)
96-
}
9792
location := source
9893

9994
// @step: check for an ssh key in the environment variables and provision a configuration
@@ -121,28 +116,13 @@ func Run(ctx context.Context, source, destination string, timeout time.Duration,
121116
}
122117

123118
case os.Getenv("GIT_PASSWORD") != "" || os.Getenv("GIT_USERNAME") != "":
124-
var src string
125-
126-
switch {
127-
case os.Getenv("GIT_PASSWORD") != "" && os.Getenv("GIT_USERNAME") == "":
128-
src = fmt.Sprintf("%s://%s@%s%s",
129-
uri.Scheme,
130-
os.Getenv("GIT_PASSWORD"),
131-
uri.Hostname(), uri.Path,
132-
)
133-
134-
default:
135-
src = fmt.Sprintf("%s://%s:%s@%s%s",
136-
uri.Scheme,
137-
os.Getenv("GIT_USERNAME"),
138-
os.Getenv("GIT_PASSWORD"),
139-
uri.Hostname(), uri.Path,
140-
)
119+
src, dest, err := sanitizeSource(location)
120+
if err != nil {
121+
return fmt.Errorf("failed to parse source url: %w", err)
141122
}
142-
143123
data, err := template.New(gitConfig, map[string]string{
144124
"Source": src,
145-
"Destination": unprefixed,
125+
"Destination": dest,
146126
})
147127
if err != nil {
148128
return fmt.Errorf("failed to create git config template: %w", err)
@@ -265,3 +245,39 @@ func Run(ctx context.Context, source, destination string, timeout time.Duration,
265245
//nolint:gosec
266246
return exec.Command("cp", []string{"-rT", "/tmp/source/", destination}...).Run()
267247
}
248+
249+
// sanitizeSource is responsible for sanitizing the source url
250+
func sanitizeSource(location string) (string, string, error) {
251+
var source, destination string
252+
253+
uri, err := url.Parse(strings.TrimPrefix(location, "git::"))
254+
if err != nil {
255+
return "", "", err
256+
}
257+
path := uri.Path
258+
259+
if strings.Contains(uri.Path, "//") {
260+
path = strings.Split(uri.Path, "//")[0]
261+
}
262+
263+
destination = fmt.Sprintf("%s://%s%s", uri.Scheme, uri.Host, path)
264+
265+
switch {
266+
case os.Getenv("GIT_PASSWORD") != "" && os.Getenv("GIT_USERNAME") == "":
267+
source = fmt.Sprintf("%s://%s@%s%s",
268+
uri.Scheme,
269+
os.Getenv("GIT_PASSWORD"),
270+
uri.Hostname(), path,
271+
)
272+
273+
default:
274+
source = fmt.Sprintf("%s://%s:%s@%s%s",
275+
uri.Scheme,
276+
os.Getenv("GIT_USERNAME"),
277+
os.Getenv("GIT_PASSWORD"),
278+
uri.Hostname(), path,
279+
)
280+
}
281+
282+
return source, destination, nil
283+
}

cmd/source/source_test.go

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Copyright (C) 2023 Appvia Ltd <info@appvia.io>
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version 2
7+
* of the License, or (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package main
19+
20+
import (
21+
"os"
22+
"testing"
23+
24+
"github.com/stretchr/testify/assert"
25+
)
26+
27+
func TestSantizeSource(t *testing.T) {
28+
/*
29+
These will sanitize to the gitconfig urls in such a way. Note, subpaths are ignored
30+
31+
[url "https://GIT_PASSWORD@github.com/appvia/terranetes-controller"]
32+
insteadOf = https://github.com/appvia/terranetes-controller
33+
[url "https://GIT_USERNAME:GIT_PASSWORD@github.com/appvia/terranetes-controller"]
34+
insteadOf = https://github.com/appvia/terranetes-controller
35+
*/
36+
37+
cases := []struct {
38+
Location string
39+
Source string
40+
Destination string
41+
ExpectError bool
42+
Environment map[string]string
43+
}{
44+
{
45+
Location: "https://github.com/appvia/terranetes-controller.git",
46+
Source: "https://user:pass@github.com/appvia/terranetes-controller.git",
47+
Destination: "https://github.com/appvia/terranetes-controller.git",
48+
Environment: map[string]string{
49+
"GIT_USERNAME": "user",
50+
"GIT_PASSWORD": "pass",
51+
},
52+
},
53+
{
54+
Location: "https://github.com/appvia/terranetes-controller.git//module/test",
55+
Source: "https://user:pass@github.com/appvia/terranetes-controller.git",
56+
Destination: "https://github.com/appvia/terranetes-controller.git",
57+
Environment: map[string]string{
58+
"GIT_USERNAME": "user",
59+
"GIT_PASSWORD": "pass",
60+
},
61+
},
62+
{
63+
Location: "git::https://github.com/appvia/terranetes-controller.git//module/test",
64+
Source: "https://user:pass@github.com/appvia/terranetes-controller.git",
65+
Destination: "https://github.com/appvia/terranetes-controller.git",
66+
Environment: map[string]string{
67+
"GIT_USERNAME": "user",
68+
"GIT_PASSWORD": "pass",
69+
},
70+
},
71+
{
72+
Location: "git::https://github.com/appvia/terranetes-controller.git",
73+
Source: "https://token@github.com/appvia/terranetes-controller.git",
74+
Destination: "https://github.com/appvia/terranetes-controller.git",
75+
Environment: map[string]string{
76+
"GIT_PASSWORD": "token",
77+
},
78+
},
79+
{
80+
Location: "https://github.com/appvia/terranetes-controller.git",
81+
Source: "https://token@github.com/appvia/terranetes-controller.git",
82+
Destination: "https://github.com/appvia/terranetes-controller.git",
83+
Environment: map[string]string{
84+
"GIT_PASSWORD": "token",
85+
},
86+
},
87+
{
88+
Location: "https://github.com/appvia/terranetes-controller.git//module/source",
89+
Source: "https://token@github.com/appvia/terranetes-controller.git",
90+
Destination: "https://github.com/appvia/terranetes-controller.git",
91+
Environment: map[string]string{
92+
"GIT_PASSWORD": "token",
93+
},
94+
},
95+
{
96+
Location: "git::https://github.com/appvia/terranetes-controller.git//module/source",
97+
Source: "https://token@github.com/appvia/terranetes-controller.git",
98+
Destination: "https://github.com/appvia/terranetes-controller.git",
99+
Environment: map[string]string{
100+
"GIT_PASSWORD": "token",
101+
},
102+
},
103+
{
104+
Location: "git::https://dev.azure.com/gambol99/terranetes-controller/_git/e2e//module/submodule",
105+
Source: "https://token@dev.azure.com/gambol99/terranetes-controller/_git/e2e",
106+
Destination: "https://dev.azure.com/gambol99/terranetes-controller/_git/e2e",
107+
Environment: map[string]string{
108+
"GIT_PASSWORD": "token",
109+
},
110+
},
111+
{
112+
Location: "git::https://dev.azure.com/gambol99/terranetes-controller/_git/e2e//module/submodule",
113+
Source: "https://user:token@dev.azure.com/gambol99/terranetes-controller/_git/e2e",
114+
Destination: "https://dev.azure.com/gambol99/terranetes-controller/_git/e2e",
115+
Environment: map[string]string{
116+
"GIT_USERNAME": "user",
117+
"GIT_PASSWORD": "token",
118+
},
119+
},
120+
}
121+
for i, c := range cases {
122+
os.Unsetenv("GIT_PASSORD")
123+
os.Unsetenv("GIT_USERNAME")
124+
for k, v := range c.Environment {
125+
assert.NoError(t, os.Setenv(k, v))
126+
}
127+
128+
source, destination, err := sanitizeSource(c.Location)
129+
if c.ExpectError {
130+
assert.Error(t, err, "case %d, expected an error", i)
131+
} else {
132+
assert.NoError(t, err, "case %d, expected no error", i)
133+
}
134+
assert.Equal(t, c.Source, source, "case %d, expected source to match", i)
135+
assert.Equal(t, c.Destination, destination, "case %d, expected destination to match", i)
136+
}
137+
}

0 commit comments

Comments
 (0)