Skip to content

Commit

Permalink
[BUGFIX] - Submodules Source Fix (#799)
Browse files Browse the repository at this point in the history
Fixing the source to correctly handle submodules
  • Loading branch information
gambol99 authored Jun 7, 2023
1 parent 7b40f79 commit 5f1ac57
Show file tree
Hide file tree
Showing 2 changed files with 177 additions and 24 deletions.
64 changes: 40 additions & 24 deletions cmd/source/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,6 @@ func Run(ctx context.Context, source, destination string, timeout time.Duration,
return errors.New("timeout can not be less than zero")
}

unprefixed := strings.TrimPrefix(source, "git::")
uri, err := url.Parse(unprefixed)
if err != nil {
return fmt.Errorf("failed to parse source url: %w", err)
}
location := source

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

case os.Getenv("GIT_PASSWORD") != "" || os.Getenv("GIT_USERNAME") != "":
var src string

switch {
case os.Getenv("GIT_PASSWORD") != "" && os.Getenv("GIT_USERNAME") == "":
src = fmt.Sprintf("%s://%s@%s%s",
uri.Scheme,
os.Getenv("GIT_PASSWORD"),
uri.Hostname(), uri.Path,
)

default:
src = fmt.Sprintf("%s://%s:%s@%s%s",
uri.Scheme,
os.Getenv("GIT_USERNAME"),
os.Getenv("GIT_PASSWORD"),
uri.Hostname(), uri.Path,
)
src, dest, err := sanitizeSource(location)
if err != nil {
return fmt.Errorf("failed to parse source url: %w", err)
}

data, err := template.New(gitConfig, map[string]string{
"Source": src,
"Destination": unprefixed,
"Destination": dest,
})
if err != nil {
return fmt.Errorf("failed to create git config template: %w", err)
Expand Down Expand Up @@ -265,3 +245,39 @@ func Run(ctx context.Context, source, destination string, timeout time.Duration,
//nolint:gosec
return exec.Command("cp", []string{"-rT", "/tmp/source/", destination}...).Run()
}

// sanitizeSource is responsible for sanitizing the source url
func sanitizeSource(location string) (string, string, error) {
var source, destination string

uri, err := url.Parse(strings.TrimPrefix(location, "git::"))
if err != nil {
return "", "", err
}
path := uri.Path

if strings.Contains(uri.Path, "//") {
path = strings.Split(uri.Path, "//")[0]
}

destination = fmt.Sprintf("%s://%s%s", uri.Scheme, uri.Host, path)

switch {
case os.Getenv("GIT_PASSWORD") != "" && os.Getenv("GIT_USERNAME") == "":
source = fmt.Sprintf("%s://%s@%s%s",
uri.Scheme,
os.Getenv("GIT_PASSWORD"),
uri.Hostname(), path,
)

default:
source = fmt.Sprintf("%s://%s:%s@%s%s",
uri.Scheme,
os.Getenv("GIT_USERNAME"),
os.Getenv("GIT_PASSWORD"),
uri.Hostname(), path,
)
}

return source, destination, nil
}
137 changes: 137 additions & 0 deletions cmd/source/source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* Copyright (C) 2023 Appvia Ltd <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package main

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestSantizeSource(t *testing.T) {
/*
These will sanitize to the gitconfig urls in such a way. Note, subpaths are ignored
[url "https://[email protected]/appvia/terranetes-controller"]
insteadOf = https://github.com/appvia/terranetes-controller
[url "https://GIT_USERNAME:[email protected]/appvia/terranetes-controller"]
insteadOf = https://github.com/appvia/terranetes-controller
*/

cases := []struct {
Location string
Source string
Destination string
ExpectError bool
Environment map[string]string
}{
{
Location: "https://github.com/appvia/terranetes-controller.git",
Source: "https://user:[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_USERNAME": "user",
"GIT_PASSWORD": "pass",
},
},
{
Location: "https://github.com/appvia/terranetes-controller.git//module/test",
Source: "https://user:[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_USERNAME": "user",
"GIT_PASSWORD": "pass",
},
},
{
Location: "git::https://github.com/appvia/terranetes-controller.git//module/test",
Source: "https://user:[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_USERNAME": "user",
"GIT_PASSWORD": "pass",
},
},
{
Location: "git::https://github.com/appvia/terranetes-controller.git",
Source: "https://[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_PASSWORD": "token",
},
},
{
Location: "https://github.com/appvia/terranetes-controller.git",
Source: "https://[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_PASSWORD": "token",
},
},
{
Location: "https://github.com/appvia/terranetes-controller.git//module/source",
Source: "https://[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_PASSWORD": "token",
},
},
{
Location: "git::https://github.com/appvia/terranetes-controller.git//module/source",
Source: "https://[email protected]/appvia/terranetes-controller.git",
Destination: "https://github.com/appvia/terranetes-controller.git",
Environment: map[string]string{
"GIT_PASSWORD": "token",
},
},
{
Location: "git::https://dev.azure.com/gambol99/terranetes-controller/_git/e2e//module/submodule",
Source: "https://[email protected]/gambol99/terranetes-controller/_git/e2e",
Destination: "https://dev.azure.com/gambol99/terranetes-controller/_git/e2e",
Environment: map[string]string{
"GIT_PASSWORD": "token",
},
},
{
Location: "git::https://dev.azure.com/gambol99/terranetes-controller/_git/e2e//module/submodule",
Source: "https://user:[email protected]/gambol99/terranetes-controller/_git/e2e",
Destination: "https://dev.azure.com/gambol99/terranetes-controller/_git/e2e",
Environment: map[string]string{
"GIT_USERNAME": "user",
"GIT_PASSWORD": "token",
},
},
}
for i, c := range cases {
os.Unsetenv("GIT_PASSORD")
os.Unsetenv("GIT_USERNAME")
for k, v := range c.Environment {
assert.NoError(t, os.Setenv(k, v))
}

source, destination, err := sanitizeSource(c.Location)
if c.ExpectError {
assert.Error(t, err, "case %d, expected an error", i)
} else {
assert.NoError(t, err, "case %d, expected no error", i)
}
assert.Equal(t, c.Source, source, "case %d, expected source to match", i)
assert.Equal(t, c.Destination, destination, "case %d, expected destination to match", i)
}
}

0 comments on commit 5f1ac57

Please sign in to comment.