Skip to content

#6946 Run hooks on merge/edit and cope with protected branches #6961

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 22 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
71467f9
Fix #6946 by checking PullRequest ID on pushing
zeripath May 15, 2019
fca3a51
Ensure we have the owner name, the pr attributes and the the issue
zeripath May 15, 2019
4d68e21
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 16, 2019
56d7a2f
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 17, 2019
1271a3b
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 17, 2019
5e1d436
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 19, 2019
1f9915d
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 20, 2019
dde55bd
Fix TestSearchRepo by waiting till indexing is done
zeripath May 20, 2019
f7fba98
Update integrations/repo_search_test.go
zeripath May 21, 2019
cb9b7bb
changes as per @mrsdizzie
zeripath May 21, 2019
a90466b
Merge branch 'fix-#6946-pass-in-pr-into-hooks' of github.com:zeripath…
zeripath May 21, 2019
fefc60f
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 21, 2019
604117c
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath May 23, 2019
5b63303
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath Jun 2, 2019
10773f1
missing comma
zeripath Jun 2, 2019
46d8b2e
Spelling mistake
zeripath Jun 2, 2019
757c395
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath Jun 3, 2019
4feeb65
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath Jun 13, 2019
48c4bbd
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath Jun 17, 2019
172cf28
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
zeripath Jun 27, 2019
c015839
Fix full pushing environment
zeripath Jun 27, 2019
77e8790
Merge branch 'master' into fix-#6946-pass-in-pr-into-hooks
techknowlogick Jun 30, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func runHookPreReceive(c *cli.Context) error {
reponame := os.Getenv(models.EnvRepoName)
userIDStr := os.Getenv(models.EnvPusherID)
repoPath := models.RepoPath(username, reponame)
prID, _ := strconv.ParseInt(os.Getenv(models.ProtectedBranchPRID), 10, 64)

buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(os.Stdin)
Expand Down Expand Up @@ -115,6 +116,9 @@ func runHookPreReceive(c *cli.Context) error {

userID, _ := strconv.ParseInt(userIDStr, 10, 64)
canPush, err := private.CanUserPush(protectBranch.ID, userID)
if err == nil && !canPush {
canPush, err = private.HasEnoughApprovals(protectBranch.ID, prID)
}
if err != nil {
fail("Internal error", "Fail to detect user can push: %v", err)
} else if !canPush {
Expand Down
1 change: 1 addition & 0 deletions cmd/serv.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ func runServ(c *cli.Context) error {
}

os.Setenv(models.ProtectedBranchRepoID, fmt.Sprintf("%d", repo.ID))
os.Setenv(models.ProtectedBranchPRID, fmt.Sprintf("%d", 0))

gitcmd.Dir = setting.RepoRootPath
gitcmd.Stdout = os.Stdout
Expand Down
21 changes: 21 additions & 0 deletions integrations/repo_search_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
package integrations

import (
"log"
"net/http"
"testing"
"time"

"code.gitea.io/gitea/models"

"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
Expand All @@ -27,6 +31,23 @@ func resultFilenames(t testing.TB, doc *HTMLDoc) []string {
func TestSearchRepo(t *testing.T) {
prepareTestEnv(t)

repo, err := models.GetRepositoryByOwnerAndName("user2", "repo1")
assert.NoError(t, err)

models.UpdateRepoIndexer(repo)

log.Printf("Waiting for indexing\n")

i := 0
for {
if repo.IndexerStatus != nil && len(repo.IndexerStatus.CommitSha) != 0 && i <= 60 {
break
}
time.Sleep(1 * time.Second)
i++
}
log.Printf("Indexing took: %d s\n", i)

req := NewRequestf(t, "GET", "/user2/repo1/search?q=Description&page=1")
resp := MakeRequest(t, req, http.StatusOK)

Expand Down
2 changes: 2 additions & 0 deletions models/branches.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import (
const (
// ProtectedBranchRepoID protected Repo ID
ProtectedBranchRepoID = "GITEA_REPO_ID"
// ProtectedBranchPRID protected Repo PR ID
ProtectedBranchPRID = "GITEA_PR_ID"
)

// ProtectedBranch struct
Expand Down
24 changes: 16 additions & 8 deletions models/helper_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,34 @@ import (

// PushingEnvironment returns an os environment to allow hooks to work on push
func PushingEnvironment(doer *User, repo *Repository) []string {
return FullPushingEnvironment(doer, doer, repo, 0)
}

// FullPushingEnvironment returns an os environment to allow hooks to work on push
func FullPushingEnvironment(author, committer *User, repo *Repository, prID int64) []string {
isWiki := "false"
if strings.HasSuffix(repo.Name, ".wiki") {
isWiki = "true"
}

sig := doer.NewGitSig()
authorSig := author.NewGitSig()
committerSig := committer.NewGitSig()

// We should add "SSH_ORIGINAL_COMMAND=gitea-internal",
// once we have hook and pushing infrastructure working correctly
return append(os.Environ(),
"GIT_AUTHOR_NAME="+sig.Name,
"GIT_AUTHOR_EMAIL="+sig.Email,
"GIT_COMMITTER_NAME="+sig.Name,
"GIT_COMMITTER_EMAIL="+sig.Email,
"GIT_AUTHOR_NAME="+authorSig.Name,
"GIT_AUTHOR_EMAIL="+authorSig.Email,
"GIT_COMMITTER_NAME="+committerSig.Name,
"GIT_COMMITTER_EMAIL="+committerSig.Email,
EnvRepoName+"="+repo.Name,
EnvRepoUsername+"="+repo.OwnerName,
EnvRepoUsername+"="+repo.MustOwnerName(),
EnvRepoIsWiki+"="+isWiki,
EnvPusherName+"="+doer.Name,
EnvPusherID+"="+fmt.Sprintf("%d", doer.ID),
EnvPusherName+"="+committer.Name,
EnvPusherID+"="+fmt.Sprintf("%d", committer.ID),
ProtectedBranchRepoID+"="+fmt.Sprintf("%d", repo.ID),
ProtectedBranchPRID+"="+fmt.Sprintf("%d", prID),
"SSH_ORIGINAL_COMMAND=gitea-internal",
)

}
4 changes: 2 additions & 2 deletions models/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository, mergeStyle
return ErrInvalidMergeStyle{pr.BaseRepo.ID, mergeStyle}
}

env := PushingEnvironment(doer, pr.BaseRepo)
env := FullPushingEnvironment(doer, doer, pr.BaseRepo, pr.ID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

author should be pullrequest's poster

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


// Push back to upstream.
if err := git.NewCommand("push", baseGitRepo.Path, pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
Expand Down Expand Up @@ -1123,7 +1123,7 @@ func (pr *PullRequest) UpdatePatch() (err error) {
if err = pr.GetHeadRepo(); err != nil {
return fmt.Errorf("GetHeadRepo: %v", err)
} else if pr.HeadRepo == nil {
log.Trace("PullRequest[%d].UpdatePatch: ignored cruppted data", pr.ID)
log.Trace("PullRequest[%d].UpdatePatch: ignored corrupted data", pr.ID)
return nil
}

Expand Down
30 changes: 30 additions & 0 deletions modules/private/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,33 @@ func CanUserPush(protectedBranchID, userID int64) (bool, error) {

return canPush["can_push"].(bool), nil
}

// HasEnoughApprovals returns if true if pr has enough granted approvals.
func HasEnoughApprovals(protectedBranchID, prID int64) (bool, error) {
if prID <= 0 {
return false, nil
}

// Ask for running deliver hook and test pull request tasks.
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/protectedbranchpr/%d/%d", protectedBranchID, prID)
log.GitLogger.Trace("CanUserPush: %s", reqURL)

resp, err := newInternalRequest(reqURL, "GET").Response()
if err != nil {
return false, err
}

var canPush = make(map[string]interface{})
if err := json.NewDecoder(resp.Body).Decode(&canPush); err != nil {
return false, err
}

defer resp.Body.Close()

// All 2XX status codes are accepted and others will return an error
if resp.StatusCode/100 != 2 {
return false, fmt.Errorf("Failed to retrieve push user: %s", decodeJSONError(resp).Err)
}

return canPush["can_push"].(bool), nil
}
35 changes: 35 additions & 0 deletions routers/private/branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,38 @@ func CanUserPush(ctx *macaron.Context) {
})
}
}

// HasEnoughApprovals return if PR has enough approvals
func HasEnoughApprovals(ctx *macaron.Context) {
pbID := ctx.ParamsInt64(":pbid")
prID := ctx.ParamsInt64(":prid")

protectBranch, err := models.GetProtectedBranchByID(pbID)
if err != nil {
ctx.JSON(500, map[string]interface{}{
"err": err.Error(),
})
return
} else if prID > 0 && protectBranch != nil {
pr, err := models.GetPullRequestByID(prID)
if err == nil {
err = pr.LoadAttributes()
}
if err == nil {
err = pr.LoadIssue()
}
if err != nil {
ctx.JSON(500, map[string]interface{}{
"err": err.Error(),
})
return
}
ctx.JSON(200, map[string]interface{}{
"can_push": protectBranch.HasEnoughApprovals(pr),
})
} else {
ctx.JSON(200, map[string]interface{}{
"can_push": false,
})
}
}
1 change: 1 addition & 0 deletions routers/private/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/repositories/:repoid/wiki/init", InitWiki)
m.Post("/push/update", PushUpdate)
m.Get("/protectedbranch/:pbid/:userid", CanUserPush)
m.Get("/protectedbranchpr/:pbid/:prid", HasEnoughApprovals)
m.Get("/repo/:owner/:repo", GetRepositoryByOwnerAndName)
m.Get("/branch/:id/*", GetProtectedBranchBy)
m.Get("/repository/:rid", GetRepository)
Expand Down