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:
parent
6736f5aebc
commit
3d39553189
|
@ -36,7 +36,7 @@ var cmdProjectCreate = &cobra.Command{
|
||||||
type projectCreateOptions struct {
|
type projectCreateOptions struct {
|
||||||
name string
|
name string
|
||||||
parentPath string
|
parentPath string
|
||||||
repoURL string
|
repoPath string
|
||||||
remoteSourceName string
|
remoteSourceName string
|
||||||
skipSSHHostKeyCheck bool
|
skipSSHHostKeyCheck bool
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func init() {
|
||||||
flags := cmdProjectCreate.Flags()
|
flags := cmdProjectCreate.Flags()
|
||||||
|
|
||||||
flags.StringVarP(&projectCreateOpts.name, "name", "n", "", "project name")
|
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.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.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`)
|
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{
|
req := &api.CreateProjectRequest{
|
||||||
Name: projectCreateOpts.name,
|
Name: projectCreateOpts.name,
|
||||||
ParentID: projectCreateOpts.parentPath,
|
ParentID: projectCreateOpts.parentPath,
|
||||||
RepoURL: projectCreateOpts.repoURL,
|
RepoPath: projectCreateOpts.repoPath,
|
||||||
RemoteSourceName: projectCreateOpts.remoteSourceName,
|
RemoteSourceName: projectCreateOpts.remoteSourceName,
|
||||||
SkipSSHHostKeyCheck: projectCreateOpts.skipSSHHostKeyCheck,
|
SkipSSHHostKeyCheck: projectCreateOpts.skipSSHHostKeyCheck,
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,10 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
return nil, nil
|
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) {
|
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)
|
resp, err := c.getResponse("GET", fmt.Sprintf("%s/%s/raw/%s/%s", owner, repo, commit, file), nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -111,6 +111,18 @@ func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
}, nil
|
}, 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) {
|
func (c *Client) GetFile(owner, repo, commit, file string) ([]byte, error) {
|
||||||
data, err := c.client.GetFile(owner, repo, commit, file)
|
data, err := c.client.GetFile(owner, repo, commit, file)
|
||||||
return data, err
|
return data, err
|
||||||
|
|
|
@ -121,6 +121,18 @@ func (c *Client) RequestOauth2Token(callbackURL, code string) (*oauth2.Token, er
|
||||||
return token, nil
|
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) {
|
func (c *Client) GetUserInfo() (*gitsource.UserInfo, error) {
|
||||||
user, _, err := c.client.Users.CurrentUser()
|
user, _, err := c.client.Users.CurrentUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,6 +30,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type GitSource interface {
|
type GitSource interface {
|
||||||
|
GetRepoInfo(owner, repo string) (*RepoInfo, error)
|
||||||
GetFile(owner, repo, commit, file string) ([]byte, error)
|
GetFile(owner, repo, commit, file string) ([]byte, error)
|
||||||
DeleteDeployKey(owner, repo, title string) error
|
DeleteDeployKey(owner, repo, title string) error
|
||||||
CreateDeployKey(owner, repo, title, pubKey string, readonly bool) error
|
CreateDeployKey(owner, repo, title, pubKey string, readonly bool) error
|
||||||
|
@ -57,6 +58,12 @@ type Oauth2Source interface {
|
||||||
RequestOauth2Token(callbackURL, code string) (*oauth2.Token, error)
|
RequestOauth2Token(callbackURL, code string) (*oauth2.Token, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RepoInfo struct {
|
||||||
|
ID string
|
||||||
|
SSHCloneURL string
|
||||||
|
HTTPCloneURL string
|
||||||
|
}
|
||||||
|
|
||||||
type UserInfo struct {
|
type UserInfo struct {
|
||||||
ID string
|
ID string
|
||||||
LoginName string
|
LoginName string
|
||||||
|
|
|
@ -31,7 +31,7 @@ import (
|
||||||
type CreateProjectRequest struct {
|
type CreateProjectRequest struct {
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
ParentID string `json:"parent_id,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"`
|
RemoteSourceName string `json:"remote_source_name,omitempty"`
|
||||||
SkipSSHHostKeyCheck bool `json:"skip_ssh_host_key_check,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{
|
creq := &command.CreateProjectRequest{
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
ParentID: req.ParentID,
|
ParentID: req.ParentID,
|
||||||
RepoURL: req.RepoURL,
|
RepoPath: req.RepoPath,
|
||||||
RemoteSourceName: req.RemoteSourceName,
|
RemoteSourceName: req.RemoteSourceName,
|
||||||
CurrentUserID: userID,
|
CurrentUserID: userID,
|
||||||
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
|
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
||||||
|
@ -196,13 +197,20 @@ func (h *UserByNameHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
type UserResponse struct {
|
type UserResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
UserName string `json:"username"`
|
UserName string `json:"username"`
|
||||||
|
Tokens []string `json:"tokens"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func createUserResponse(r *types.User) *UserResponse {
|
func createUserResponse(u *types.User) *UserResponse {
|
||||||
user := &UserResponse{
|
user := &UserResponse{
|
||||||
ID: r.ID,
|
ID: u.ID,
|
||||||
UserName: r.UserName,
|
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
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ package command
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ type CreateProjectRequest struct {
|
||||||
Name string
|
Name string
|
||||||
ParentID string
|
ParentID string
|
||||||
RemoteSourceName string
|
RemoteSourceName string
|
||||||
RepoURL string
|
RepoPath string
|
||||||
CurrentUserID string
|
CurrentUserID string
|
||||||
SkipSSHHostKeyCheck bool
|
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)
|
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)
|
user, _, err := c.configstoreClient.GetUser(ctx, req.CurrentUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to get user %q", req.CurrentUserID)
|
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)
|
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
|
parentID := req.ParentID
|
||||||
if parentID == "" {
|
if parentID == "" {
|
||||||
// create project in current user namespace
|
// create project in current user namespace
|
||||||
|
@ -98,8 +99,8 @@ func (c *CommandHandler) CreateProject(ctx context.Context, req *CreateProjectRe
|
||||||
ID: parentID,
|
ID: parentID,
|
||||||
},
|
},
|
||||||
LinkedAccountID: la.ID,
|
LinkedAccountID: la.ID,
|
||||||
RepoPath: fmt.Sprintf("%s/%s", repoOwner, repoName),
|
RepoPath: req.RepoPath,
|
||||||
CloneURL: cloneURL,
|
CloneURL: sshCloneURL,
|
||||||
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
|
SkipSSHHostKeyCheck: req.SkipSSHHostKeyCheck,
|
||||||
SSHPrivateKey: string(privateKey),
|
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 {
|
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)
|
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))
|
pubKey, err := util.ExtractPublicKey([]byte(conf.Project.SSHPrivateKey))
|
||||||
if err != nil {
|
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)
|
webhookURL := fmt.Sprintf("%s/webhooks?projectid=%s", c.apiExposedURL, conf.Project.ID)
|
||||||
|
|
Loading…
Reference in New Issue