Skip to content

Commit

Permalink
Merge pull request agola-io#83 from sgotti/user_direct_run_custom_bra…
Browse files Browse the repository at this point in the history
…nch_tag_ref

userdirectrun: allow setting destination branch/tag/ref
  • Loading branch information
sgotti authored Aug 5, 2019
2 parents b463541 + 056ff23 commit 9a0bbc9
Show file tree
Hide file tree
Showing 11 changed files with 375 additions and 54 deletions.
2 changes: 1 addition & 1 deletion .agola/config.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ local task_build_docker_tests(version, arch) = {
|||,
},
{ type: 'restore_workspace', dest_dir: '.' },
{ type: 'run', name: 'integration tests', command: 'AGOLA_TOOLBOX_PATH="./bin" GITEA_PATH=${PWD}/bin/gitea DOCKER_BRIDGE_ADDRESS="172.18.0.1" ./bin/integration-tests -test.parallel 1 -test.v' },
{ type: 'run', name: 'integration tests', command: 'AGOLA_BIN_DIR="./bin" GITEA_PATH=${PWD}/bin/gitea DOCKER_BRIDGE_ADDRESS="172.18.0.1" ./bin/integration-tests -test.parallel 1 -test.v' },
],
depends: [
'build go 1.12 amd64',
Expand Down
83 changes: 64 additions & 19 deletions cmd/agola/cmd/directrunstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"fmt"
"path"
"regexp"

gitsave "agola.io/agola/internal/git-save"
"agola.io/agola/internal/util"
Expand All @@ -39,32 +40,63 @@ var cmdDirectRunStart = &cobra.Command{
}

type directRunStartOptions struct {
statusFilter []string
labelFilter []string
limit int
start string
untracked bool
ignored bool
untracked bool
ignored bool

branch string
tag string
ref string
prRefRegexes []string
}

var directRunStartOpts directRunStartOptions

func init() {
flags := cmdDirectRunStart.Flags()

flags.StringSliceVarP(&directRunStartOpts.statusFilter, "status", "s", nil, "filter runs matching the provided status. This option can be repeated multiple times")
flags.StringArrayVarP(&directRunStartOpts.labelFilter, "label", "l", nil, "filter runs matching the provided label. This option can be repeated multiple times, in this case only runs matching all the labels will be returned")
flags.IntVar(&directRunStartOpts.limit, "limit", 10, "max number of runs to show")
flags.StringVar(&directRunStartOpts.start, "start", "", "starting run id (excluded) to fetch")
flags.BoolVar(&directRunStartOpts.untracked, "untracked", true, "push untracked files")
flags.BoolVar(&directRunStartOpts.ignored, "ignored", false, "push ignored files")
flags.StringVar(&directRunStartOpts.branch, "branch", "master", "branch to push to")
flags.StringVar(&directRunStartOpts.tag, "tag", "", "tag to push to")
flags.StringVar(&directRunStartOpts.ref, "ref", "", `ref to push to (i.e "refs/heads/master" for a branch, "refs/tags/v1.0" for a tag)`)
flags.StringArrayVar(&directRunStartOpts.prRefRegexes, "pull-request-ref-regexes", []string{`refs/pull/(\d+)/head`, `refs/merge-requests/(\d+)/head`}, `regular expression to determine if a ref is a pull request`)

cmdDirectRun.AddCommand(cmdDirectRunStart)
}

func directRunStart(cmd *cobra.Command, args []string) error {
gwclient := gwclient.NewClient(gatewayURL, token)

for _, res := range directRunStartOpts.prRefRegexes {
if _, err := regexp.Compile(res); err != nil {
return fmt.Errorf("wrong regular expression %q: %v", res, err)
}
}

branch := directRunStartOpts.branch
tag := directRunStartOpts.tag
ref := directRunStartOpts.ref

set := 0

flags := cmd.Flags()
if flags.Changed("branch") {
set++
}
if tag != "" {
set++
// unset branch default value
branch = ""
}
if ref != "" {
set++
// unset branch default value
branch = ""
}
if set > 1 {
return fmt.Errorf(`only one of "--branch", "--tag" or "--ref" can be provided`)
}

user, _, err := gwclient.GetCurrentUser(context.TODO())
if err != nil {
return err
Expand All @@ -85,10 +117,10 @@ func directRunStart(cmd *cobra.Command, args []string) error {
AddIgnored: directRunStartOpts.ignored,
})

branch := "gitsavebranch-" + uuid.NewV4().String()
localBranch := "gitsavebranch-" + uuid.NewV4().String()
message := "agola direct run"

commitSHA, err := gs.Save(message, branch)
commitSHA, err := gs.Save(message, localBranch)
if err != nil {
return err
}
Expand All @@ -98,17 +130,30 @@ func directRunStart(cmd *cobra.Command, args []string) error {
repoURL := fmt.Sprintf("%s/repos/%s/%s.git", gatewayURL, user.ID, repoUUID)

// push to a branch with default branch refs "refs/heads/branch"
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/heads/%s", path.Join(gs.RefsPrefix(), branch), branch)); err != nil {
return err
if branch != "" {
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/heads/%s", path.Join(gs.RefsPrefix(), localBranch), branch)); err != nil {
return err
}
} else if tag != "" {
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:refs/tags/%s", path.Join(gs.RefsPrefix(), localBranch), tag)); err != nil {
return err
}
} else if ref != "" {
if err := gitsave.GitPush("", repoURL, fmt.Sprintf("%s:%s", path.Join(gs.RefsPrefix(), localBranch), ref)); err != nil {
return err
}
}

log.Infof("starting direct run")
req := &gwapitypes.UserCreateRunRequest{
RepoUUID: repoUUID,
RepoPath: repoPath,
Branch: branch,
CommitSHA: commitSHA,
Message: message,
RepoUUID: repoUUID,
RepoPath: repoPath,
Branch: branch,
Tag: tag,
Ref: ref,
CommitSHA: commitSHA,
Message: message,
PullRequestRefRegexes: directRunStartOpts.prRefRegexes,
}
if _, err := gwclient.UserCreateRun(context.TODO(), req); err != nil {
return err
Expand Down
30 changes: 24 additions & 6 deletions internal/gitsources/agolagit/agolagit.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"net"
"net/http"
"net/url"
"regexp"
"strings"
"time"

Expand All @@ -36,12 +37,13 @@ var (
)

type Client struct {
url string
client *http.Client
url string
client *http.Client
pullRequestRefRegexes []*regexp.Regexp
}

// NewClient initializes and returns a API client.
func New(url string) *Client {
func New(url string, pullRequestRefRegexes []*regexp.Regexp) *Client {
// copied from net/http until it has a clone function: https://github.com/golang/go/issues/26013
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
Expand All @@ -59,8 +61,9 @@ func New(url string) *Client {

httpClient := &http.Client{Transport: transport}
return &Client{
url: strings.TrimSuffix(url, "/"),
client: httpClient,
url: strings.TrimSuffix(url, "/"),
client: httpClient,
pullRequestRefRegexes: pullRequestRefRegexes,
}
}

Expand Down Expand Up @@ -168,7 +171,22 @@ func (c *Client) GetRef(repopath, ref string) (*gitsource.Ref, error) {
}

func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {
return -1, "", nil
if strings.HasPrefix(ref, branchRefPrefix) {
return gitsource.RefTypeBranch, strings.TrimPrefix(ref, branchRefPrefix), nil
}

if strings.HasPrefix(ref, tagRefPrefix) {
return gitsource.RefTypeTag, strings.TrimPrefix(ref, tagRefPrefix), nil
}

for _, re := range c.pullRequestRefRegexes {
if re.MatchString(ref) {
m := re.FindStringSubmatch(ref)
return gitsource.RefTypePullRequest, m[1], nil
}
}

return -1, "", fmt.Errorf("unsupported ref: %s", ref)
}

func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error) {
Expand Down
2 changes: 1 addition & 1 deletion internal/gitsources/gitea/gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {

case pullRequestRefRegex.MatchString(ref):
m := pullRequestRefRegex.FindStringSubmatch(ref)
return gitsource.RefTypePullRequest, m[0], nil
return gitsource.RefTypePullRequest, m[1], nil

default:
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
Expand Down
2 changes: 1 addition & 1 deletion internal/gitsources/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {

case pullRequestRefRegex.MatchString(ref):
m := pullRequestRefRegex.FindStringSubmatch(ref)
return gitsource.RefTypePullRequest, m[0], nil
return gitsource.RefTypePullRequest, m[1], nil

default:
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
Expand Down
2 changes: 1 addition & 1 deletion internal/gitsources/gitlab/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ func (c *Client) RefType(ref string) (gitsource.RefType, string, error) {

case pullRequestRefRegex.MatchString(ref):
m := pullRequestRefRegex.FindStringSubmatch(ref)
return gitsource.RefTypePullRequest, m[0], nil
return gitsource.RefTypePullRequest, m[1], nil

default:
return -1, "", fmt.Errorf("unsupported ref: %s", ref)
Expand Down
4 changes: 1 addition & 3 deletions internal/services/gateway/action/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,14 +528,12 @@ func (h *ActionHandler) ProjectCreateRun(ctx context.Context, projectRef, branch
refType = types.RunRefTypeBranch
message = commit.Message
branchLink = gitSource.BranchLink(repoInfo, branch)

}

if tag != "" {
refType = types.RunRefTypeBranch
refType = types.RunRefTypeTag
message = fmt.Sprintf("Tag %s", tag)
tagLink = gitSource.TagLink(repoInfo, tag)

}

// use remotesource skipSSHHostKeyCheck config and override with project config if set to true there
Expand Down
86 changes: 80 additions & 6 deletions internal/services/gateway/action/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"encoding/json"
"fmt"
"regexp"
"strings"
"time"

Expand Down Expand Up @@ -817,11 +818,24 @@ type UserCreateRunRequest struct {
RepoUUID string
RepoPath string
Branch string
Tag string
Ref string
CommitSHA string
Message string

PullRequestRefRegexes []string
}

func (h *ActionHandler) UserCreateRun(ctx context.Context, req *UserCreateRunRequest) error {
prRefRegexes := []*regexp.Regexp{}
for _, res := range req.PullRequestRefRegexes {
re, err := regexp.Compile(res)
if err != nil {
return fmt.Errorf("wrong regular expression %q: %v", res, err)
}
prRefRegexes = append(prRefRegexes, re)
}

curUserID := h.CurrentUserID(ctx)

user, resp, err := h.configstoreClient.GetUser(ctx, curUserID)
Expand All @@ -841,12 +855,72 @@ func (h *ActionHandler) UserCreateRun(ctx context.Context, req *UserCreateRunReq
return util.NewErrUnauthorized(errors.Errorf("repo %q not owned", req.RepoPath))
}

gitSource := agolagit.New(h.apiExposedURL + "/repos")
branch := req.Branch
tag := req.Tag
ref := req.Ref

set := 0
if branch != "" {
set++
}
if tag != "" {
set++
}
if ref != "" {
set++
}
if set == 0 {
return util.NewErrBadRequest(errors.Errorf("one of branch, tag or ref is required"))
}
if set > 1 {
return util.NewErrBadRequest(errors.Errorf("only one of branch, tag or ref can be provided"))
}

gitSource := agolagit.New(h.apiExposedURL+"/repos", prRefRegexes)
cloneURL := fmt.Sprintf("%s/%s.git", h.apiExposedURL+"/repos", req.RepoPath)

if ref == "" {
if branch != "" {
ref = gitSource.BranchRef(branch)
}
if tag != "" {
ref = gitSource.TagRef(tag)
}
}

gitRefType, name, err := gitSource.RefType(ref)
if err != nil {
return util.NewErrBadRequest(errors.Errorf("failed to get refType for ref %q: %w", ref, err))
}

var pullRequestID string

switch gitRefType {
case gitsource.RefTypeBranch:
branch = name
case gitsource.RefTypeTag:
tag = name
case gitsource.RefTypePullRequest:
pullRequestID = name
default:
return errors.Errorf("unsupported ref %q for manual run creation", ref)
}

var refType types.RunRefType

if branch != "" {
refType = types.RunRefTypeBranch
}
if tag != "" {
refType = types.RunRefTypeTag
}
if pullRequestID != "" {
refType = types.RunRefTypePullRequest
}

creq := &CreateRunRequest{
RunType: types.RunTypeUser,
RefType: types.RunRefTypeBranch,
RefType: refType,
RunCreationTrigger: types.RunCreationTriggerTypeManual,

Project: nil,
Expand All @@ -855,10 +929,10 @@ func (h *ActionHandler) UserCreateRun(ctx context.Context, req *UserCreateRunReq
GitSource: gitSource,
CommitSHA: req.CommitSHA,
Message: req.Message,
Branch: req.Branch,
Tag: "",
PullRequestID: "",
Ref: gitSource.BranchRef(req.Branch),
Branch: branch,
Tag: tag,
Ref: ref,
PullRequestID: pullRequestID,
CloneURL: cloneURL,

CommitLink: "",
Expand Down
13 changes: 8 additions & 5 deletions internal/services/gateway/api/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,11 +570,14 @@ func (h *UserCreateRunHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
}

creq := &action.UserCreateRunRequest{
RepoUUID: req.RepoUUID,
RepoPath: req.RepoPath,
Branch: req.Branch,
CommitSHA: req.CommitSHA,
Message: req.Message,
RepoUUID: req.RepoUUID,
RepoPath: req.RepoPath,
Branch: req.Branch,
Tag: req.Tag,
Ref: req.Ref,
CommitSHA: req.CommitSHA,
Message: req.Message,
PullRequestRefRegexes: req.PullRequestRefRegexes,
}
err := h.ah.UserCreateRun(ctx, creq)
if httpError(w, err) {
Expand Down
4 changes: 4 additions & 0 deletions services/gateway/api/types/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ type UserCreateRunRequest struct {
RepoUUID string `json:"repo_uuid,omitempty"`
RepoPath string `json:"repo_path,omitempty"`
Branch string `json:"branch,omitempty"`
Tag string `json:"tag,omitempty"`
Ref string `json:"ref,omitempty"`
CommitSHA string `json:"commit_sha,omitempty"`
Message string `json:"message,omitempty"`

PullRequestRefRegexes []string
}
Loading

0 comments on commit 9a0bbc9

Please sign in to comment.