gateway: add UserCreateRun api and related action
add an api to execute a user direct run. This method will replace the current custom webhook way to create a direct run.
This commit is contained in:
parent
810abaaab8
commit
2a95c93f0d
|
@ -30,7 +30,10 @@ import (
|
||||||
errors "golang.org/x/xerrors"
|
errors "golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
var jsonContent = http.Header{"content-type": []string{"application/json"}}
|
var (
|
||||||
|
branchRefPrefix = "refs/heads/"
|
||||||
|
tagRefPrefix = "refs/tags/"
|
||||||
|
)
|
||||||
|
|
||||||
// Client represents a Gogs API client.
|
// Client represents a Gogs API client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -131,7 +134,7 @@ func (c *Client) GetRepoInfo(repopath string) (*gitsource.RepoInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
func (c *Client) GetFile(repopath, commit, file string) ([]byte, error) {
|
||||||
resp, err := c.getResponse("GET", fmt.Sprintf("%s/raw/%s/%s", repopath, commit, file), nil, nil, nil)
|
resp, err := c.getResponse("GET", fmt.Sprintf("%s.git/raw/%s/%s", repopath, commit, file), nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -182,11 +185,11 @@ func (c *Client) GetCommit(repopath, commitSHA string) (*gitsource.Commit, error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) BranchRef(branch string) string {
|
func (c *Client) BranchRef(branch string) string {
|
||||||
return ""
|
return branchRefPrefix + branch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) TagRef(tag string) string {
|
func (c *Client) TagRef(tag string) string {
|
||||||
return ""
|
return tagRefPrefix + tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) PullRequestRef(prID string) string {
|
func (c *Client) PullRequestRef(prID string) string {
|
||||||
|
|
|
@ -17,9 +17,12 @@ package action
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
gitsource "github.com/sorintlab/agola/internal/gitsources"
|
||||||
|
"github.com/sorintlab/agola/internal/gitsources/agolagit"
|
||||||
"github.com/sorintlab/agola/internal/services/common"
|
"github.com/sorintlab/agola/internal/services/common"
|
||||||
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
|
csapi "github.com/sorintlab/agola/internal/services/configstore/api"
|
||||||
"github.com/sorintlab/agola/internal/services/types"
|
"github.com/sorintlab/agola/internal/services/types"
|
||||||
|
@ -814,3 +817,49 @@ func (h *ActionHandler) DeleteUserToken(ctx context.Context, userRef, tokenName
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *ActionHandler) UserCreateRun(ctx context.Context, repoPath, branch, commitSHA, message string) error {
|
||||||
|
curUserID := h.CurrentUserID(ctx)
|
||||||
|
|
||||||
|
user, resp, err := h.configstoreClient.GetUser(ctx, curUserID)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Errorf("failed to get user %q: %w", curUserID, ErrFromRemote(resp, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that the repo is owned by the user
|
||||||
|
repoParts := strings.Split(repoPath, "/")
|
||||||
|
if len(repoParts) != 2 {
|
||||||
|
return util.NewErrBadRequest(errors.Errorf("wrong repo path: %q", repoPath))
|
||||||
|
}
|
||||||
|
if repoParts[0] != user.ID {
|
||||||
|
return util.NewErrUnauthorized(errors.Errorf("repo %q not owned", repoPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
gitSource := agolagit.New(h.apiExposedURL + "/repos")
|
||||||
|
cloneURL := fmt.Sprintf("%s/%s.git", h.apiExposedURL+"/repos", repoPath)
|
||||||
|
|
||||||
|
req := &CreateRunRequest{
|
||||||
|
RunType: types.RunTypeUser,
|
||||||
|
RefType: types.RunRefTypeBranch,
|
||||||
|
RunCreationTrigger: types.RunCreationTriggerTypeManual,
|
||||||
|
|
||||||
|
Project: nil,
|
||||||
|
User: user,
|
||||||
|
RepoPath: repoPath,
|
||||||
|
GitSource: gitSource,
|
||||||
|
CommitSHA: commitSHA,
|
||||||
|
Message: message,
|
||||||
|
Branch: branch,
|
||||||
|
Tag: "",
|
||||||
|
PullRequestID: "",
|
||||||
|
Ref: gitSource.BranchRef(branch),
|
||||||
|
CloneURL: cloneURL,
|
||||||
|
|
||||||
|
CommitLink: "",
|
||||||
|
BranchLink: "",
|
||||||
|
TagLink: "",
|
||||||
|
PullRequestLink: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.CreateRuns(ctx, req)
|
||||||
|
}
|
||||||
|
|
|
@ -282,6 +282,15 @@ func (c *Client) DeleteUser(ctx context.Context, userRef string) (*http.Response
|
||||||
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/users/%s", userRef), nil, jsonContent, nil)
|
return c.getResponse(ctx, "DELETE", fmt.Sprintf("/users/%s", userRef), nil, jsonContent, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) UserCreateRun(ctx context.Context, req *UserCreateRunRequest) (*http.Response, error) {
|
||||||
|
reqj, err := json.Marshal(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.getResponse(ctx, "POST", "/user/createrun", nil, jsonContent, bytes.NewReader(reqj))
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) CreateUserLA(ctx context.Context, userRef string, req *CreateUserLARequest) (*CreateUserLAResponse, *http.Response, error) {
|
func (c *Client) CreateUserLA(ctx context.Context, userRef string, req *CreateUserLARequest) (*CreateUserLAResponse, *http.Response, error) {
|
||||||
reqj, err := json.Marshal(req)
|
reqj, err := json.Marshal(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -603,3 +603,40 @@ func (h *LoginUserHandler) loginUser(ctx context.Context, req *LoginUserRequest)
|
||||||
}
|
}
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserCreateRunRequest struct {
|
||||||
|
RepoPath string `json:"repo_path,omitempty"`
|
||||||
|
Branch string `json:"branch,omitempty"`
|
||||||
|
CommitSHA string `json:"commit_sha,omitempty"`
|
||||||
|
Message string `json:"message,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserCreateRunHandler struct {
|
||||||
|
log *zap.SugaredLogger
|
||||||
|
ah *action.ActionHandler
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserCreateRunHandler(logger *zap.Logger, ah *action.ActionHandler) *UserCreateRunHandler {
|
||||||
|
return &UserCreateRunHandler{log: logger.Sugar(), ah: ah}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *UserCreateRunHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
|
||||||
|
var req UserCreateRunRequest
|
||||||
|
d := json.NewDecoder(r.Body)
|
||||||
|
if err := d.Decode(&req); err != nil {
|
||||||
|
httpError(w, util.NewErrBadRequest(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := h.ah.UserCreateRun(ctx, req.RepoPath, req.Branch, req.CommitSHA, req.Message)
|
||||||
|
if httpError(w, err) {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := httpResponse(w, http.StatusCreated, nil); err != nil {
|
||||||
|
h.log.Errorf("err: %+v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -177,6 +177,7 @@ func (g *Gateway) Run(ctx context.Context) error {
|
||||||
usersHandler := api.NewUsersHandler(logger, g.ah)
|
usersHandler := api.NewUsersHandler(logger, g.ah)
|
||||||
createUserHandler := api.NewCreateUserHandler(logger, g.ah)
|
createUserHandler := api.NewCreateUserHandler(logger, g.ah)
|
||||||
deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah)
|
deleteUserHandler := api.NewDeleteUserHandler(logger, g.ah)
|
||||||
|
userCreateRunHandler := api.NewUserCreateRunHandler(logger, g.ah)
|
||||||
|
|
||||||
createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah)
|
createUserLAHandler := api.NewCreateUserLAHandler(logger, g.ah)
|
||||||
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah)
|
deleteUserLAHandler := api.NewDeleteUserLAHandler(logger, g.ah)
|
||||||
|
@ -264,6 +265,7 @@ func (g *Gateway) Run(ctx context.Context) error {
|
||||||
apirouter.Handle("/users", authForcedHandler(usersHandler)).Methods("GET")
|
apirouter.Handle("/users", authForcedHandler(usersHandler)).Methods("GET")
|
||||||
apirouter.Handle("/users", authForcedHandler(createUserHandler)).Methods("POST")
|
apirouter.Handle("/users", authForcedHandler(createUserHandler)).Methods("POST")
|
||||||
apirouter.Handle("/users/{userref}", authForcedHandler(deleteUserHandler)).Methods("DELETE")
|
apirouter.Handle("/users/{userref}", authForcedHandler(deleteUserHandler)).Methods("DELETE")
|
||||||
|
apirouter.Handle("/user/createrun", authForcedHandler(userCreateRunHandler)).Methods("POST")
|
||||||
|
|
||||||
apirouter.Handle("/users/{userref}/linkedaccounts", authForcedHandler(createUserLAHandler)).Methods("POST")
|
apirouter.Handle("/users/{userref}/linkedaccounts", authForcedHandler(createUserLAHandler)).Methods("POST")
|
||||||
apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
apirouter.Handle("/users/{userref}/linkedaccounts/{laid}", authForcedHandler(deleteUserLAHandler)).Methods("DELETE")
|
||||||
|
|
Loading…
Reference in New Issue