Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion service/runway/server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,14 @@ func (m *mergerConfig) normalizeAndValidateGitHub(where string) error {
if m.Host == "" {
m.Host = defaultGitHubHost
}
if strings.ContainsAny(m.Host, "/ \t") {
return fmt.Errorf(
"%s: github merger host %q must be a host[:port] such as %q, without scheme or path",
where,
m.Host,
defaultGitHubHost,
)
}
if m.Target == "" {
m.Target = "main"
}
Expand All @@ -306,7 +314,15 @@ func parseOptionalDuration(v string) (time.Duration, error) {
if v == "" {
return 0, nil
}
return time.ParseDuration(v)
d, err := time.ParseDuration(v)
if err != nil {
return 0, err
}
if d < 0 {
return 0, fmt.Errorf("duration %q must not be negative", v)
}

return d, nil
}

// firstDifference reports the first field in which two git mergers disagree,
Expand Down
32 changes: 32 additions & 0 deletions service/runway/server/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -592,3 +592,35 @@ func TestMergerConfig_Provisions(t *testing.T) {
owned := mergerConfig{Type: mergerTypeGit, CheckoutPath: "/var/checkouts/r", RemoteURL: "https://example.com/o/r.git"}
assert.True(t, owned.provisions())
}

func TestLoadMergeConfig_GitHubDurationAndHostValidation(t *testing.T) {
tests := []struct {
name string
extra string
wantErr bool
}{
{name: "defaults", extra: ""},
{name: "valid durations", extra: " httpTimeout: 30s\n pollInterval: 2s\n maxPollDuration: 5m\n"},
{name: "host with port", extra: " host: ghe.example.com:8443\n"},
{name: "negative httpTimeout", extra: " httpTimeout: -1s\n", wantErr: true},
{name: "negative pollInterval", extra: " pollInterval: -1s\n", wantErr: true},
{name: "negative maxPollDuration", extra: " maxPollDuration: -1m\n", wantErr: true},
{name: "host with scheme", extra: " host: https://github.com\n", wantErr: true},
{name: "host with path", extra: " host: github.com/path\n", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
path := filepath.Join(t.TempDir(), "merge.yaml")
yaml := "defaults:\n merger:\n type: github\n owner: uber\n repo: submitqueue\n" + tt.extra
require.NoError(t, os.WriteFile(path, []byte(yaml), 0o600))

_, err := loadMergeConfig(path)

if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}