Merge pull request '[gitea] week 2024-23 cherry pick (gitea/main -> forgejo)' (#3989) from earl-warren/wcp/2024-23 into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3989 Reviewed-by: Otto <otto@codeberg.org>
This commit is contained in:
commit
c2382d4f5b
98 changed files with 1520 additions and 975 deletions
|
@ -7,7 +7,6 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
@ -141,18 +140,19 @@ func (r *jobStatusResolver) resolve() map[int64]actions_model.Status {
|
|||
if allSucceed {
|
||||
ret[id] = actions_model.StatusWaiting
|
||||
} else {
|
||||
// If a job's "if" condition is "always()", the job should always run even if some of its dependencies did not succeed.
|
||||
// See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds
|
||||
always := false
|
||||
// Check if the job has an "if" condition
|
||||
hasIf := false
|
||||
if wfJobs, _ := jobparser.Parse(r.jobMap[id].WorkflowPayload); len(wfJobs) == 1 {
|
||||
_, wfJob := wfJobs[0].Job()
|
||||
expr := strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(wfJob.If.Value, "${{"), "}}"))
|
||||
always = expr == "always()"
|
||||
hasIf = len(wfJob.If.Value) > 0
|
||||
}
|
||||
|
||||
if always {
|
||||
if hasIf {
|
||||
// act_runner will check the "if" condition
|
||||
ret[id] = actions_model.StatusWaiting
|
||||
} else {
|
||||
// If the "if" condition is empty and not all dependent jobs completed successfully,
|
||||
// the job should be skipped.
|
||||
ret[id] = actions_model.StatusSkipped
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,9 +71,9 @@ func Test_jobStatusResolver_Resolve(t *testing.T) {
|
|||
want: map[int64]actions_model.Status{},
|
||||
},
|
||||
{
|
||||
name: "with ${{ always() }} condition",
|
||||
name: "`if` is not empty and all jobs in `needs` completed successfully",
|
||||
jobs: actions_model.ActionJobList{
|
||||
{ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
|
||||
{ID: 1, JobID: "job1", Status: actions_model.StatusSuccess, Needs: []string{}},
|
||||
{ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
|
||||
`
|
||||
name: test
|
||||
|
@ -82,15 +82,15 @@ jobs:
|
|||
job2:
|
||||
runs-on: ubuntu-latest
|
||||
needs: job1
|
||||
if: ${{ always() }}
|
||||
if: ${{ always() && needs.job1.result == 'success' }}
|
||||
steps:
|
||||
- run: echo "always run"
|
||||
- run: echo "will be checked by act_runner"
|
||||
`)},
|
||||
},
|
||||
want: map[int64]actions_model.Status{2: actions_model.StatusWaiting},
|
||||
},
|
||||
{
|
||||
name: "with always() condition",
|
||||
name: "`if` is not empty and not all jobs in `needs` completed successfully",
|
||||
jobs: actions_model.ActionJobList{
|
||||
{ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
|
||||
{ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
|
||||
|
@ -101,15 +101,15 @@ jobs:
|
|||
job2:
|
||||
runs-on: ubuntu-latest
|
||||
needs: job1
|
||||
if: always()
|
||||
if: ${{ always() && needs.job1.result == 'failure' }}
|
||||
steps:
|
||||
- run: echo "always run"
|
||||
- run: echo "will be checked by act_runner"
|
||||
`)},
|
||||
},
|
||||
want: map[int64]actions_model.Status{2: actions_model.StatusWaiting},
|
||||
},
|
||||
{
|
||||
name: "without always() condition",
|
||||
name: "`if` is empty and not all jobs in `needs` completed successfully",
|
||||
jobs: actions_model.ActionJobList{
|
||||
{ID: 1, JobID: "job1", Status: actions_model.StatusFailure, Needs: []string{}},
|
||||
{ID: 2, JobID: "job2", Status: actions_model.StatusBlocked, Needs: []string{"job1"}, WorkflowPayload: []byte(
|
||||
|
@ -121,7 +121,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
needs: job1
|
||||
steps:
|
||||
- run: echo "not always run"
|
||||
- run: echo "should be skipped"
|
||||
`)},
|
||||
},
|
||||
want: map[int64]actions_model.Status{2: actions_model.StatusSkipped},
|
||||
|
|
|
@ -31,15 +31,15 @@ func ToAPIIssue(ctx context.Context, doer *user_model.User, issue *issues_model.
|
|||
}
|
||||
|
||||
func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue {
|
||||
if err := issue.LoadLabels(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
if err := issue.LoadPoster(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
if err := issue.LoadRepo(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
if err := issue.LoadAttachments(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
|
||||
apiIssue := &api.Issue{
|
||||
ID: issue.ID,
|
||||
|
@ -63,6 +63,9 @@ func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Iss
|
|||
}
|
||||
apiIssue.URL = issue.APIURL(ctx)
|
||||
apiIssue.HTMLURL = issue.HTMLURL()
|
||||
if err := issue.LoadLabels(ctx); err != nil {
|
||||
return &api.Issue{}
|
||||
}
|
||||
apiIssue.Labels = ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner)
|
||||
apiIssue.Repo = &api.RepositoryMeta{
|
||||
ID: issue.Repo.ID,
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
@ -44,7 +45,16 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
|
|||
return nil
|
||||
}
|
||||
|
||||
p, err := access_model.GetUserRepoPermission(ctx, pr.BaseRepo, doer)
|
||||
var doerID int64
|
||||
if doer != nil {
|
||||
doerID = doer.ID
|
||||
}
|
||||
|
||||
const repoDoerPermCacheKey = "repo_doer_perm_cache"
|
||||
p, err := cache.GetWithContextCache(ctx, repoDoerPermCacheKey, fmt.Sprintf("%d_%d", pr.BaseRepoID, doerID),
|
||||
func() (access_model.Permission, error) {
|
||||
return access_model.GetUserRepoPermission(ctx, pr.BaseRepo, doer)
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("GetUserRepoPermission[%d]: %v", pr.BaseRepoID, err)
|
||||
p.AccessMode = perm.AccessModeNone
|
||||
|
|
|
@ -237,6 +237,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
|
|||
MirrorInterval: mirrorInterval,
|
||||
MirrorUpdated: mirrorUpdated,
|
||||
RepoTransfer: transfer,
|
||||
Topics: repo.Topics,
|
||||
ObjectFormatName: repo.ObjectFormatName,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -370,45 +370,21 @@ func (i IssueLockForm) HasValidReason() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// __________ __ __
|
||||
// \______ \_______ ____ |__| ____ _____/ |_ ______
|
||||
// | ___/\_ __ \/ _ \ | |/ __ \_/ ___\ __\/ ___/
|
||||
// | | | | \( <_> ) | \ ___/\ \___| | \___ \
|
||||
// |____| |__| \____/\__| |\___ >\___ >__| /____ >
|
||||
// \______| \/ \/ \/
|
||||
|
||||
// CreateProjectForm form for creating a project
|
||||
type CreateProjectForm struct {
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Content string
|
||||
BoardType project_model.BoardType
|
||||
CardType project_model.CardType
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Content string
|
||||
TemplateType project_model.TemplateType
|
||||
CardType project_model.CardType
|
||||
}
|
||||
|
||||
// UserCreateProjectForm is a from for creating an individual or organization
|
||||
// form.
|
||||
type UserCreateProjectForm struct {
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Content string
|
||||
BoardType project_model.BoardType
|
||||
CardType project_model.CardType
|
||||
UID int64 `binding:"Required"`
|
||||
}
|
||||
|
||||
// EditProjectBoardForm is a form for editing a project board
|
||||
type EditProjectBoardForm struct {
|
||||
// EditProjectColumnForm is a form for editing a project column
|
||||
type EditProjectColumnForm struct {
|
||||
Title string `binding:"Required;MaxSize(100)"`
|
||||
Sorting int8
|
||||
Color string `binding:"MaxSize(7)"`
|
||||
}
|
||||
|
||||
// _____ .__.__ __
|
||||
// / \ |__| | ____ _______/ |_ ____ ____ ____
|
||||
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
|
||||
// / Y \ | |_\ ___/ \___ \ | | ( <_> ) | \ ___/
|
||||
// \____|__ /__|____/\___ >____ > |__| \____/|___| /\___ >
|
||||
// \/ \/ \/ \/ \/
|
||||
|
||||
// CreateMilestoneForm form for creating milestone
|
||||
type CreateMilestoneForm struct {
|
||||
Title string `binding:"Required;MaxSize(50)"`
|
||||
|
@ -422,13 +398,6 @@ func (f *CreateMilestoneForm) Validate(req *http.Request, errs binding.Errors) b
|
|||
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// .____ ___. .__
|
||||
// | | _____ \_ |__ ____ | |
|
||||
// | | \__ \ | __ \_/ __ \| |
|
||||
// | |___ / __ \| \_\ \ ___/| |__
|
||||
// |_______ (____ /___ /\___ >____/
|
||||
// \/ \/ \/ \/
|
||||
|
||||
// CreateLabelForm form for creating label
|
||||
type CreateLabelForm struct {
|
||||
ID int64
|
||||
|
@ -456,13 +425,6 @@ func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors)
|
|||
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
// __________ .__ .__ __________ __
|
||||
// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
|
||||
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
|
||||
// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
|
||||
// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
|
||||
// \/ \/ |__| \/ \/
|
||||
|
||||
// MergePullRequestForm form for merging Pull Request
|
||||
// swagger:model MergePullRequestOption
|
||||
type MergePullRequestForm struct {
|
||||
|
|
|
@ -65,7 +65,7 @@ var hiddenCommentTypeGroups = hiddenCommentTypeGroupsType{
|
|||
},
|
||||
"project": {
|
||||
/*30*/ issues_model.CommentTypeProject,
|
||||
/*31*/ issues_model.CommentTypeProjectBoard,
|
||||
/*31*/ issues_model.CommentTypeProjectColumn,
|
||||
},
|
||||
"issue_ref": {
|
||||
/*33*/ issues_model.CommentTypeChangeIssueRef,
|
||||
|
|
|
@ -39,7 +39,8 @@ func TestDeleteNotPassedAssignee(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Empty(t, issue.Assignees)
|
||||
|
||||
// Check they're gone
|
||||
// Reload to check they're gone
|
||||
issue.ResetAttributesLoaded()
|
||||
assert.NoError(t, issue.LoadAssignees(db.DefaultContext))
|
||||
assert.Empty(t, issue.Assignees)
|
||||
assert.Empty(t, issue.Assignee)
|
||||
|
|
|
@ -74,7 +74,7 @@ func CreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_m
|
|||
}
|
||||
|
||||
// UpdateComment updates information of comment.
|
||||
func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_model.User, oldContent string) error {
|
||||
func UpdateComment(ctx context.Context, c *issues_model.Comment, contentVersion int, doer *user_model.User, oldContent string) error {
|
||||
needsContentHistory := c.Content != oldContent && c.Type.HasContentSupport()
|
||||
if needsContentHistory {
|
||||
hasContentHistory, err := issues_model.HasIssueContentHistory(ctx, c.IssueID, c.ID)
|
||||
|
@ -89,7 +89,7 @@ func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_mode
|
|||
}
|
||||
}
|
||||
|
||||
if err := issues_model.UpdateComment(ctx, c, doer); err != nil {
|
||||
if err := issues_model.UpdateComment(ctx, c, contentVersion, doer); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ import (
|
|||
)
|
||||
|
||||
// ChangeContent changes issue content, as the given user.
|
||||
func ChangeContent(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, content string) (err error) {
|
||||
func ChangeContent(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, content string, contentVersion int) (err error) {
|
||||
oldContent := issue.Content
|
||||
|
||||
if err := issues_model.ChangeIssueContent(ctx, issue, doer, content); err != nil {
|
||||
if err := issues_model.ChangeIssueContent(ctx, issue, doer, content, contentVersion); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -296,7 +296,7 @@ func SyncBranchesToDB(ctx context.Context, repoID, pusherID int64, branchNames,
|
|||
if _, err := git_model.UpdateBranch(ctx, repoID, pusherID, branchName, commit); err != nil {
|
||||
return fmt.Errorf("git_model.UpdateBranch %d:%s failed: %v", repoID, branchName, err)
|
||||
}
|
||||
return nil
|
||||
continue
|
||||
}
|
||||
|
||||
// if database have branches but not this branch, it means this is a new branch
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue