Skip to content

Commit

Permalink
Ensure to generate file creation URL (#635)
Browse files Browse the repository at this point in the history
**What this PR does / why we need it**:
Each deployment config template comes with a file creation URL, which is for creating a new file under the git path, with template content as default value. Something like:
https://github.com/pipe-cd/debug/new/master/kubernetes/analysis-by-metrics?filename=.pipe.yaml&value=%23+This+configures+a+non-progressive+delivery.%0AapiVersion%3A+pipecd.dev%2Fv1beta1%0Akind%3A+KubernetesApp%0Aspec%3A%0A++input%3A%0A++++manifests%3A%0A++++++-+deployment.yaml%0A++++++-+service.yaml%0A++++kubectlVersion%3A+2.1.1

Whereas, I'm getting an issue about specifying filename: isaacs/github#1527. I'll be glad to address it later.

**Which issue(s) this PR fixes**:

Fixes #627

**Does this PR introduce a user-facing change?**:
<!--
If no, just write "NONE" in the release-note block below.
-->
```release-note
NONE
```

This PR was merged by Kapetanios.
  • Loading branch information
nakabonne authored Aug 17, 2020
1 parent ec25478 commit 0891c80
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 3 deletions.
21 changes: 19 additions & 2 deletions pkg/app/api/api/web_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -818,8 +818,13 @@ func (a *WebAPI) GetCommand(ctx context.Context, req *webservice.GetCommandReque
}

func (a *WebAPI) ListDeploymentConfigTemplates(ctx context.Context, req *webservice.ListDeploymentConfigTemplatesRequest) (*webservice.ListDeploymentConfigTemplatesResponse, error) {
app, err := a.getApplication(ctx, req.ApplicationId)
if err != nil {
return nil, err
}

var templates []*webservice.DeploymentConfigTemplate
switch req.ApplicationKind {
switch app.Kind {
case model.ApplicationKind_KUBERNETES:
templates = k8sDeploymentConfigTemplates
case model.ApplicationKind_TERRAFORM:
Expand All @@ -831,7 +836,19 @@ func (a *WebAPI) ListDeploymentConfigTemplates(ctx context.Context, req *webserv
case model.ApplicationKind_CLOUDRUN:
templates = cloudrunDeploymentConfigTemplates
default:
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("unknown application kind %v", req.ApplicationKind))
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("unknown application kind %v", app.Kind))
}
for _, t := range templates {
g := app.GetGitPath()
filename := g.ConfigFilename
if filename == "" {
filename = ".pipe.yaml"
}
t.FileCreationUrl, err = git.MakeFileCreationURL(g.Repo.Remote, g.Path, g.Repo.Branch, filename, t.Content)
if err != nil {
a.logger.Error("failed to make a link to creat a file", zap.Error(err))
return nil, status.Error(codes.Internal, "failed to make a link to creat a file")
}
}

if len(req.Labels) == 0 {
Expand Down
5 changes: 4 additions & 1 deletion pkg/app/api/service/webservice/service.proto
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ message AddApplicationRequest {
}

message AddApplicationResponse {
string application_id = 1 [(validate.rules).string.min_len = 1];
}

message EnableApplicationRequest {
Expand Down Expand Up @@ -331,6 +332,8 @@ message DeploymentConfigTemplate {
string name = 2 [(validate.rules).string.min_len = 1];
repeated DeploymentConfigTemplateLabel labels = 3;
string content = 4 [(validate.rules).string.min_len = 1];
// An HTML link to create a new file under the git path, with template content as default value.
string file_creation_url = 5;
}

enum DeploymentConfigTemplateLabel {
Expand All @@ -339,7 +342,7 @@ enum DeploymentConfigTemplateLabel {
}

message ListDeploymentConfigTemplatesRequest {
pipe.model.ApplicationKind application_kind = 1 [(validate.rules).enum.defined_only = true];
string application_id = 1 [(validate.rules).string.min_len = 1];
repeated DeploymentConfigTemplateLabel labels = 2;
}

Expand Down
36 changes: 36 additions & 0 deletions pkg/git/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,42 @@ func MakeDirURL(repoURL, dir, branch string) (string, error) {
return fmt.Sprintf("%s://%s/%s/%s/%s/%s", scheme, u.Host, repoPath, subPath, branch, dir), nil
}

// MakeFileCreationURL builds a link to create a file under the given directory.
func MakeFileCreationURL(repoURL, dir, branch, filename, value string) (string, error) {
if branch == "" {
return "", fmt.Errorf("no branch given")
}
u, err := parseGitURL(repoURL)
if err != nil {
return "", err
}

if u.Scheme == "ssh" {
u.Scheme = "https"
u.User = nil
}
repoPath := strings.TrimSuffix(strings.Trim(u.Path, "/"), ".git")
dir = strings.Trim(dir, "/")

switch u.Host {
case "github.com":
u.Path = fmt.Sprintf("%s/%s/%s/%s", repoPath, "new", branch, dir)
params := &url.Values{}
if filename != "" {
params.Add("filename", filename)
}
if value != "" {
params.Add("value", value)
}
u.RawQuery = params.Encode()
default:
// TODO: Allow users to specify git host
u.Path = fmt.Sprintf("%s/%s/%s/%s", repoPath, "new", branch, dir)
}

return u.String(), nil
}

var (
knownSchemes = map[string]interface{}{
"ssh": struct{}{},
Expand Down
69 changes: 69 additions & 0 deletions pkg/git/url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,75 @@ func TestMakeDirURL(t *testing.T) {
})
}
}

func TestMakeFileCreationURL(t *testing.T) {
tests := []struct {
name string
repoURL string
dir string
branch string
filename string
value string
want string
wantErr bool
}{
{
name: "given filename",
repoURL: "git@github.com:org/repo.git",
dir: "path/to",
branch: "abc",
filename: "foo.txt",
want: "https://github.com/org/repo/new/abc/path/to?filename=foo.txt",
wantErr: false,
},
{
name: "given filename and value",
repoURL: "git@github.com:org/repo.git",
dir: "path/to",
branch: "abc",
filename: "foo.txt",
value: `# Comment
foo:
bar:
baz:
- a
- b
`,
want: "https://github.com/org/repo/new/abc/path/to?filename=foo.txt&value=%23+Comment%0Afoo%3A%0A++bar%3A%0A++++baz%3A%0A++++++-+a%0A++++++-+b%0A",
wantErr: false,
},
{
name: "ssh to unsupported git host",
repoURL: "git@foo.com:org/repo.git",
dir: "path/to",
branch: "abc",
want: "https://foo.com/org/repo/new/abc/path/to",
wantErr: false,
},
{
name: "no branch given",
repoURL: "1234abcd",
dir: "path/to",
wantErr: true,
},
{
name: "unparseable url",
repoURL: "1234abcd",
dir: "path/to",
branch: "abc",
want: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := MakeFileCreationURL(tt.repoURL, tt.dir, tt.branch, tt.filename, tt.value)
assert.Equal(t, tt.wantErr, err != nil)
assert.Equal(t, tt.want, got)
})
}
}

func TestParseGitURL(t *testing.T) {
tests := []struct {
name string
Expand Down

0 comments on commit 0891c80

Please sign in to comment.