project create: user project path

Use project path for project creation and get the project clone url directly
from the remote source
This commit is contained in:
Simone Gotti 2019-04-03 11:07:54 +02:00
parent 6736f5aebc
commit 3d39553189
8 changed files with 84 additions and 39 deletions

View File

@ -36,7 +36,7 @@ var cmdProjectCreate = &cobra.Command{
type projectCreateOptions struct {
name string
parentPath string
repoURL string
repoPath string
remoteSourceName string
skipSSHHostKeyCheck bool
}
@ -47,7 +47,7 @@ func init() {
flags := cmdProjectCreate.Flags()
flags.StringVarP(&projectCreateOpts.name, "name", "n", "", "project name")
flags.StringVar(&projectCreateOpts.repoURL, "repo-url", "", "repository url")
flags.StringVar(&projectCreateOpts.repoPath, "repo-path", "", "repository path (i.e agola-io/agola)")
flags.StringVar(&projectCreateOpts.remoteSourceName, "remote-source", "", "remote source name")
flags.BoolVarP(&projectCreateOpts.skipSSHHostKeyCheck, "skip-ssh-host-key-check", "s", false, "skip ssh host key check")
flags.StringVar(&projectCreateOpts.parentPath, "parent", "", `parent project group path (i.e "org/org01" for root project group in org01, "user/user01/group01/subgroub01") or project group id where the project should be created`)
@ -66,7 +66,7 @@ func projectCreate(cmd *cobra.Command, args []string) error {
req := &api.CreateProjectRequest{
Name: projectCreateOpts.name,
ParentID: projectCreateOpts.parentPath,
RepoURL: projectCreateOpts.repoURL,
RepoPath: projectCreateOpts.repoPath,
RemoteSourceName: projectCreateOpts.remoteSourceName,
SkipSSHHostKeyCheck: projectCreateOpts.skipSSHHostKeyCheck,
}

View File

@ -127,6 +127,10 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
return nil, nil
}
func (c *Client) GetRepoInfo(owner, reponame string) (*gitsource.RepoInfo, error) {
return nil, nil
}
func (c *Client) GetFile(owner, repo, commit, file string) ([]byte, error) {
resp, err := c.getResponse("GET", fmt.Sprintf("%s/%s/raw/%s/%s", owner, repo, commit, file), nil, nil, nil)
if err != nil {

View File

@ -111,6 +111,18 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
}, nil
}
func (c *Client) GetRepoInfo(owner, reponame string) (*gitsource.RepoInfo, error) {
repo, err := c.client.GetRepo(owner, reponame)
if err != nil {
return nil, err
}
return &gitsource.RepoInfo{
ID: strconv.FormatInt(repo.ID, 10),
SSHCloneURL: repo.SSHURL,
HTTPCloneURL: repo.CloneURL,
}, nil
}
func (c *Client) GetFile(owner, repo, commit, file string) ([]byte, error) {
data, err := c.client.GetFile(owner, repo, commit, file)
return data, err

View File

@ -121,6 +121,18 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
return token, nil
}
func (c *Client) GetRepoInfo(owner, reponame string) (*gitsource.RepoInfo, error) {
repo, _, err := c.client.Projects.GetProject(path.Join(owner, reponame))
if err != nil {
return nil, err
}
return &gitsource.RepoInfo{
ID: strconv.Itoa(repo.ID),
SSHCloneURL: repo.SSHURLToRepo,
HTTPCloneURL: repo.HTTPURLToRepo,
}, nil
}
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
user, _, err := c.client.Users.CurrentUser()
if err != nil {

View File

@ -30,6 +30,7 @@ const (
)
type GitSource interface {
GetRepoInfo(owner, repo string) (*RepoInfo, error)
GetFile(owner, repo, commit, file string) ([]byte, error)
DeleteDeployKey(owner, repo, title string) error
CreateDeployKey(owner, repo, title, pubKey string, readonly bool) error
@ -57,6 +58,12 @@ type Oauth2Source interface {
RequestOauth2Token(callbackURL, code string) (*oauth2.Token, error)
}
type RepoInfo struct {
ID string
SSHCloneURL string
HTTPCloneURL string
}
type UserInfo struct {
ID string
LoginName string

View File

@ -31,7 +31,7 @@ import (
type CreateProjectRequest struct {
Name string `json:"name,omitempty"`
ParentID string `json:"parent_id,omitempty"`
RepoURL string `json:"repo_url,omitempty"`
RepoPath string `json:"repo_path,omitempty"`
RemoteSourceName string `json:"remote_source_name,omitempty"`
SkipSSHHostKeyCheck bool `json:"skip_ssh_host_key_check,omitempty"`
}
@ -68,7 +68,7 @@ func (h *CreateProjectHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
creq := &command.CreateProjectRequest{
Name: req.Name,
ParentID: req.ParentID,
RepoURL: req.RepoURL,
RepoPath: req.RepoPath,
RemoteSourceName: req.RemoteSourceName,
CurrentUserID: userID,
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,

View File

@ -18,6 +18,7 @@ import (
"context"
"encoding/json"
"net/http"
"sort"
"strconv"
gitsource "github.com/sorintlab/agola/internal/gitsources"
@ -194,15 +195,22 @@ func (h *UserByNameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
type UserResponse struct {
ID string `json:"id"`
UserName string `json:"username"`
ID string `json:"id"`
UserName string `json:"username"`
Tokens []string `json:"tokens"`
}
func createUserResponse(r *types.User) *UserResponse {
func createUserResponse(u *types.User) *UserResponse {
user := &UserResponse{
ID: r.ID,
UserName: r.UserName,
ID: u.ID,
UserName: u.UserName,
Tokens: make([]string, 0, len(u.Tokens)),
}
for tokenName := range u.Tokens {
user.Tokens = append(user.Tokens, tokenName)
}
sort.Sort(sort.StringSlice(user.Tokens))
return user
}

View File

@ -17,7 +17,6 @@ package command
import (
"context"
"fmt"
"net/url"
"path"
"strings"
@ -32,7 +31,7 @@ type CreateProjectRequest struct {
Name string
ParentID string
RemoteSourceName string
RepoURL string
RepoPath string
CurrentUserID string
SkipSSHHostKeyCheck bool
}
@ -42,28 +41,6 @@ func (c *CommandHandler) CreateProject(ctx context.Context, req *CreateProjectRe
return nil, errors.Errorf("invalid project name %q", req.Name)
}
u, err := url.Parse(req.RepoURL)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse repo url")
}
repoOwner := strings.TrimPrefix(path.Dir(u.Path), "/")
repoName := path.Base(u.Path)
u.RawQuery = ""
u.Path = ""
host := u.Hostname()
c.log.Infof("repoOwner: %s, repoName: %s", repoOwner, repoName)
cloneURL := fmt.Sprintf("git@%s:%s/%s.git", host, repoOwner, repoName)
c.log.Infof("cloneURL: %s", cloneURL)
c.log.Infof("generating ssh key pairs")
privateKey, _, err := util.GenSSHKeyPair(4096)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate ssh key pair")
}
user, _, err := c.configstoreClient.GetUser(ctx, req.CurrentUserID)
if err != nil {
return nil, errors.Wrapf(err, "failed to get user %q", req.CurrentUserID)
@ -85,6 +62,30 @@ func (c *CommandHandler) CreateProject(ctx context.Context, req *CreateProjectRe
return nil, errors.Errorf("user doesn't have a linked account for remote source %q", rs.Name)
}
gitsource, err := common.GetGitSource(rs, la)
if err != nil {
return nil, errors.Wrapf(err, "failed to create gitsource client")
}
repoOwner := strings.TrimPrefix(path.Dir(req.RepoPath), "/")
repoName := path.Base(req.RepoPath)
c.log.Infof("repoOwner: %s, repoName: %s", repoOwner, repoName)
repo, err := gitsource.GetRepoInfo(repoOwner, repoName)
if err != nil {
return nil, errors.Wrapf(err, "failed to get repository info from gitsource")
}
//cloneURL := fmt.Sprintf("git@%s:%s/%s.git", host, repoOwner, repoName)
sshCloneURL := repo.SSHCloneURL
c.log.Infof("sshCloneURL: %s", sshCloneURL)
c.log.Infof("generating ssh key pairs")
privateKey, _, err := util.GenSSHKeyPair(4096)
if err != nil {
return nil, errors.Wrapf(err, "failed to generate ssh key pair")
}
parentID := req.ParentID
if parentID == "" {
// create project in current user namespace
@ -98,8 +99,8 @@ func (c *CommandHandler) CreateProject(ctx context.Context, req *CreateProjectRe
ID: parentID,
},
LinkedAccountID: la.ID,
RepoPath: fmt.Sprintf("%s/%s", repoOwner, repoName),
CloneURL: cloneURL,
RepoPath: req.RepoPath,
CloneURL: sshCloneURL,
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
SSHPrivateKey: string(privateKey),
}
@ -125,13 +126,14 @@ type SetupProjectRequest struct {
}
func (c *CommandHandler) SetupProject(ctx context.Context, rs *types.RemoteSource, la *types.LinkedAccount, conf *SetupProjectRequest) error {
c.log.Infof("setupproject")
gitsource, err := common.GetGitSource(rs, la)
if err != nil {
return errors.Wrapf(err, "failed to create gitsource client")
}
pubKey, err := util.ExtractPublicKey([]byte(conf.Project.SSHPrivateKey))
if err != nil {
return errors.Wrapf(err, "failed to create gitea client")
return errors.Wrapf(err, "failed to extract public key")
}
webhookURL := fmt.Sprintf("%s/webhooks?projectid=%s", c.apiExposedURL, conf.Project.ID)