Construct git remote URL if CloneURL is configured

Previously, GitLab CE/EE exposed the clone/fetch url, however, in more
complex situations where e.g. a firewall is in play this won't work.

If the user configures a `CloneURL` this URL is used to construct a
clone or fetch path. The URL _must_ start with `http` or `https`.
parent 60c24dad
Pipeline #12447366 passed with stages
in 22 minutes and 48 seconds
......@@ -470,6 +470,25 @@ func (b *Build) GetAllVariables() JobVariables {
return b.allVariables
// GetRemoteURL checks if the default clone URL is overwritten by the runner
// configuration option: 'CloneURL'. If it is, we use that to create the clone
// URL.
func (b *Build) GetRemoteURL() string {
cloneURL := strings.TrimRight(b.Runner.CloneURL, "/")
if !strings.HasPrefix(cloneURL, "http") {
return b.GitInfo.RepoURL
variables := b.GetAllVariables()
ciJobToken := variables.Get("CI_JOB_TOKEN")
ciProjectPath := variables.Get("CI_PROJECT_PATH")
splits := strings.SplitAfterN(cloneURL, "://", 2)
return fmt.Sprintf("%sgitlab-ci-token:%s@%s/%s.git", splits[0], ciJobToken, splits[1], ciProjectPath)
func (b *Build) GetGitDepth() string {
return b.GetAllVariables().Get("GIT_DEPTH")
......@@ -486,3 +486,44 @@ func TestSharedEnvVariables(t *testing.T) {
func TestGetRemoteURL(t *testing.T) {
testCases := []struct {
runner RunnerSettings
result string
runner: RunnerSettings{
CloneURL: "http://test.local/",
result: "http://gitlab-ci-token:1234567@test.local/h5bp/html5-boilerplate.git",
runner: RunnerSettings{
CloneURL: "https://test.local",
result: "https://gitlab-ci-token:1234567@test.local/h5bp/html5-boilerplate.git",
runner: RunnerSettings{},
result: "http://fallback.url",
for _, tc := range testCases {
build := &Build{
Runner: &RunnerConfig{
RunnerSettings: tc.runner,
allVariables: JobVariables{
JobVariable{Key: "CI_JOB_TOKEN", Value: "1234567"},
JobVariable{Key: "CI_PROJECT_PATH", Value: "h5bp/html5-boilerplate"},
JobResponse: JobResponse{
GitInfo: GitInfo{RepoURL: "http://fallback.url"},
assert.Equal(t, tc.result, build.GetRemoteURL())
......@@ -227,6 +227,7 @@ type RunnerSettings struct {
Executor string `toml:"executor" json:"executor" long:"executor" env:"RUNNER_EXECUTOR" required:"true" description:"Select executor, eg. shell, docker, etc."`
BuildsDir string `toml:"builds_dir,omitempty" json:"builds_dir" long:"builds-dir" env:"RUNNER_BUILDS_DIR" description:"Directory where builds are stored"`
CacheDir string `toml:"cache_dir,omitempty" json:"cache_dir" long:"cache-dir" env:"RUNNER_CACHE_DIR" description:"Directory where build cache is stored"`
CloneURL string `toml:"clone_url,omitempty" json:"clone_url" long:"clone-url" env:"CLONE_URL" description:"Overwrite the default URL used to clone or fetch the git ref"`
Environment []string `toml:"environment,omitempty" json:"environment" long:"env" env:"RUNNER_ENV" description:"Custom environment variables injected to build environment"`
PreCloneScript string `toml:"pre_clone_script,omitempty" json:"pre_clone_script" long:"pre-clone-script" env:"RUNNER_PRE_CLONE_SCRIPT" description:"Runner-specific command script executed before code is pulled"`
......@@ -52,6 +52,7 @@ This defines one runner entry.
| `pre_clone_script` | commands to be executed on the runner before cloning the Git repository. this can be used to adjust the Git client configuration first, for example. To insert multiple commands, use a (triple-quoted) multi-line string or "\n" character. |
| `pre_build_script` | commands to be executed on the runner after cloning the Git repository, but before executing the build. To insert multiple commands, use a (triple-quoted) multi-line string or "\n" character. |
| `post_build_script` | commands to be executed on the runner just after executing the build, but before executing `after_script`. To insert multiple commands, use a (triple-quoted) multi-line string or "\n" character. |
| `clone_url` | Overwrite the URL for the GitLab instance. Used if the runner can't connect to GitLab on the URL GitLab exposes itself. |
......@@ -65,8 +66,20 @@ Example:
builds_dir = ""
shell = ""
environment = ["ENV=value", "LC_ALL=en_US.UTF-8"]
clone_url = "http://gitlab.example.local"
### How `clone_url` works
In cases where the GitLab instance is exposed to an URL which can't be used
by the runner, a `clone_url` can be configured. For example; GitLab is exposed
to ``, but the runner can't reach that because of
a firewall setup. If the runner can reach the node on ``,
the `clone_url` should be set to `"`.
Only if the `clone_url` is set, the runner will construct a clone URL in the form
of `http://gitlab-ci-token:s3cr3tt0k3n@`.
There are a couple of available executors currently.
......@@ -37,7 +37,7 @@ func (b *AbstractShell) writeGitExports(w ShellWriter, info common.ShellScriptIn
func (b *AbstractShell) writeCloneCmd(w ShellWriter, build *common.Build, projectDir string) {
templateDir := w.MkTmpDir("git-template")
args := []string{"clone", "--no-checkout", build.GitInfo.RepoURL, projectDir, "--template", templateDir}
args := []string{"clone", "--no-checkout", build.GetRemoteURL(), projectDir, "--template", templateDir}
w.Command("git", "config", "-f", path.Join(templateDir, "config"), "fetch.recurseSubmodules", "false")
......@@ -76,7 +76,7 @@ func (b *AbstractShell) writeFetchCmd(w ShellWriter, build *common.Build, projec
w.Command("git", "clean", "-ffdx")
w.Command("git", "reset", "--hard")
w.Command("git", "remote", "set-url", "origin", build.GitInfo.RepoURL)
w.Command("git", "remote", "set-url", "origin", build.GetRemoteURL())
if depth != "" {
var refspec string
if build.GitInfo.RefType == common.RefTypeTag {
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment