From cbde69f6ee008db9c36dbf30f4da6344deebbb79 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 16 Oct 2024 23:00:26 +0200 Subject: [PATCH 01/39] Add test for ProtectedBranchRules.sort --- models/git/protected_banch_list_test.go | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/models/git/protected_banch_list_test.go b/models/git/protected_banch_list_test.go index 4bb3136d580bf..94a48f37e6a5b 100644 --- a/models/git/protected_banch_list_test.go +++ b/models/git/protected_banch_list_test.go @@ -74,3 +74,32 @@ func TestBranchRuleMatchPriority(t *testing.T) { } } } + +func TestBranchRuleSort(t *testing.T) { + in := []*ProtectedBranch{{ + RuleName: "b", + CreatedUnix: 1, + }, { + RuleName: "b/*", + CreatedUnix: 3, + }, { + RuleName: "a/*", + CreatedUnix: 2, + }, { + RuleName: "c", + CreatedUnix: 0, + }, { + RuleName: "a", + CreatedUnix: 4, + }} + expect := []string{"c", "b", "a", "a/*", "b/*"} + + pbr := ProtectedBranchRules(in) + pbr.sort() + + var got []string + for i := range pbr { + got = append(got, pbr[i].RuleName) + } + assert.Equal(t, expect, got) +} From ccb2e12189e2d234e5de5184164dc42360c1186c Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 16 Oct 2024 23:07:58 +0200 Subject: [PATCH 02/39] optimize loadGlob for protectedBranch --- models/git/protected_branch.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index bde6057375e55..70033476247c4 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -83,14 +83,18 @@ func IsRuleNameSpecial(ruleName string) bool { } func (protectBranch *ProtectedBranch) loadGlob() { - if protectBranch.globRule == nil { + if protectBranch.globRule == nil && !protectBranch.isPlainName { + // detect if it is not glob + if !IsRuleNameSpecial(protectBranch.RuleName) { + protectBranch.isPlainName = true + return + } var err error protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/') if err != nil { log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err) protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/') } - protectBranch.isPlainName = !IsRuleNameSpecial(protectBranch.RuleName) } } From e6b983410f9ec393b13a38f3789ba1376f693868 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 16 Oct 2024 23:08:35 +0200 Subject: [PATCH 03/39] sort non glob protected branch roules by name --- models/git/protected_banch_list_test.go | 2 +- models/git/protected_branch_list.go | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/models/git/protected_banch_list_test.go b/models/git/protected_banch_list_test.go index 94a48f37e6a5b..8852e898d8e3b 100644 --- a/models/git/protected_banch_list_test.go +++ b/models/git/protected_banch_list_test.go @@ -92,7 +92,7 @@ func TestBranchRuleSort(t *testing.T) { RuleName: "a", CreatedUnix: 4, }} - expect := []string{"c", "b", "a", "a/*", "b/*"} + expect := []string{"a", "b", "c", "a/*", "b/*"} pbr := ProtectedBranchRules(in) pbr.sort() diff --git a/models/git/protected_branch_list.go b/models/git/protected_branch_list.go index 613333a5a2950..9fe7d3f1a4cd5 100644 --- a/models/git/protected_branch_list.go +++ b/models/git/protected_branch_list.go @@ -6,6 +6,7 @@ package git import ( "context" "sort" + "strings" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/optional" @@ -29,7 +30,12 @@ func (rules ProtectedBranchRules) sort() { rules[i].loadGlob() rules[j].loadGlob() if rules[i].isPlainName != rules[j].isPlainName { - return rules[i].isPlainName // plain name comes first, so plain name means "less" + // plain name comes first, so plain name means "less" + return rules[i].isPlainName + } + if rules[i].isPlainName { + // both are plain names so sort alphabetically + return strings.Compare(rules[i].RuleName, rules[j].RuleName) < 0 } return rules[i].CreatedUnix < rules[j].CreatedUnix }) From 74760d522333bb155ca6513e2b7e0c4098a26f75 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Wed, 16 Oct 2024 23:21:10 +0200 Subject: [PATCH 04/39] update comment --- models/git/protected_branch_list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/git/protected_branch_list.go b/models/git/protected_branch_list.go index 9fe7d3f1a4cd5..d028a4941411c 100644 --- a/models/git/protected_branch_list.go +++ b/models/git/protected_branch_list.go @@ -48,7 +48,7 @@ func FindRepoProtectedBranchRules(ctx context.Context, repoID int64) (ProtectedB if err != nil { return nil, err } - rules.sort() // to make non-glob rules have higher priority, and for same glob/non-glob rules, first created rules have higher priority + rules.sort() // make sure first match is detected in right order return rules, nil } From 3103499b2a9b75a33ef25c12591bd899ac908363 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 17 Oct 2024 10:32:18 +0200 Subject: [PATCH 05/39] clean unrelated --- models/git/protected_banch_list_test.go | 2 +- models/git/protected_branch_list.go | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/models/git/protected_banch_list_test.go b/models/git/protected_banch_list_test.go index 8852e898d8e3b..94a48f37e6a5b 100644 --- a/models/git/protected_banch_list_test.go +++ b/models/git/protected_banch_list_test.go @@ -92,7 +92,7 @@ func TestBranchRuleSort(t *testing.T) { RuleName: "a", CreatedUnix: 4, }} - expect := []string{"a", "b", "c", "a/*", "b/*"} + expect := []string{"c", "b", "a", "a/*", "b/*"} pbr := ProtectedBranchRules(in) pbr.sort() diff --git a/models/git/protected_branch_list.go b/models/git/protected_branch_list.go index d028a4941411c..613333a5a2950 100644 --- a/models/git/protected_branch_list.go +++ b/models/git/protected_branch_list.go @@ -6,7 +6,6 @@ package git import ( "context" "sort" - "strings" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/optional" @@ -30,12 +29,7 @@ func (rules ProtectedBranchRules) sort() { rules[i].loadGlob() rules[j].loadGlob() if rules[i].isPlainName != rules[j].isPlainName { - // plain name comes first, so plain name means "less" - return rules[i].isPlainName - } - if rules[i].isPlainName { - // both are plain names so sort alphabetically - return strings.Compare(rules[i].RuleName, rules[j].RuleName) < 0 + return rules[i].isPlainName // plain name comes first, so plain name means "less" } return rules[i].CreatedUnix < rules[j].CreatedUnix }) @@ -48,7 +42,7 @@ func FindRepoProtectedBranchRules(ctx context.Context, repoID int64) (ProtectedB if err != nil { return nil, err } - rules.sort() // make sure first match is detected in right order + rules.sort() // to make non-glob rules have higher priority, and for same glob/non-glob rules, first created rules have higher priority return rules, nil } From 0ff31b82d35a8b6a21b20f4f005da71e70e13305 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 17 Oct 2024 10:52:59 +0200 Subject: [PATCH 06/39] Backend to sort ProtectedBranch by Priority --- models/git/protected_banch_list_test.go | 36 ++++++++++++++++++++++++- models/git/protected_branch.go | 1 + models/git/protected_branch_list.go | 7 +++++ models/migrations/migrations.go | 2 ++ models/migrations/v1_23/v306.go | 16 +++++++++++ 5 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 models/migrations/v1_23/v306.go diff --git a/models/git/protected_banch_list_test.go b/models/git/protected_banch_list_test.go index 94a48f37e6a5b..a46402c5432b3 100644 --- a/models/git/protected_banch_list_test.go +++ b/models/git/protected_banch_list_test.go @@ -75,7 +75,7 @@ func TestBranchRuleMatchPriority(t *testing.T) { } } -func TestBranchRuleSort(t *testing.T) { +func TestBranchRuleSortLegacy(t *testing.T) { in := []*ProtectedBranch{{ RuleName: "b", CreatedUnix: 1, @@ -103,3 +103,37 @@ func TestBranchRuleSort(t *testing.T) { } assert.Equal(t, expect, got) } + +func TestBranchRuleSortPriority(t *testing.T) { + in := []*ProtectedBranch{{ + RuleName: "b", + CreatedUnix: 1, + Priority: 4, + }, { + RuleName: "b/*", + CreatedUnix: 3, + Priority: 2, + }, { + RuleName: "a/*", + CreatedUnix: 2, + Priority: 1, + }, { + RuleName: "c", + CreatedUnix: 0, + Priority: 0, + }, { + RuleName: "a", + CreatedUnix: 4, + Priority: 3, + }} + expect := []string{"c", "a/*", "b/*", "a", "b"} + + pbr := ProtectedBranchRules(in) + pbr.sort() + + var got []string + for i := range pbr { + got = append(got, pbr[i].RuleName) + } + assert.Equal(t, expect, got) +} diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index 70033476247c4..0b14107c7fa96 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -34,6 +34,7 @@ type ProtectedBranch struct { RepoID int64 `xorm:"UNIQUE(s)"` Repo *repo_model.Repository `xorm:"-"` RuleName string `xorm:"'branch_name' UNIQUE(s)"` // a branch name or a glob match to branch name + Priority int64 `xorm:"NOT NULL DEFAULT 0"` globRule glob.Glob `xorm:"-"` isPlainName bool `xorm:"-"` CanPush bool `xorm:"NOT NULL DEFAULT false"` diff --git a/models/git/protected_branch_list.go b/models/git/protected_branch_list.go index 613333a5a2950..16f85006723b1 100644 --- a/models/git/protected_branch_list.go +++ b/models/git/protected_branch_list.go @@ -28,6 +28,13 @@ func (rules ProtectedBranchRules) sort() { sort.Slice(rules, func(i, j int) bool { rules[i].loadGlob() rules[j].loadGlob() + + // if priority differ, use that to sort + if rules[i].Priority != rules[j].Priority { + return rules[i].Priority < rules[j].Priority + } + + // now we sort the old way if rules[i].isPlainName != rules[j].isPlainName { return rules[i].isPlainName // plain name comes first, so plain name means "less" } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index f99718ead2859..a33ae7641face 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -603,6 +603,8 @@ var migrations = []Migration{ NewMigration("Add index for release sha1", v1_23.AddIndexForReleaseSha1), // v305 -> v306 NewMigration("Add Repository Licenses", v1_23.AddRepositoryLicenses), + // v306 -> v307 + NewMigration("Add Priority to ProtectedBranch", v1_23.AddPriorityToProtectedBranch), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_23/v306.go b/models/migrations/v1_23/v306.go new file mode 100644 index 0000000000000..394417f5a01b0 --- /dev/null +++ b/models/migrations/v1_23/v306.go @@ -0,0 +1,16 @@ +// Copyright 2024 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_23 //nolint + +import ( + "xorm.io/xorm" +) + +func AddPriorityToProtectedBranch(x *xorm.Engine) error { + type ProtectedBranch struct { + Priority int64 `xorm:"NOT NULL DEFAULT 0"` + } + + return x.Sync(new(ProtectedBranch)) +} From c6f49a773a8f52c17dce520f21b77c279fe64a67 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 17 Oct 2024 11:09:23 +0200 Subject: [PATCH 07/39] fix misspell --- ...protected_banch_list_test.go => protected_branch_list_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename models/git/{protected_banch_list_test.go => protected_branch_list_test.go} (100%) diff --git a/models/git/protected_banch_list_test.go b/models/git/protected_branch_list_test.go similarity index 100% rename from models/git/protected_banch_list_test.go rename to models/git/protected_branch_list_test.go From 05fe3169875fbe5ef7c05dbfaf2daa3dc58640c3 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 17 Oct 2024 11:49:27 +0200 Subject: [PATCH 08/39] Update/Insert protectedBranch respect priorityes and add updateFunc for priorities --- models/git/protected_branch.go | 52 +++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index 0b14107c7fa96..1047823f274b6 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -411,19 +411,51 @@ func UpdateProtectBranch(ctx context.Context, repo *repo_model.Repository, prote } protectBranch.ApprovalsWhitelistTeamIDs = whitelist - // Make sure protectBranch.ID is not 0 for whitelists - if protectBranch.ID == 0 { - if _, err = db.GetEngine(ctx).Insert(protectBranch); err != nil { - return fmt.Errorf("Insert: %v", err) + return db.WithTx(ctx, func(ctx context.Context) error { + // Looks like it's a new rule + if protectBranch.ID == 0 { + // as it's a new rule and if priority was not set, we need to calc it. + if protectBranch.Priority == 0 { + var lowestPrio int64 + db.GetEngine(ctx).Table(protectBranch). + Select("MAX(priority)"). + Where("repo_id = ?", protectBranch.RepoID). + Get(&lowestPrio) + log.Trace("Create new ProtectedBranch at repo[%d] and detect current lowest priority '%d'", protectBranch.RepoID, lowestPrio) + protectBranch.Priority = lowestPrio + 1 + } + + if _, err = db.GetEngine(ctx).Insert(protectBranch); err != nil { + return fmt.Errorf("Insert: %v", err) + } + return nil } - return nil - } - if _, err = db.GetEngine(ctx).ID(protectBranch.ID).AllCols().Update(protectBranch); err != nil { - return fmt.Errorf("Update: %v", err) - } + // update the rule + if _, err = db.GetEngine(ctx).ID(protectBranch.ID).AllCols().Update(protectBranch); err != nil { + return fmt.Errorf("Update: %v", err) + } - return nil + return nil + }) +} + +func UpdateProtectBranchPriorities(ctx context.Context, repo *repo_model.Repository, ids []int64) error { + prio := int64(1) + return db.WithTx(ctx, func(ctx context.Context) error { + for _, id := range ids { + if _, err := db.GetEngine(ctx). + ID(id).Where("repo_id = ?", repo.ID). + Cols("priority"). + Update(&ProtectedBranch{ + Priority: prio, + }); err != nil { + return err + } + prio++ + } + return nil + }) } // updateApprovalWhitelist checks whether the user whitelist changed and returns a whitelist with From 6c1ffb7ab01df004fa4af4dd491efa24915c6a62 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 17 Oct 2024 13:36:08 +0200 Subject: [PATCH 09/39] api --- modules/structs/repo_branch.go | 3 +++ routers/api/v1/repo/branch.go | 5 +++++ services/convert/convert.go | 1 + templates/swagger/v1_json.tmpl | 15 +++++++++++++++ 4 files changed, 24 insertions(+) diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go index 0f2cf482fd5a2..88279150f7cd4 100644 --- a/modules/structs/repo_branch.go +++ b/modules/structs/repo_branch.go @@ -25,6 +25,7 @@ type BranchProtection struct { // Deprecated: true BranchName string `json:"branch_name"` RuleName string `json:"rule_name"` + Priority int64 `json:"priority"` EnablePush bool `json:"enable_push"` EnablePushWhitelist bool `json:"enable_push_whitelist"` PushWhitelistUsernames []string `json:"push_whitelist_usernames"` @@ -63,6 +64,7 @@ type CreateBranchProtectionOption struct { // Deprecated: true BranchName string `json:"branch_name"` RuleName string `json:"rule_name"` + Priority int64 `json:"priority"` EnablePush bool `json:"enable_push"` EnablePushWhitelist bool `json:"enable_push_whitelist"` PushWhitelistUsernames []string `json:"push_whitelist_usernames"` @@ -94,6 +96,7 @@ type CreateBranchProtectionOption struct { // EditBranchProtectionOption options for editing a branch protection type EditBranchProtectionOption struct { + Priority *int64 `json:"priority"` EnablePush *bool `json:"enable_push"` EnablePushWhitelist *bool `json:"enable_push_whitelist"` PushWhitelistUsernames []string `json:"push_whitelist_usernames"` diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 63de4b8b6a2be..666e5bf4a7ae6 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -623,6 +623,7 @@ func CreateBranchProtection(ctx *context.APIContext) { protectBranch = &git_model.ProtectedBranch{ RepoID: ctx.Repo.Repository.ID, RuleName: ruleName, + Priority: form.Priority, CanPush: form.EnablePush, EnableWhitelist: form.EnablePush && form.EnablePushWhitelist, WhitelistDeployKeys: form.EnablePush && form.EnablePushWhitelist && form.PushWhitelistDeployKeys, @@ -800,6 +801,10 @@ func EditBranchProtection(ctx *context.APIContext) { } } + if form.Priority != nil { + protectBranch.Priority = *form.Priority + } + if form.EnableMergeWhitelist != nil { protectBranch.EnableMergeWhitelist = *form.EnableMergeWhitelist } diff --git a/services/convert/convert.go b/services/convert/convert.go index 041d553e98cc5..75e9d6ae802da 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -158,6 +158,7 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch, repo return &api.BranchProtection{ BranchName: branchName, RuleName: bp.RuleName, + Priority: bp.Priority, EnablePush: bp.CanPush, EnablePushWhitelist: bp.EnableWhitelist, PushWhitelistUsernames: pushWhitelistUsernames, diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 2cbd8782d8410..ccd4145062951 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -18837,6 +18837,11 @@ }, "x-go-name": "MergeWhitelistUsernames" }, + "priority": { + "type": "integer", + "format": "int64", + "x-go-name": "Priority" + }, "protected_file_patterns": { "type": "string", "x-go-name": "ProtectedFilePatterns" @@ -19527,6 +19532,11 @@ }, "x-go-name": "MergeWhitelistUsernames" }, + "priority": { + "type": "integer", + "format": "int64", + "x-go-name": "Priority" + }, "protected_file_patterns": { "type": "string", "x-go-name": "ProtectedFilePatterns" @@ -20741,6 +20751,11 @@ }, "x-go-name": "MergeWhitelistUsernames" }, + "priority": { + "type": "integer", + "format": "int64", + "x-go-name": "Priority" + }, "protected_file_patterns": { "type": "string", "x-go-name": "ProtectedFilePatterns" From 3ed30a745e3cd9ca3749df6bdb31d35fc5868944 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Thu, 17 Oct 2024 13:57:10 +0200 Subject: [PATCH 10/39] Add api to update --- modules/structs/repo_branch.go | 3 ++ routers/api/v1/api.go | 1 + routers/api/v1/repo/branch.go | 44 ++++++++++++++++++++++ routers/api/v1/swagger/options.go | 3 ++ templates/swagger/v1_json.tmpl | 61 +++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+) diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go index 88279150f7cd4..e3451b1fdcdbf 100644 --- a/modules/structs/repo_branch.go +++ b/modules/structs/repo_branch.go @@ -125,3 +125,6 @@ type EditBranchProtectionOption struct { ProtectedFilePatterns *string `json:"protected_file_patterns"` UnprotectedFilePatterns *string `json:"unprotected_file_patterns"` } + +// UpdateBranchProtectionPriories a list to update the branch protection rule priorities +type UpdateBranchProtectionPriories []int64 diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 883e694e44b75..51d56ff4df17f 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1196,6 +1196,7 @@ func Routes() *web.Router { m.Patch("", bind(api.EditBranchProtectionOption{}), mustNotBeArchived, repo.EditBranchProtection) m.Delete("", repo.DeleteBranchProtection) }) + m.Post("/priority/move", bind(api.UpdateBranchProtectionPriories{}), mustNotBeArchived, repo.UpdateBranchProtectionPriories) }, reqToken(), reqAdmin()) m.Group("/tags", func() { m.Get("", repo.ListTags) diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 666e5bf4a7ae6..68809df7d1815 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -1085,3 +1085,47 @@ func DeleteBranchProtection(ctx *context.APIContext) { ctx.Status(http.StatusNoContent) } + +// UpdateBranchProtectionPriories updates the priorities of branch protections for a repo +func UpdateBranchProtectionPriories(ctx *context.APIContext) { + // swagger:operation POST /repos/{owner}/{repo}/branch_protections/priority/move repository repoUpdateBranchProtectionPriories + // --- + // summary: Update the priorities of branch protections for a repository. + // consumes: + // - application/json + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: body + // in: body + // schema: + // "$ref": "#/definitions/UpdateBranchProtectionPriories" + // responses: + // "204": + // "$ref": "#/responses/empty" + // "404": + // "$ref": "#/responses/notFound" + // "422": + // "$ref": "#/responses/validationError" + // "423": + // "$ref": "#/responses/repoArchivedError" + form := web.GetForm(ctx).(*api.UpdateBranchProtectionPriories) + repo := ctx.Repo.Repository + + if err := git_model.UpdateProtectBranchPriorities(ctx, repo, *form); err != nil { + ctx.Error(http.StatusInternalServerError, "UpdateProtectBranchPriorities", err) + return + } + + ctx.Status(http.StatusNoContent) +} diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go index 1de58632d57fa..39c98c666e545 100644 --- a/routers/api/v1/swagger/options.go +++ b/routers/api/v1/swagger/options.go @@ -146,6 +146,9 @@ type swaggerParameterBodies struct { // in:body EditBranchProtectionOption api.EditBranchProtectionOption + // in:body + UpdateBranchProtectionPriories api.UpdateBranchProtectionPriories + // in:body CreateOAuth2ApplicationOptions api.CreateOAuth2ApplicationOptions diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index ccd4145062951..fa5c67635fde7 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -4642,6 +4642,58 @@ } } }, + "/repos/{owner}/{repo}/branch_protections/priority/move": { + "post": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "repository" + ], + "summary": "Update the priorities of branch protections for a repository.", + "operationId": "repoUpdateBranchProtectionPriories", + "parameters": [ + { + "type": "string", + "description": "owner of the repo", + "name": "owner", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "name of the repo", + "name": "repo", + "in": "path", + "required": true + }, + { + "name": "body", + "in": "body", + "schema": { + "$ref": "#/definitions/UpdateBranchProtectionPriories" + } + } + ], + "responses": { + "204": { + "$ref": "#/responses/empty" + }, + "404": { + "$ref": "#/responses/notFound" + }, + "422": { + "$ref": "#/responses/validationError" + }, + "423": { + "$ref": "#/responses/repoArchivedError" + } + } + } + }, "/repos/{owner}/{repo}/branch_protections/{name}": { "get": { "produces": [ @@ -24842,6 +24894,15 @@ }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, + "UpdateBranchProtectionPriories": { + "description": "UpdateBranchProtectionPriories a list to update the branch protection rule priorities", + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "x-go-package": "code.gitea.io/gitea/modules/structs" + }, "UpdateFileOptions": { "description": "UpdateFileOptions options for updating files\nNote: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)", "type": "object", From 5dd06235cc9e25a243a3455c1a66d3a2bfd99f17 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 16:51:08 +0200 Subject: [PATCH 11/39] future profe API as its an object we can add stuff later on --- modules/structs/repo_branch.go | 4 +++- routers/api/v1/repo/branch.go | 7 ++++++- templates/swagger/v1_json.tmpl | 10 ++++++++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go index e3451b1fdcdbf..afa042944be13 100644 --- a/modules/structs/repo_branch.go +++ b/modules/structs/repo_branch.go @@ -127,4 +127,6 @@ type EditBranchProtectionOption struct { } // UpdateBranchProtectionPriories a list to update the branch protection rule priorities -type UpdateBranchProtectionPriories []int64 +type UpdateBranchProtectionPriories []struct { + ID int64 `json:"id"` +} diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 68809df7d1815..d1115bd22ba4f 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -1122,7 +1122,12 @@ func UpdateBranchProtectionPriories(ctx *context.APIContext) { form := web.GetForm(ctx).(*api.UpdateBranchProtectionPriories) repo := ctx.Repo.Repository - if err := git_model.UpdateProtectBranchPriorities(ctx, repo, *form); err != nil { + ids := make([]int64, len(*form)) + for i, v := range *form { + ids[i] = v.ID + } + + if err := git_model.UpdateProtectBranchPriorities(ctx, repo, ids); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateProtectBranchPriorities", err) return } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 29f4f4af74185..ce0655b86d815 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -24922,8 +24922,14 @@ "description": "UpdateBranchProtectionPriories a list to update the branch protection rule priorities", "type": "array", "items": { - "type": "integer", - "format": "int64" + "type": "object", + "properties": { + "id": { + "type": "integer", + "format": "int64", + "x-go-name": "ID" + } + } }, "x-go-package": "code.gitea.io/gitea/modules/structs" }, From bc81f757b1a3c20476f8adec3903e84845827cf0 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 19:00:16 +0200 Subject: [PATCH 12/39] add route for webui --- routers/web/repo/setting/protected_branch.go | 10 ++++++++++ routers/web/web.go | 1 + 2 files changed, 11 insertions(+) diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index 7d943fd434dfe..e34bdcd01f768 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -321,6 +321,16 @@ func DeleteProtectedBranchRulePost(ctx *context.Context) { ctx.JSONRedirect(fmt.Sprintf("%s/settings/branches", ctx.Repo.RepoLink)) } +func UpdateBranchProtectionPriories(ctx *context.Context) { + form := web.GetForm(ctx).([]int64) + repo := ctx.Repo.Repository + + if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form); err != nil { + ctx.ServerError("UpdateProtectBranchPriorities", err) + return + } +} + // RenameBranchPost responses for rename a branch func RenameBranchPost(ctx *context.Context) { form := web.GetForm(ctx).(*forms.RenameBranchForm) diff --git a/routers/web/web.go b/routers/web/web.go index f28ec82c8f0b8..cd26ddc3289b5 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1075,6 +1075,7 @@ func registerRoutes(m *web.Router) { m.Combo("/edit").Get(repo_setting.SettingsProtectedBranch). Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.SettingsProtectedBranchPost) m.Post("/{id}/delete", repo_setting.DeleteProtectedBranchRulePost) + m.Post("/priority", web.Bind([]int64{}), context.RepoMustNotBeArchived(), repo_setting.UpdateBranchProtectionPriories) }) m.Group("/tags", func() { From c83fce90dfebc9377a467f6beb5f74e78a054154 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 19:00:48 +0200 Subject: [PATCH 13/39] add grabber octicon --- web_src/js/svg.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts index 6a4bfafc9244c..6870682f1662f 100644 --- a/web_src/js/svg.ts +++ b/web_src/js/svg.ts @@ -34,6 +34,7 @@ import octiconGitCommit from '../../public/assets/img/svg/octicon-git-commit.svg import octiconGitMerge from '../../public/assets/img/svg/octicon-git-merge.svg'; import octiconGitPullRequest from '../../public/assets/img/svg/octicon-git-pull-request.svg'; import octiconGitPullRequestDraft from '../../public/assets/img/svg/octicon-git-pull-request-draft.svg'; +import octiconGrabber from '../../public/assets/img/svg/octicon-grabber.svg'; import octiconHeading from '../../public/assets/img/svg/octicon-heading.svg'; import octiconHorizontalRule from '../../public/assets/img/svg/octicon-horizontal-rule.svg'; import octiconImage from '../../public/assets/img/svg/octicon-image.svg'; @@ -107,6 +108,7 @@ const svgs = { 'octicon-git-merge': octiconGitMerge, 'octicon-git-pull-request': octiconGitPullRequest, 'octicon-git-pull-request-draft': octiconGitPullRequestDraft, + 'octicon-grabber': octiconGrabber, 'octicon-heading': octiconHeading, 'octicon-horizontal-rule': octiconHorizontalRule, 'octicon-image': octiconImage, From ae19b8e398fa3913b800d474352f609e5b3ede69 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 20:25:17 +0200 Subject: [PATCH 14/39] wip? --- templates/repo/settings/branches.tmpl | 27 +++++++++++-------- web_src/js/features/repo-settings-branches.ts | 22 +++++++++++++++ web_src/js/index.ts | 2 ++ 3 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 web_src/js/features/repo-settings-branches.ts diff --git a/templates/repo/settings/branches.tmpl b/templates/repo/settings/branches.tmpl index 6f070ba61cd0f..aae13f2bbfcef 100644 --- a/templates/repo/settings/branches.tmpl +++ b/templates/repo/settings/branches.tmpl @@ -37,19 +37,24 @@
-
+
{{range .ProtectedBranches}} -
-
-
-
{{.RuleName}}
+
+
+
+ {{svg "octicon-grabber" 16}} +
+
+
+
{{.RuleName}}
+
+
+
+ {{ctx.Locale.Tr "repo.settings.edit_protected_branch"}} +
-
-
- {{ctx.Locale.Tr "repo.settings.edit_protected_branch"}} -
{{else}} diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts new file mode 100644 index 0000000000000..e10de788dbe24 --- /dev/null +++ b/web_src/js/features/repo-settings-branches.ts @@ -0,0 +1,22 @@ +import {createSortable} from '../modules/sortable.ts'; +import {POST} from '../modules/fetch.ts'; + +export function initRepoBranchesSettings() { + const protectedBranchesList = document.getElementById('protected-branches-list'); + if (!protectedBranchesList) return; + + createSortable(protectedBranchesList, { + handle: '.drag-handle', + animation: 150, + onEnd: async (evt) => { + const newOrder = Array.from(protectedBranchesList.children).map((item) => item.dataset.id); + try { + await POST(protectedBranchesList.getAttribute('data-priority-url'), { + data: newOrder, + }); + } catch (err) { + console.error('Failed to update branch protection rule priority:', err); + } + }, + }); +} diff --git a/web_src/js/index.ts b/web_src/js/index.ts index 13dfe1f3efe1c..8c2db24671a67 100644 --- a/web_src/js/index.ts +++ b/web_src/js/index.ts @@ -49,6 +49,7 @@ import { initRepoSettingsCollaboration, initRepoSettingSearchTeamBox, } from './features/repo-settings.ts'; +import {initRepoBranchesSettings} from './features/repo-settings-branches.ts'; import {initRepoDiffView} from './features/repo-diff.ts'; import {initOrgTeamSearchRepoBox, initOrgTeamSettings} from './features/org-team.ts'; import {initUserAuthWebAuthn, initUserAuthWebAuthnRegister} from './features/user-auth-webauthn.ts'; @@ -206,6 +207,7 @@ onDomReady(() => { initRepoSettingGitHook, initRepoSettingSearchTeamBox, initRepoSettingsCollaboration, + initRepoBranchesSettings, initRepoTemplateSearch, initRepoTopicBar, initRepoWikiForm, From 19b2b7c6659070d17159acd23db08a98e823605b Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 21:07:54 +0200 Subject: [PATCH 15/39] form expect struct --- routers/web/repo/setting/protected_branch.go | 4 ++-- routers/web/web.go | 2 +- services/forms/repo_form.go | 4 ++++ web_src/js/features/repo-settings-branches.ts | 10 ++++++++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index e34bdcd01f768..3d9127a441d04 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -322,10 +322,10 @@ func DeleteProtectedBranchRulePost(ctx *context.Context) { } func UpdateBranchProtectionPriories(ctx *context.Context) { - form := web.GetForm(ctx).([]int64) + form := web.GetForm(ctx).(*forms.ProtectBranchPriorityForm) repo := ctx.Repo.Repository - if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form); err != nil { + if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form.IDS); err != nil { ctx.ServerError("UpdateProtectBranchPriorities", err) return } diff --git a/routers/web/web.go b/routers/web/web.go index cd26ddc3289b5..57d9ead510fef 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -1075,7 +1075,7 @@ func registerRoutes(m *web.Router) { m.Combo("/edit").Get(repo_setting.SettingsProtectedBranch). Post(web.Bind(forms.ProtectBranchForm{}), context.RepoMustNotBeArchived(), repo_setting.SettingsProtectedBranchPost) m.Post("/{id}/delete", repo_setting.DeleteProtectedBranchRulePost) - m.Post("/priority", web.Bind([]int64{}), context.RepoMustNotBeArchived(), repo_setting.UpdateBranchProtectionPriories) + m.Post("/priority", web.Bind(forms.ProtectBranchPriorityForm{}), context.RepoMustNotBeArchived(), repo_setting.UpdateBranchProtectionPriories) }) m.Group("/tags", func() { diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 988e479a48138..29ad9766f5ad9 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -227,6 +227,10 @@ func (f *ProtectBranchForm) Validate(req *http.Request, errs binding.Errors) bin return middleware.Validate(errs, ctx.Data, f, ctx.Locale) } +type ProtectBranchPriorityForm struct { + IDS []int64 +} + // __ __ ___. .__ __ // / \ / \ ____\_ |__ | |__ ____ ____ | | __ // \ \/\/ // __ \| __ \| | \ / _ \ / _ \| |/ / diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index e10de788dbe24..1ead3a2ac5c25 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -9,10 +9,16 @@ export function initRepoBranchesSettings() { handle: '.drag-handle', animation: 150, onEnd: async (evt) => { - const newOrder = Array.from(protectedBranchesList.children).map((item) => item.dataset.id); + const newOrder = Array.from(protectedBranchesList.children).map((item) => { + const id = item.dataset.id; + return id ? parseInt(id, 10) : NaN; + }).filter(id => !isNaN(id)); + try { await POST(protectedBranchesList.getAttribute('data-priority-url'), { - data: newOrder, + data: { + ids: newOrder, + }, }); } catch (err) { console.error('Failed to update branch protection rule priority:', err); From 78c9d4c2ee3610e9a60f98f61e7f15da97bd947b Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 21:21:17 +0200 Subject: [PATCH 16/39] fix lints --- models/git/protected_branch.go | 6 ++++-- services/forms/repo_form.go | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index 1047823f274b6..b35a138c0e800 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -417,10 +417,12 @@ func UpdateProtectBranch(ctx context.Context, repo *repo_model.Repository, prote // as it's a new rule and if priority was not set, we need to calc it. if protectBranch.Priority == 0 { var lowestPrio int64 - db.GetEngine(ctx).Table(protectBranch). + if _, err := db.GetEngine(ctx).Table(protectBranch). Select("MAX(priority)"). Where("repo_id = ?", protectBranch.RepoID). - Get(&lowestPrio) + Get(&lowestPrio); err != nil { + return err + } log.Trace("Create new ProtectedBranch at repo[%d] and detect current lowest priority '%d'", protectBranch.RepoID, lowestPrio) protectBranch.Priority = lowestPrio + 1 } diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index 29ad9766f5ad9..df428d4fc50b4 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -228,7 +228,7 @@ func (f *ProtectBranchForm) Validate(req *http.Request, errs binding.Errors) bin } type ProtectBranchPriorityForm struct { - IDS []int64 + IDs []int64 } // __ __ ___. .__ __ From 962ea78e9c0f10c17295ae795d0c8cbb4bfa4682 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 21:23:06 +0200 Subject: [PATCH 17/39] fix lints --- routers/web/repo/setting/protected_branch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index 3d9127a441d04..1c37fd5fdb12b 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -325,7 +325,7 @@ func UpdateBranchProtectionPriories(ctx *context.Context) { form := web.GetForm(ctx).(*forms.ProtectBranchPriorityForm) repo := ctx.Repo.Repository - if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form.IDS); err != nil { + if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form.IDs); err != nil { ctx.ServerError("UpdateProtectBranchPriorities", err) return } From 5056af5fac0d79c3bc637378ae54be6284cf5657 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 21:33:27 +0200 Subject: [PATCH 18/39] fix webui lint issues --- web_src/js/features/repo-settings-branches.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 1ead3a2ac5c25..fe37035b4b6c3 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -2,15 +2,15 @@ import {createSortable} from '../modules/sortable.ts'; import {POST} from '../modules/fetch.ts'; export function initRepoBranchesSettings() { - const protectedBranchesList = document.getElementById('protected-branches-list'); + const protectedBranchesList = document.querySelector('#protected-branches-list'); if (!protectedBranchesList) return; createSortable(protectedBranchesList, { handle: '.drag-handle', animation: 150, - onEnd: async (evt) => { - const newOrder = Array.from(protectedBranchesList.children).map((item) => { - const id = item.dataset.id; + onEnd: async (e) => { // eslint-disable-line @typescript-eslint/no-misused-promises + const newOrder = Array.from(protectedBranchesList.children, (item) => { + const id = item.getAttribute('data-id'); return id ? parseInt(id, 10) : NaN; }).filter(id => !isNaN(id)); From b939a8d32a253f6dee367ea98668f5f260fc74a1 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 21:45:27 +0200 Subject: [PATCH 19/39] fix webui lint issues --- web_src/js/features/repo-settings-branches.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index fe37035b4b6c3..a0f53f479f38c 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -2,17 +2,19 @@ import {createSortable} from '../modules/sortable.ts'; import {POST} from '../modules/fetch.ts'; export function initRepoBranchesSettings() { - const protectedBranchesList = document.querySelector('#protected-branches-list'); + const protectedBranchesList = document.querySelector( + '#protected-branches-list', + ); if (!protectedBranchesList) return; createSortable(protectedBranchesList, { handle: '.drag-handle', animation: 150, - onEnd: async (e) => { // eslint-disable-line @typescript-eslint/no-misused-promises + onEnd: async () => { // eslint-disable-line @typescript-eslint/no-misused-promises const newOrder = Array.from(protectedBranchesList.children, (item) => { const id = item.getAttribute('data-id'); - return id ? parseInt(id, 10) : NaN; - }).filter(id => !isNaN(id)); + return id ? parseInt(id) : NaN; + }).filter((id) => !Number.isNaN(id)); try { await POST(protectedBranchesList.getAttribute('data-priority-url'), { From 7939780ae68370c1f6abaa4d011598788bf81fdf Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Mon, 21 Oct 2024 21:59:18 +0200 Subject: [PATCH 20/39] limit scope --- routers/api/v1/repo/branch.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index d1115bd22ba4f..35ae8308b0b85 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -645,7 +645,7 @@ func CreateBranchProtection(ctx *context.APIContext) { BlockOnOutdatedBranch: form.BlockOnOutdatedBranch, } - err = git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{ + if err := git_model.UpdateProtectBranch(ctx, ctx.Repo.Repository, protectBranch, git_model.WhitelistOptions{ UserIDs: whitelistUsers, TeamIDs: whitelistTeams, ForcePushUserIDs: forcePushAllowlistUsers, @@ -654,14 +654,13 @@ func CreateBranchProtection(ctx *context.APIContext) { MergeTeamIDs: mergeWhitelistTeams, ApprovalsUserIDs: approvalsWhitelistUsers, ApprovalsTeamIDs: approvalsWhitelistTeams, - }) - if err != nil { + }); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateProtectBranch", err) return } if isBranchExist { - if err = pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, ruleName); err != nil { + if err := pull_service.CheckPRsForBaseBranch(ctx, ctx.Repo.Repository, ruleName); err != nil { ctx.Error(http.StatusInternalServerError, "CheckPRsForBaseBranch", err) return } From 7f2bcf9c497799bac880dd72106dd2da1a19334c Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Nov 2024 17:08:53 +0100 Subject: [PATCH 21/39] backend tests --- models/git/protected_branch_test.go | 78 +++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/models/git/protected_branch_test.go b/models/git/protected_branch_test.go index 1962859a8c4e3..592ee2f237694 100644 --- a/models/git/protected_branch_test.go +++ b/models/git/protected_branch_test.go @@ -8,6 +8,10 @@ import ( "testing" "github.com/stretchr/testify/assert" + + "code.gitea.io/gitea/models/db" + repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unittest" ) func TestBranchRuleMatch(t *testing.T) { @@ -76,3 +80,77 @@ func TestBranchRuleMatch(t *testing.T) { ) } } + +func TestUpdateProtectBranchPriorities(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + // Create some test protected branches with initial priorities + protectedBranches := []*ProtectedBranch{ + { + RepoID: repo.ID, + RuleName: "master", + Priority: 1, + }, + { + RepoID: repo.ID, + RuleName: "develop", + Priority: 2, + }, + { + RepoID: repo.ID, + RuleName: "feature/*", + Priority: 3, + }, + } + + for _, pb := range protectedBranches { + _, err := db.GetEngine(db.DefaultContext).Insert(pb) + assert.NoError(t, err) + } + + // Test updating priorities + newPriorities := []int64{protectedBranches[2].ID, protectedBranches[0].ID, protectedBranches[1].ID} + err := UpdateProtectBranchPriorities(db.DefaultContext, repo, newPriorities) + assert.NoError(t, err) + + // Verify new priorities + pbs, err := FindRepoProtectedBranchRules(db.DefaultContext, repo.ID) + assert.NoError(t, err) + + expectedPriorities := map[string]int64{ + "feature/*": 1, + "master": 2, + "develop": 3, + } + + for _, pb := range pbs { + assert.Equal(t, expectedPriorities[pb.RuleName], pb.Priority) + } +} + +func TestNewProtectBranchPriority(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + + err := UpdateProtectBranch(db.DefaultContext, repo, &ProtectedBranch{ + RepoID: repo.ID, + RuleName: "branch-1", + Priority: 1, + }, WhitelistOptions{}) + assert.NoError(t, err) + + newPB := &ProtectedBranch{ + RepoID: repo.ID, + RuleName: "branch-2", + // Priority intentionally omitted + } + + err = UpdateProtectBranch(db.DefaultContext, repo, newPB, WhitelistOptions{}) + assert.NoError(t, err) + + savedPB2, err := GetFirstMatchProtectedBranchRule(db.DefaultContext, repo.ID, "branch-2") + assert.NoError(t, err) + assert.Equal(t, int64(2), savedPB2.Priority) +} From 9606f7ed6eff4690fc0ce75bdcda1e2f774dd33b Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Nov 2024 17:28:58 +0100 Subject: [PATCH 22/39] frontend test --- .../features/repo-settings-branches.test.ts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 web_src/js/features/repo-settings-branches.test.ts diff --git a/web_src/js/features/repo-settings-branches.test.ts b/web_src/js/features/repo-settings-branches.test.ts new file mode 100644 index 0000000000000..1ff84e5bf5725 --- /dev/null +++ b/web_src/js/features/repo-settings-branches.test.ts @@ -0,0 +1,77 @@ +import {beforeEach, describe, expect, test, vi} from 'vitest'; +import {initRepoBranchesSettings} from './repo-settings-branches.ts'; +import {POST} from '../modules/fetch.ts'; +import {createSortable} from '../modules/sortable.ts'; + +vi.mock('../modules/fetch.ts', () => ({ + POST: vi.fn(), +})); + +vi.mock('../modules/sortable.ts', () => ({ + createSortable: vi.fn(), +})); + +describe('Repository Branch Settings', () => { + beforeEach(() => { + document.body.innerHTML = ` +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `; + + vi.clearAllMocks(); + }); + + test('should initialize sortable for protected branches list', () => { + initRepoBranchesSettings(); + + expect(createSortable).toHaveBeenCalledWith( + document.querySelector('#protected-branches-list'), + expect.objectContaining({ + handle: '.drag-handle', + animation: 150, + }), + ); + }); + + test('should not initialize if protected branches list is not present', () => { + document.body.innerHTML = ''; + + initRepoBranchesSettings(); + + expect(createSortable).not.toHaveBeenCalled(); + }); + + test('should post new order after sorting', async () => { + vi.mocked(POST).mockResolvedValue({ok: true} as Response); + + // Mock createSortable to capture and execute the onEnd callback + vi.mocked(createSortable).mockImplementation((_el, options) => { + options.onEnd(); + return {destroy: vi.fn()}; + }); + + initRepoBranchesSettings(); + + expect(POST).toHaveBeenCalledWith( + 'some/repo/branches/priority', + expect.objectContaining({ + data: {ids: [1, 2, 3]}, + }), + ); + }); +}); From 1a3872b5520ceb61b1a9a26b308f873d0440c829 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Nov 2024 17:39:49 +0100 Subject: [PATCH 23/39] more test coverage --- tests/integration/api_branch_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/integration/api_branch_test.go b/tests/integration/api_branch_test.go index dc1aaec2a28c9..8e49516aa7220 100644 --- a/tests/integration/api_branch_test.go +++ b/tests/integration/api_branch_test.go @@ -49,7 +49,7 @@ func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPSta return nil } -func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) { +func testAPICreateBranchProtection(t *testing.T, branchName string, expectedPriority, expectedHTTPStatus int) { token := getUserToken(t, "user2", auth_model.AccessTokenScopeWriteRepository) req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections", &api.BranchProtection{ RuleName: branchName, @@ -60,6 +60,7 @@ func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTP var branchProtection api.BranchProtection DecodeJSON(t, resp, &branchProtection) assert.EqualValues(t, branchName, branchProtection.RuleName) + assert.EqualValues(t, expectedPriority, branchProtection.Priority) } } @@ -189,13 +190,13 @@ func TestAPIBranchProtection(t *testing.T) { defer tests.PrepareTestEnv(t)() // Branch protection on branch that not exist - testAPICreateBranchProtection(t, "master/doesnotexist", http.StatusCreated) + testAPICreateBranchProtection(t, "master/doesnotexist", 1, http.StatusCreated) // Get branch protection on branch that exist but not branch protection testAPIGetBranchProtection(t, "master", http.StatusNotFound) - testAPICreateBranchProtection(t, "master", http.StatusCreated) + testAPICreateBranchProtection(t, "master", 2, http.StatusCreated) // Can only create once - testAPICreateBranchProtection(t, "master", http.StatusForbidden) + testAPICreateBranchProtection(t, "master", 0, http.StatusForbidden) // Can't delete a protected branch testAPIDeleteBranch(t, "master", http.StatusForbidden) From 3cf2120adab5abe862be4375f417df8ac54622a7 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Nov 2024 17:44:07 +0100 Subject: [PATCH 24/39] fix lint --- models/git/protected_branch_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/git/protected_branch_test.go b/models/git/protected_branch_test.go index 592ee2f237694..49d433f845d21 100644 --- a/models/git/protected_branch_test.go +++ b/models/git/protected_branch_test.go @@ -7,11 +7,11 @@ import ( "fmt" "testing" - "github.com/stretchr/testify/assert" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" + + "github.com/stretchr/testify/assert" ) func TestBranchRuleMatch(t *testing.T) { From 59cc58bff0559ed8717d131be19959e0c982f883 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Nov 2024 20:12:35 +0100 Subject: [PATCH 25/39] make mssql work --- models/git/protected_branch.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index 734096d4281cf..1e625a4614861 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -420,9 +420,8 @@ func UpdateProtectBranch(ctx context.Context, repo *repo_model.Repository, prote // as it's a new rule and if priority was not set, we need to calc it. if protectBranch.Priority == 0 { var lowestPrio int64 - if _, err := db.GetEngine(ctx).Table(protectBranch). - Select("MAX(priority)"). - Where("repo_id = ?", protectBranch.RepoID). + // because of mssql we can not use builder or save xorm syntax, so raw sql it is + if _, err := db.GetEngine(ctx).SQL(`SELECT MAX(priority) FROM protected_branch WHERE repo_id = ?`, protectBranch.RepoID). Get(&lowestPrio); err != nil { return err } From dffb634eff0afe7217688b1e4a86a17ef58615d9 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Sat, 9 Nov 2024 20:53:14 +0100 Subject: [PATCH 26/39] simple api path won --- routers/api/v1/api.go | 2 +- routers/api/v1/repo/branch.go | 2 +- templates/swagger/v1_json.tmpl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index d40a0dde28176..3b2812f04a775 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1204,7 +1204,7 @@ func Routes() *web.Router { m.Patch("", bind(api.EditBranchProtectionOption{}), mustNotBeArchived, repo.EditBranchProtection) m.Delete("", repo.DeleteBranchProtection) }) - m.Post("/priority/move", bind(api.UpdateBranchProtectionPriories{}), mustNotBeArchived, repo.UpdateBranchProtectionPriories) + m.Post("/priority", bind(api.UpdateBranchProtectionPriories{}), mustNotBeArchived, repo.UpdateBranchProtectionPriories) }, reqToken(), reqAdmin()) m.Group("/tags", func() { m.Get("", repo.ListTags) diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index e93e5fed4ebeb..7e6c1445a835e 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -1092,7 +1092,7 @@ func DeleteBranchProtection(ctx *context.APIContext) { // UpdateBranchProtectionPriories updates the priorities of branch protections for a repo func UpdateBranchProtectionPriories(ctx *context.APIContext) { - // swagger:operation POST /repos/{owner}/{repo}/branch_protections/priority/move repository repoUpdateBranchProtectionPriories + // swagger:operation POST /repos/{owner}/{repo}/branch_protections/priority repository repoUpdateBranchProtectionPriories // --- // summary: Update the priorities of branch protections for a repository. // consumes: diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 3d79686255865..862cd76a079f2 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -4666,7 +4666,7 @@ } } }, - "/repos/{owner}/{repo}/branch_protections/priority/move": { + "/repos/{owner}/{repo}/branch_protections/priority": { "post": { "consumes": [ "application/json" From f0658d3ec43efef837b44552af60908f7ef4b5ac Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 11 Nov 2024 17:28:06 +0100 Subject: [PATCH 27/39] address TS review --- web_src/js/features/repo-settings-branches.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index a0f53f479f38c..68bde87655a75 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -2,9 +2,7 @@ import {createSortable} from '../modules/sortable.ts'; import {POST} from '../modules/fetch.ts'; export function initRepoBranchesSettings() { - const protectedBranchesList = document.querySelector( - '#protected-branches-list', - ); + const protectedBranchesList = document.querySelector('#protected-branches-list'); if (!protectedBranchesList) return; createSortable(protectedBranchesList, { @@ -13,7 +11,7 @@ export function initRepoBranchesSettings() { onEnd: async () => { // eslint-disable-line @typescript-eslint/no-misused-promises const newOrder = Array.from(protectedBranchesList.children, (item) => { const id = item.getAttribute('data-id'); - return id ? parseInt(id) : NaN; + return parseInt(id); }).filter((id) => !Number.isNaN(id)); try { From 4b9f09c1d0e7841ea61d18a615c8ae6f2a3adcdb Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 11 Nov 2024 17:29:24 +0100 Subject: [PATCH 28/39] sed -i 's/data-priority-url/data-update-priority-url/g' --- templates/repo/settings/branches.tmpl | 2 +- web_src/js/features/repo-settings-branches.test.ts | 2 +- web_src/js/features/repo-settings-branches.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/repo/settings/branches.tmpl b/templates/repo/settings/branches.tmpl index aae13f2bbfcef..be91c6636b9db 100644 --- a/templates/repo/settings/branches.tmpl +++ b/templates/repo/settings/branches.tmpl @@ -37,7 +37,7 @@
-
+
{{range .ProtectedBranches}}
diff --git a/web_src/js/features/repo-settings-branches.test.ts b/web_src/js/features/repo-settings-branches.test.ts index 1ff84e5bf5725..93b8d450bb694 100644 --- a/web_src/js/features/repo-settings-branches.test.ts +++ b/web_src/js/features/repo-settings-branches.test.ts @@ -14,7 +14,7 @@ vi.mock('../modules/sortable.ts', () => ({ describe('Repository Branch Settings', () => { beforeEach(() => { document.body.innerHTML = ` -
+
diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 68bde87655a75..90ef6e9f67f0e 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -15,7 +15,7 @@ export function initRepoBranchesSettings() { }).filter((id) => !Number.isNaN(id)); try { - await POST(protectedBranchesList.getAttribute('data-priority-url'), { + await POST(protectedBranchesList.getAttribute('data-update-priority-url'), { data: { ids: newOrder, }, From 63ccf8223756ca035f5130bfe3aeff8af4d04c80 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 11 Nov 2024 17:31:36 +0100 Subject: [PATCH 29/39] no db.WithTx --- models/git/protected_branch.go | 44 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/models/git/protected_branch.go b/models/git/protected_branch.go index 1e625a4614861..a3caed73c40fa 100644 --- a/models/git/protected_branch.go +++ b/models/git/protected_branch.go @@ -414,34 +414,32 @@ func UpdateProtectBranch(ctx context.Context, repo *repo_model.Repository, prote } protectBranch.ApprovalsWhitelistTeamIDs = whitelist - return db.WithTx(ctx, func(ctx context.Context) error { - // Looks like it's a new rule - if protectBranch.ID == 0 { - // as it's a new rule and if priority was not set, we need to calc it. - if protectBranch.Priority == 0 { - var lowestPrio int64 - // because of mssql we can not use builder or save xorm syntax, so raw sql it is - if _, err := db.GetEngine(ctx).SQL(`SELECT MAX(priority) FROM protected_branch WHERE repo_id = ?`, protectBranch.RepoID). - Get(&lowestPrio); err != nil { - return err - } - log.Trace("Create new ProtectedBranch at repo[%d] and detect current lowest priority '%d'", protectBranch.RepoID, lowestPrio) - protectBranch.Priority = lowestPrio + 1 - } - - if _, err = db.GetEngine(ctx).Insert(protectBranch); err != nil { - return fmt.Errorf("Insert: %v", err) + // Looks like it's a new rule + if protectBranch.ID == 0 { + // as it's a new rule and if priority was not set, we need to calc it. + if protectBranch.Priority == 0 { + var lowestPrio int64 + // because of mssql we can not use builder or save xorm syntax, so raw sql it is + if _, err := db.GetEngine(ctx).SQL(`SELECT MAX(priority) FROM protected_branch WHERE repo_id = ?`, protectBranch.RepoID). + Get(&lowestPrio); err != nil { + return err } - return nil + log.Trace("Create new ProtectedBranch at repo[%d] and detect current lowest priority '%d'", protectBranch.RepoID, lowestPrio) + protectBranch.Priority = lowestPrio + 1 } - // update the rule - if _, err = db.GetEngine(ctx).ID(protectBranch.ID).AllCols().Update(protectBranch); err != nil { - return fmt.Errorf("Update: %v", err) + if _, err = db.GetEngine(ctx).Insert(protectBranch); err != nil { + return fmt.Errorf("Insert: %v", err) } - return nil - }) + } + + // update the rule + if _, err = db.GetEngine(ctx).ID(protectBranch.ID).AllCols().Update(protectBranch); err != nil { + return fmt.Errorf("Update: %v", err) + } + + return nil } func UpdateProtectBranchPriorities(ctx context.Context, repo *repo_model.Repository, ids []int64) error { From ffff47d6355caa4fe39a87dd4688db4a8d31b014 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 11 Nov 2024 18:10:45 +0100 Subject: [PATCH 30/39] toasty error messages --- templates/repo/settings/branches.tmpl | 2 +- web_src/js/features/repo-settings-branches.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/templates/repo/settings/branches.tmpl b/templates/repo/settings/branches.tmpl index be91c6636b9db..aa24846a068f8 100644 --- a/templates/repo/settings/branches.tmpl +++ b/templates/repo/settings/branches.tmpl @@ -39,7 +39,7 @@
{{range .ProtectedBranches}} -
+
{{svg "octicon-grabber" 16}} diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 90ef6e9f67f0e..525b3340e98f1 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -1,5 +1,6 @@ import {createSortable} from '../modules/sortable.ts'; import {POST} from '../modules/fetch.ts'; +import {showErrorToast} from '../modules/toast.ts'; export function initRepoBranchesSettings() { const protectedBranchesList = document.querySelector('#protected-branches-list'); @@ -21,7 +22,8 @@ export function initRepoBranchesSettings() { }, }); } catch (err) { - console.error('Failed to update branch protection rule priority:', err); + const errorMessage = String(err); + showErrorToast(`Failed to update branch protection rule priority:, error: ${errorMessage}`); } }, }); From 4a30f742be4c4f13401bfb81a449a7e9e157ce98 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 11 Nov 2024 18:18:38 +0100 Subject: [PATCH 31/39] update frontend tests --- web_src/js/features/repo-settings-branches.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web_src/js/features/repo-settings-branches.test.ts b/web_src/js/features/repo-settings-branches.test.ts index 93b8d450bb694..f3bae7c6c0466 100644 --- a/web_src/js/features/repo-settings-branches.test.ts +++ b/web_src/js/features/repo-settings-branches.test.ts @@ -15,17 +15,17 @@ describe('Repository Branch Settings', () => { beforeEach(() => { document.body.innerHTML = `
-
+
-
+
-
+
From 08df5593c263f9f7e4b64583bea36500080937d0 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 25 Nov 2024 21:08:40 +0100 Subject: [PATCH 32/39] fix lint err --- web_src/js/features/repo-issue-list.ts | 6 +++- web_src/js/features/repo-settings-branches.ts | 33 ++++++++++--------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/web_src/js/features/repo-issue-list.ts b/web_src/js/features/repo-issue-list.ts index caf517c5e0e71..1f1e76d426663 100644 --- a/web_src/js/features/repo-issue-list.ts +++ b/web_src/js/features/repo-issue-list.ts @@ -196,7 +196,11 @@ async function initIssuePinSort() { createSortable(pinDiv, { group: 'shared', - onEnd: pinMoveEnd, // eslint-disable-line @typescript-eslint/no-misused-promises + onEnd: (e) => { + (async () => { + await pinMoveEnd(e); + })(); + }, }); } diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 525b3340e98f1..2f8179679616a 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -9,22 +9,25 @@ export function initRepoBranchesSettings() { createSortable(protectedBranchesList, { handle: '.drag-handle', animation: 150, - onEnd: async () => { // eslint-disable-line @typescript-eslint/no-misused-promises - const newOrder = Array.from(protectedBranchesList.children, (item) => { - const id = item.getAttribute('data-id'); - return parseInt(id); - }).filter((id) => !Number.isNaN(id)); - try { - await POST(protectedBranchesList.getAttribute('data-update-priority-url'), { - data: { - ids: newOrder, - }, - }); - } catch (err) { - const errorMessage = String(err); - showErrorToast(`Failed to update branch protection rule priority:, error: ${errorMessage}`); - } + onEnd: () => { + (async () => { + const newOrder = Array.from(protectedBranchesList.children, (item) => { + const id = item.getAttribute('data-id'); + return parseInt(id); + }).filter((id) => !Number.isNaN(id)); + + try { + await POST(protectedBranchesList.getAttribute('data-update-priority-url'), { + data: { + ids: newOrder, + }, + }); + } catch (err) { + const errorMessage = String(err); + showErrorToast(`Failed to update branch protection rule priority:, error: ${errorMessage}`); + } + })(); }, }); } From f229044d28a6be7aee0f340bc6a270b4e0b80bf7 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 25 Nov 2024 21:14:48 +0100 Subject: [PATCH 33/39] one diff less --- templates/repo/settings/branches.tmpl | 28 +++++++++---------- .../features/repo-settings-branches.test.ts | 18 ++++-------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/templates/repo/settings/branches.tmpl b/templates/repo/settings/branches.tmpl index aa24846a068f8..8e949abc154aa 100644 --- a/templates/repo/settings/branches.tmpl +++ b/templates/repo/settings/branches.tmpl @@ -39,23 +39,21 @@
{{range .ProtectedBranches}} -
-
-
- {{svg "octicon-grabber" 16}} -
-
-
-
{{.RuleName}}
-
-
-
- {{ctx.Locale.Tr "repo.settings.edit_protected_branch"}} - +
+
+ {{svg "octicon-grabber" 16}} +
+
+
+
{{.RuleName}}
+
+ {{ctx.Locale.Tr "repo.settings.edit_protected_branch"}} + +
{{else}}
diff --git a/web_src/js/features/repo-settings-branches.test.ts b/web_src/js/features/repo-settings-branches.test.ts index f3bae7c6c0466..023039334f905 100644 --- a/web_src/js/features/repo-settings-branches.test.ts +++ b/web_src/js/features/repo-settings-branches.test.ts @@ -15,20 +15,14 @@ describe('Repository Branch Settings', () => { beforeEach(() => { document.body.innerHTML = `
-
-
-
-
+
+
-
-
-
-
+
+
-
-
-
-
+
+
`; From c1bda05feeddb8f5944ce2f93fb7b264c97506c7 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 25 Nov 2024 21:27:03 +0100 Subject: [PATCH 34/39] just struct --- modules/structs/repo_branch.go | 4 ++-- routers/api/v1/repo/branch.go | 7 +------ templates/swagger/v1_json.tmpl | 16 ++++++++-------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go index b90e2966d83dd..a9aa1d330a184 100644 --- a/modules/structs/repo_branch.go +++ b/modules/structs/repo_branch.go @@ -130,6 +130,6 @@ type EditBranchProtectionOption struct { } // UpdateBranchProtectionPriories a list to update the branch protection rule priorities -type UpdateBranchProtectionPriories []struct { - ID int64 `json:"id"` +type UpdateBranchProtectionPriories struct { + IDs []int64 `json:"ids"` } diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 7f94a618c7854..45c5c1cd145b3 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -1121,12 +1121,7 @@ func UpdateBranchProtectionPriories(ctx *context.APIContext) { form := web.GetForm(ctx).(*api.UpdateBranchProtectionPriories) repo := ctx.Repo.Repository - ids := make([]int64, len(*form)) - for i, v := range *form { - ids[i] = v.ID - } - - if err := git_model.UpdateProtectBranchPriorities(ctx, repo, ids); err != nil { + if err := git_model.UpdateProtectBranchPriorities(ctx, repo, form.IDs); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateProtectBranchPriorities", err) return } diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 17e714725a41b..c06c0ad1541c2 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -24955,15 +24955,15 @@ }, "UpdateBranchProtectionPriories": { "description": "UpdateBranchProtectionPriories a list to update the branch protection rule priorities", - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { + "type": "object", + "properties": { + "ids": { + "type": "array", + "items": { "type": "integer", - "format": "int64", - "x-go-name": "ID" - } + "format": "int64" + }, + "x-go-name": "IDs" } }, "x-go-package": "code.gitea.io/gitea/modules/structs" From 056a9a794a73cc90b39f2640ade5875ca5efbaa8 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 25 Nov 2024 21:42:11 +0100 Subject: [PATCH 35/39] fix tmpl --- templates/repo/settings/branches.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/settings/branches.tmpl b/templates/repo/settings/branches.tmpl index 8e949abc154aa..57d9f2c5a831c 100644 --- a/templates/repo/settings/branches.tmpl +++ b/templates/repo/settings/branches.tmpl @@ -39,7 +39,7 @@
{{range .ProtectedBranches}} -
+
{{svg "octicon-grabber" 16}}
From ee28d2f222215afdbe01bef15eb69e7ee21fe7b6 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Tue, 26 Nov 2024 14:32:20 +0100 Subject: [PATCH 36/39] simplify --- web_src/js/features/repo-settings-branches.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 2f8179679616a..3317bd11e45e8 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -12,15 +12,15 @@ export function initRepoBranchesSettings() { onEnd: () => { (async () => { - const newOrder = Array.from(protectedBranchesList.children, (item) => { + const itemIds = Array.from(protectedBranchesList.children, (item) => { const id = item.getAttribute('data-id'); return parseInt(id); - }).filter((id) => !Number.isNaN(id)); + }); try { await POST(protectedBranchesList.getAttribute('data-update-priority-url'), { data: { - ids: newOrder, + ids: itemIds, }, }); } catch (err) { From 6f3308b5ee86f2f34e2172c3af4e1a51caccd118 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Tue, 26 Nov 2024 14:54:18 +0100 Subject: [PATCH 37/39] working --- web_src/js/features/repo-settings-branches.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 3317bd11e45e8..3713a06d03e81 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -1,6 +1,7 @@ import {createSortable} from '../modules/sortable.ts'; import {POST} from '../modules/fetch.ts'; import {showErrorToast} from '../modules/toast.ts'; +import {queryElemChildren} from '../utils/dom.ts'; export function initRepoBranchesSettings() { const protectedBranchesList = document.querySelector('#protected-branches-list'); @@ -12,10 +13,8 @@ export function initRepoBranchesSettings() { onEnd: () => { (async () => { - const itemIds = Array.from(protectedBranchesList.children, (item) => { - const id = item.getAttribute('data-id'); - return parseInt(id); - }); + const itemElems = queryElemChildren(protectedBranchesList, '.item[data-id]'); + const itemIds = Array.from(itemElems, (el) => el.getAttribute('data-id')); try { await POST(protectedBranchesList.getAttribute('data-update-priority-url'), { From 7aa9db157bf632cb7b6e48647c7c33fcda5643ce Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Tue, 26 Nov 2024 17:24:10 +0100 Subject: [PATCH 38/39] parse --- web_src/js/features/repo-settings-branches.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/js/features/repo-settings-branches.ts b/web_src/js/features/repo-settings-branches.ts index 3713a06d03e81..43b98f79b391c 100644 --- a/web_src/js/features/repo-settings-branches.ts +++ b/web_src/js/features/repo-settings-branches.ts @@ -14,7 +14,7 @@ export function initRepoBranchesSettings() { onEnd: () => { (async () => { const itemElems = queryElemChildren(protectedBranchesList, '.item[data-id]'); - const itemIds = Array.from(itemElems, (el) => el.getAttribute('data-id')); + const itemIds = Array.from(itemElems, (el) => parseInt(el.getAttribute('data-id'))); try { await POST(protectedBranchesList.getAttribute('data-update-priority-url'), { From 02756d3da5d89db2acfe297e9eb7aa9313cf76db Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Wed, 27 Nov 2024 05:13:46 +0100 Subject: [PATCH 39/39] nit --- web_src/js/features/repo-settings.ts | 2 ++ web_src/js/index.ts | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web_src/js/features/repo-settings.ts b/web_src/js/features/repo-settings.ts index 72213f794a49c..5a009cfea4b8b 100644 --- a/web_src/js/features/repo-settings.ts +++ b/web_src/js/features/repo-settings.ts @@ -3,6 +3,7 @@ import {minimatch} from 'minimatch'; import {createMonaco} from './codeeditor.ts'; import {onInputDebounce, queryElems, toggleElem} from '../utils/dom.ts'; import {POST} from '../modules/fetch.ts'; +import {initRepoBranchesSettings} from './repo-settings-branches.ts'; const {appSubUrl, csrfToken} = window.config; @@ -154,4 +155,5 @@ export function initRepoSettings() { initRepoSettingsCollaboration(); initRepoSettingsSearchTeamBox(); initRepoSettingsGitHook(); + initRepoBranchesSettings(); } diff --git a/web_src/js/index.ts b/web_src/js/index.ts index 1b0b9536cfdac..90e2d292250d4 100644 --- a/web_src/js/index.ts +++ b/web_src/js/index.ts @@ -64,7 +64,6 @@ import {initCommonIssueListQuickGoto} from './features/common-issue-list.ts'; import {initRepoContributors} from './features/contributors.ts'; import {initRepoCodeFrequency} from './features/code-frequency.ts'; import {initRepoRecentCommits} from './features/recent-commits.ts'; -import {initRepoBranchesSettings} from './features/repo-settings-branches.ts'; import {initRepoDiffCommitBranchesAndTags} from './features/repo-diff-commit.ts'; import {initDirAuto} from './modules/dirauto.ts'; import {initRepositorySearch} from './features/repo-search.ts'; @@ -190,7 +189,6 @@ onDomReady(() => { initRepoPullRequestReview, initRepoRelease, initRepoReleaseNew, - initRepoBranchesSettings, initRepoTemplateSearch, initRepoTopicBar, initRepoWikiForm,