From b51d02148c3ba03bd8691080a9f3e06e421298bc Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Sat, 28 Jul 2018 00:12:15 +0200 Subject: [PATCH 01/12] prevent pull request to be merged when PR is a WIP Signed-off-by: Julien Tant --- models/pull.go | 37 +++++++++++++++++++++ options/locale/locale_en-US.ini | 2 ++ routers/api/v1/repo/pull.go | 2 +- routers/repo/pull.go | 12 +++++++ templates/repo/issue/view_content/pull.tmpl | 6 ++++ 5 files changed, 58 insertions(+), 1 deletion(-) diff --git a/models/pull.go b/models/pull.go index 90b341907d2be..296935d14543d 100644 --- a/models/pull.go +++ b/models/pull.go @@ -1195,6 +1195,43 @@ func (pr *PullRequest) checkAndUpdateStatus() { } } +// Enumerate the prefixes that will help determine if a pull request is a Work In Progress +var pullRequestWorkInProgressPrefixes = [...]string{ + "WIP:", + "[WIP]", +} + +// IsWorkInProgress determine if the Pull Request is a Work In Progress by its title +func (pr *PullRequest) IsWorkInProgress() bool { + if err := pr.LoadIssue(); err != nil { + log.Error(4, "LoadIssue: %v", err) + return false + } + + for _, prefix := range pullRequestWorkInProgressPrefixes { + if strings.HasPrefix(strings.ToUpper(pr.Issue.Title), prefix) { + return true + } + } + return false +} + +// GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress. +// It returns an empty string when none were found +func (pr *PullRequest) GetWorkInProgressPrefix() string { + if err := pr.LoadIssue(); err != nil { + log.Error(4, "LoadIssue: %v", err) + return "" + } + + for _, prefix := range pullRequestWorkInProgressPrefixes { + if strings.HasPrefix(strings.ToUpper(pr.Issue.Title), prefix) { + return pr.Issue.Title[0:len(prefix)] + } + } + return "" +} + // TestPullRequests checks and tests untested patches of pull requests. // TODO: test more pull requests at same time. func TestPullRequests() { diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 96d450b5ca8d1..ab293b9de38fa 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -829,6 +829,7 @@ pulls.tab_files = Files Changed pulls.reopen_to_merge = Please reopen this pull request to perform a merge. pulls.merged = Merged pulls.has_merged = The pull request has been merged. +pulls.work_in_progress = "This Pull Request is marked as a work in progress. Remove the %s prefix from the title when it's ready" pulls.data_broken = This pull request is broken due to missing fork information. pulls.is_checking = "Merge conflict checking is in progress. Try again in few moments." pulls.can_auto_merge_desc = This pull request can be merged automatically. @@ -836,6 +837,7 @@ pulls.cannot_auto_merge_desc = This pull request cannot be merged automatically pulls.cannot_auto_merge_helper = Merge manually to resolve the conflicts. pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled. pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually. +pulls.no_merge_wip = "This pull request can not be merged because it is marked as being a work in progress." pulls.merge_pull_request = Merge Pull Request pulls.rebase_merge_pull_request = Rebase and Merge pulls.squash_merge_pull_request = Squash and Merge diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index c346d81e33b4b..1527b8e8c988f 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -510,7 +510,7 @@ func MergePullRequest(ctx *context.APIContext, form auth.MergePullRequestForm) { return } - if !pr.CanAutoMerge() || pr.HasMerged { + if !pr.CanAutoMerge() || pr.HasMerged || pr.IsWorkInProgress() { ctx.Status(405) return } diff --git a/routers/repo/pull.go b/routers/repo/pull.go index 1d7747450be0a..e2ee9e13b9640 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -323,6 +323,12 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.PullReq ctx.ServerError("GetPullRequestInfo", err) return nil } + + if pull.IsWorkInProgress() { + ctx.Data["IsPullWorkInProgress"] = true + ctx.Data["WorkInProgressPrefix"] = pull.GetWorkInProgressPrefix() + } + ctx.Data["NumCommits"] = prInfo.Commits.Len() ctx.Data["NumFiles"] = prInfo.NumFiles return prInfo @@ -501,6 +507,12 @@ func MergePullRequest(ctx *context.Context, form auth.MergePullRequestForm) { return } + if pr.IsWorkInProgress() { + ctx.Flash.Error(ctx.Tr("repo.pulls.no_merge_wip")) + ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index)) + return + } + if ctx.HasError() { ctx.Flash.Error(ctx.Data["ErrorMsg"].(string)) ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + com.ToStr(pr.Index)) diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index 9c9dd290a3934..6e9b61482e43f 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -2,6 +2,7 @@ {{$.i18n.Tr "repo.pulls.data_broken"}} + {{else if .IsPullWorkInProgress}} +
+ + {{$.i18n.Tr "repo.pulls.work_in_progress" .WorkInProgressPrefix | Str2html}} +
{{else if .Issue.PullRequest.IsChecking}}
From 4e04e186bd593e13bbba2f73c4b5093e8da1416d Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Sat, 28 Jul 2018 02:02:32 +0200 Subject: [PATCH 02/12] add tests Signed-off-by: Julien Tant --- integrations/api_pull_test.go | 19 +++++++++++++++++++ integrations/pull_merge_test.go | 21 +++++++++++++++++++++ models/pull.go | 2 +- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/integrations/api_pull_test.go b/integrations/api_pull_test.go index b9bab920e18f3..e59b8034f8360 100644 --- a/integrations/api_pull_test.go +++ b/integrations/api_pull_test.go @@ -5,10 +5,12 @@ package integrations import ( + "fmt" "net/http" "testing" "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/auth" api "code.gitea.io/sdk/gitea" "github.com/stretchr/testify/assert" @@ -28,3 +30,20 @@ func TestAPIViewPulls(t *testing.T) { expectedLen := models.GetCount(t, &models.Issue{RepoID: repo.ID}, models.Cond("is_pull = ?", true)) assert.Len(t, pulls, expectedLen) } + +// TestAPIMergePullWIP ensures that we can't merge a WIP pull request +func TestAPIMergePullWIP(t *testing.T) { + prepareTestEnv(t) + repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) + owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User) + pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{Status: models.PullRequestStatusMergeable, HasMerged: false}).(*models.PullRequest) + pr.LoadIssue() + + session := loginUser(t, owner.Name) + req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge", owner.Name, repo.Name, pr.Index), &auth.MergePullRequestForm{ + MergeMessageField: pr.Issue.Title, + Do: string(models.MergeStyleMerge), + }) + + session.MakeRequest(t, req, http.StatusMethodNotAllowed) +} diff --git a/integrations/pull_merge_test.go b/integrations/pull_merge_test.go index 27f3586406ccb..4d3f3c5d0464c 100644 --- a/integrations/pull_merge_test.go +++ b/integrations/pull_merge_test.go @@ -13,6 +13,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/test" + "github.com/Unknwon/i18n" "github.com/stretchr/testify/assert" ) @@ -123,3 +124,23 @@ func TestPullCleanUpAfterMerge(t *testing.T) { assert.EqualValues(t, "Branch 'user1/feature/test' has been deleted.", resultMsg) } + +func TestCantMergeWorkInProgress(t *testing.T) { + prepareTestEnv(t) + session := loginUser(t, "user1") + testRepoFork(t, session, "user2", "repo1", "user1", "repo1") + testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n") + + resp := testPullCreate(t, session, "user1", "repo1", "master", "[wip] This is a pull title") + + req := NewRequest(t, "GET", resp.Header().Get("Location")) + resp = session.MakeRequest(t, req, http.StatusOK) + htmlDoc := NewHTMLParser(t, resp.Body) + text := strings.TrimSpace(htmlDoc.doc.Find(".merge.segment > .text.grey").Text()) + assert.NotEmpty(t, text, "Can't find WIP text") + + // remove from lang + expected := i18n.Tr("en", "repo.pulls.work_in_progress", "[wip]") + replacer := strings.NewReplacer("", "", "", "") + assert.Equal(t, replacer.Replace(expected), text, "Unable to find WIP text") +} diff --git a/models/pull.go b/models/pull.go index 296935d14543d..ac84c93246fc3 100644 --- a/models/pull.go +++ b/models/pull.go @@ -214,7 +214,7 @@ func (pr *PullRequest) APIFormat() *api.PullRequest { } if pr.Status != PullRequestStatusChecking { - mergeable := pr.Status != PullRequestStatusConflict + mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress() apiPullRequest.Mergeable = mergeable } if pr.HasMerged { From 2950078d8ff5360558db9e23067822fd4697034c Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Mon, 30 Jul 2018 00:42:02 +0200 Subject: [PATCH 03/12] add helper to prepend WIP: in PR title --- integrations/pull_merge_test.go | 2 +- options/locale/locale_en-US.ini | 3 ++- public/js/index.js | 14 ++++++++++++++ templates/repo/issue/new_form.tmpl | 5 ++++- templates/repo/issue/view_content/pull.tmpl | 2 +- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/integrations/pull_merge_test.go b/integrations/pull_merge_test.go index 4d3f3c5d0464c..b64f9913d029f 100644 --- a/integrations/pull_merge_test.go +++ b/integrations/pull_merge_test.go @@ -140,7 +140,7 @@ func TestCantMergeWorkInProgress(t *testing.T) { assert.NotEmpty(t, text, "Can't find WIP text") // remove from lang - expected := i18n.Tr("en", "repo.pulls.work_in_progress", "[wip]") + expected := i18n.Tr("en", "repo.pulls.cannot_merge_work_in_progress", "[wip]") replacer := strings.NewReplacer("", "", "", "") assert.Equal(t, replacer.Replace(expected), text, "Unable to find WIP text") } diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index ab293b9de38fa..58e8d96e12d91 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -829,7 +829,8 @@ pulls.tab_files = Files Changed pulls.reopen_to_merge = Please reopen this pull request to perform a merge. pulls.merged = Merged pulls.has_merged = The pull request has been merged. -pulls.work_in_progress = "This Pull Request is marked as a work in progress. Remove the %s prefix from the title when it's ready" +pulls.title_wip_desc = 'Start the title with WIP: to prevent the pull request from being merged accidentally.' +pulls.cannot_merge_work_in_progress = "This pull request is marked as a work in progress. Remove the %s prefix from the title when it's ready" pulls.data_broken = This pull request is broken due to missing fork information. pulls.is_checking = "Merge conflict checking is in progress. Try again in few moments." pulls.can_auto_merge_desc = This pull request can be merged automatically. diff --git a/public/js/index.js b/public/js/index.js index 5f4a7bc774aad..6671553060067 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1557,6 +1557,19 @@ function u2fRegisterRequest() { }); } +function initWipTitle() { + $(".title_wip_desc > a").click(function (e) { + e.preventDefault(); + + var $issueTitle = $("#issue_title"); + var value = $issueTitle.val().trim().toUpperCase(); + + if (!value.startsWith("WIP:") && !value.startsWith("[WIP]")) { + $issueTitle.val("WIP: " + $issueTitle.val()); + } + }); +} + $(document).ready(function () { csrf = $('meta[name=_csrf]').attr("content"); suburl = $('meta[name=_suburl]').attr("content"); @@ -1771,6 +1784,7 @@ $(document).ready(function () { initU2FAuth(); initU2FRegister(); initIssueList(); + initWipTitle(); // Repo clone url. if ($('#repo-clone-url').length > 0) { diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index e904ca4ba7d15..140b261640c6a 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -13,7 +13,10 @@
- + + {{if .PageIsComparePull}} + {{.i18n.Tr "repo.pulls.title_wip_desc" | Safe}} + {{end}}
{{template "repo/issue/comment_tab" .}}
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl index 6e9b61482e43f..92bfc86cb4fa3 100644 --- a/templates/repo/issue/view_content/pull.tmpl +++ b/templates/repo/issue/view_content/pull.tmpl @@ -31,7 +31,7 @@ {{else if .IsPullWorkInProgress}}
- {{$.i18n.Tr "repo.pulls.work_in_progress" .WorkInProgressPrefix | Str2html}} + {{$.i18n.Tr "repo.pulls.cannot_merge_work_in_progress" .WorkInProgressPrefix | Str2html}}
{{else if .Issue.PullRequest.IsChecking}}
From 864f795c508043a621435cd48227f81fb54578a9 Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Mon, 30 Jul 2018 14:34:00 +0200 Subject: [PATCH 04/12] regroup external imports Signed-off-by: Julien Tant --- integrations/pull_merge_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/pull_merge_test.go b/integrations/pull_merge_test.go index b64f9913d029f..b375a55f53b21 100644 --- a/integrations/pull_merge_test.go +++ b/integrations/pull_merge_test.go @@ -13,8 +13,8 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/test" - "github.com/Unknwon/i18n" + "github.com/Unknwon/i18n" "github.com/stretchr/testify/assert" ) From 195b413e999d2d32ce646f568b044e8dfa8e4b75 Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Wed, 1 Aug 2018 09:22:57 +0200 Subject: [PATCH 05/12] move default wip prefixes into settings Signed-off-by: Julien Tant --- custom/conf/app.ini.sample | 3 +++ models/pull.go | 10 ++-------- modules/setting/defaults.go | 5 +++-- modules/setting/setting.go | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index 97a0eac02c530..ca6ac849013ce 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -60,6 +60,9 @@ FILE_MAX_SIZE = 3 ; Max number of files per upload. Defaults to 5 MAX_FILES = 5 +[repository.pull-request] +WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP] + [ui] ; Number of repositories that are displayed on one explore page EXPLORE_PAGING_NUM = 20 diff --git a/models/pull.go b/models/pull.go index ac84c93246fc3..5e7d716029c6a 100644 --- a/models/pull.go +++ b/models/pull.go @@ -1195,12 +1195,6 @@ func (pr *PullRequest) checkAndUpdateStatus() { } } -// Enumerate the prefixes that will help determine if a pull request is a Work In Progress -var pullRequestWorkInProgressPrefixes = [...]string{ - "WIP:", - "[WIP]", -} - // IsWorkInProgress determine if the Pull Request is a Work In Progress by its title func (pr *PullRequest) IsWorkInProgress() bool { if err := pr.LoadIssue(); err != nil { @@ -1208,7 +1202,7 @@ func (pr *PullRequest) IsWorkInProgress() bool { return false } - for _, prefix := range pullRequestWorkInProgressPrefixes { + for _, prefix := range setting.Repository.PullRequest.WorkInProgressPrefixes { if strings.HasPrefix(strings.ToUpper(pr.Issue.Title), prefix) { return true } @@ -1224,7 +1218,7 @@ func (pr *PullRequest) GetWorkInProgressPrefix() string { return "" } - for _, prefix := range pullRequestWorkInProgressPrefixes { + for _, prefix := range setting.Repository.PullRequest.WorkInProgressPrefixes { if strings.HasPrefix(strings.ToUpper(pr.Issue.Title), prefix) { return pr.Issue.Title[0:len(prefix)] } diff --git a/modules/setting/defaults.go b/modules/setting/defaults.go index 527a6af3b9b04..7630d10090ed5 100644 --- a/modules/setting/defaults.go +++ b/modules/setting/defaults.go @@ -5,6 +5,7 @@ import ( ) var ( - defaultLangs = strings.Split("en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR", ",") - defaultLangNames = strings.Split("English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어", ",") + defaultLangs = strings.Split("en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR", ",") + defaultLangNames = strings.Split("English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,français,Nederlands,latviešu,русский,Українська,日本語,español,português do Brasil,polski,български,italiano,suomi,Türkçe,čeština,српски,svenska,한국어", ",") + defaultPullRequestWorkInProgressPrefixes = strings.Split("WIP:,[WIP]", ",") ) diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 1b9919404cfee..78bee7999a58d 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -223,6 +223,11 @@ var ( LocalCopyPath string LocalWikiPath string } `ini:"-"` + + // Pull request settings + PullRequest struct { + WorkInProgressPrefixes []string + } `ini:"repository.pull-request"` }{ AnsiCharset: "", ForcePrivate: false, @@ -266,6 +271,13 @@ var ( LocalCopyPath: "tmp/local-repo", LocalWikiPath: "tmp/local-wiki", }, + + // Pull request settings + PullRequest: struct { + WorkInProgressPrefixes []string + }{ + WorkInProgressPrefixes: defaultPullRequestWorkInProgressPrefixes, + }, } RepoRootPath string ScriptType = "bash" @@ -1024,6 +1036,8 @@ func NewContext() { log.Fatal(4, "Failed to map Repository.Upload settings: %v", err) } else if err = Cfg.Section("repository.local").MapTo(&Repository.Local); err != nil { log.Fatal(4, "Failed to map Repository.Local settings: %v", err) + } else if err = Cfg.Section("repository.pull-request").MapTo(&Repository.PullRequest); err != nil { + log.Fatal(4, "Failed to map Repository.PullRequest settings: %v", err) } if !filepath.IsAbs(Repository.Upload.TempPath) { From eaadddd72faca234dcde3c6089c764b9e21a8c3b Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Wed, 1 Aug 2018 18:54:36 +0200 Subject: [PATCH 06/12] use configurable WIP prefixes in javascript and default to first one in templates --- options/locale/locale_en-US.ini | 2 +- public/js/index.js | 12 ++++++++++-- routers/repo/issue.go | 2 ++ routers/repo/pull.go | 2 ++ templates/repo/issue/new_form.tmpl | 6 +++++- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 58e8d96e12d91..9a994c54a91d5 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -829,7 +829,7 @@ pulls.tab_files = Files Changed pulls.reopen_to_merge = Please reopen this pull request to perform a merge. pulls.merged = Merged pulls.has_merged = The pull request has been merged. -pulls.title_wip_desc = 'Start the title with WIP: to prevent the pull request from being merged accidentally.' +pulls.title_wip_desc = 'Start the title with %s to prevent the pull request from being merged accidentally.' pulls.cannot_merge_work_in_progress = "This pull request is marked as a work in progress. Remove the %s prefix from the title when it's ready" pulls.data_broken = This pull request is broken due to missing fork information. pulls.is_checking = "Merge conflict checking is in progress. Try again in few moments." diff --git a/public/js/index.js b/public/js/index.js index 6671553060067..0fcab4f20f0fd 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1564,8 +1564,16 @@ function initWipTitle() { var $issueTitle = $("#issue_title"); var value = $issueTitle.val().trim().toUpperCase(); - if (!value.startsWith("WIP:") && !value.startsWith("[WIP]")) { - $issueTitle.val("WIP: " + $issueTitle.val()); + var addPrefix = true; + for (var i in wipPrefixes) { + if (value.startsWith(wipPrefixes[i].toUpperCase())) { + addPrefix = false; + break; + } + } + + if (addPrefix) { + $issueTitle.val(wipPrefixes[0] + " " + $issueTitle.val()); } }); } diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 27c95cd9dc6ac..be1f141ed2d20 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -356,6 +356,7 @@ func NewIssue(ctx *context.Context) { ctx.Data["RequireHighlightJS"] = true ctx.Data["RequireSimpleMDE"] = true ctx.Data["RequireTribute"] = true + ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates) renderAttachmentSettings(ctx) @@ -449,6 +450,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) { ctx.Data["RequireHighlightJS"] = true ctx.Data["RequireSimpleMDE"] = true ctx.Data["ReadOnly"] = false + ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes renderAttachmentSettings(ctx) var ( diff --git a/routers/repo/pull.go b/routers/repo/pull.go index e2ee9e13b9640..57a9d1f54e9af 100644 --- a/routers/repo/pull.go +++ b/routers/repo/pull.go @@ -744,6 +744,7 @@ func CompareAndPullRequest(ctx *context.Context) { ctx.Data["IsDiffCompare"] = true ctx.Data["RequireHighlightJS"] = true ctx.Data["RequireTribute"] = true + ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes setTemplateIfExists(ctx, pullRequestTemplateKey, pullRequestTemplateCandidates) renderAttachmentSettings(ctx) @@ -787,6 +788,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm) ctx.Data["PageIsComparePull"] = true ctx.Data["IsDiffCompare"] = true ctx.Data["RequireHighlightJS"] = true + ctx.Data["PullRequestWorkInProgressPrefixes"] = setting.Repository.PullRequest.WorkInProgressPrefixes renderAttachmentSettings(ctx) var ( diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index 140b261640c6a..59be2fb5d1eed 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -15,7 +15,7 @@
{{if .PageIsComparePull}} - {{.i18n.Tr "repo.pulls.title_wip_desc" | Safe}} + {{.i18n.Tr "repo.pulls.title_wip_desc" (index .PullRequestWorkInProgressPrefixes 0) | Safe}} {{end}}
{{template "repo/issue/comment_tab" .}} @@ -153,3 +153,7 @@
+{{if .PageIsComparePull}} + +{{end}} + From f150a2056d787f2932ad809c0cf2a72c4f7079e1 Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Wed, 1 Aug 2018 20:37:57 +0200 Subject: [PATCH 07/12] add documentation --- custom/conf/app.ini.sample | 1 + .../doc/advanced/config-cheat-sheet.en-us.md | 4 +++ docs/content/doc/usage/pull-request.en-us.md | 31 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 docs/content/doc/usage/pull-request.en-us.md diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index ca6ac849013ce..23b8a35aa33ea 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -61,6 +61,7 @@ FILE_MAX_SIZE = 3 MAX_FILES = 5 [repository.pull-request] +; List of prefixes used in Pull Request title to mark them as Work In Progress WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP] [ui] diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 29489d885520b..18ccc87f6a2e6 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -62,6 +62,10 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`. HTTP protocol. - `USE_COMPAT_SSH_URI`: **false**: Force ssh:// clone url instead of scp-style uri when default SSH port is used. + +### Repository - Pull Request (`repository.pull-request`) +- `WORK_IN_PROGRESS_PREFIXES`: **WIP:,\[WIP\]**: List of prefixes used in Pull Request + title to mark them as Work In Progress ## UI (`ui`) diff --git a/docs/content/doc/usage/pull-request.en-us.md b/docs/content/doc/usage/pull-request.en-us.md new file mode 100644 index 0000000000000..29565f4ad4d59 --- /dev/null +++ b/docs/content/doc/usage/pull-request.en-us.md @@ -0,0 +1,31 @@ +--- +date: "2018-06-01T19:00:00+02:00" +title: "Usage: Pull Request" +slug: "pull-request" +weight: 13 +toc: true +draft: false +menu: + sidebar: + parent: "usage" + name: "Pull Request" + weight: 13 + identifier: "pull-request" +--- + +# Pull Request + +## "Work In Progress" pull requests + +Marking a pull request as being a work in progress will prevent that pull request from being accidentally merged. To mark a pull request as being a work in progress, you must prefix its title by `WIP:` or `[WIP]` (case insensitive). Those values are configurable in your `app.ini` file : + +``` +[repository.pull-request] +WORK_IN_PROGRESS_PREFIXES=WIP:,[WIP] +``` + +The first value of the list will be used in helpers. + +## Pull Request Templates + +You can find more information about pull request templates into the dedicated page : [Issue and Pull Request templates](../issue-pull-request-templates) From 45732db95d63ad8e1392df094984a2c064c9403d Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Wed, 1 Aug 2018 21:51:34 +0200 Subject: [PATCH 08/12] add unit test on pull model --- models/pull_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/models/pull_test.go b/models/pull_test.go index e725193bb1766..1dad664077711 100644 --- a/models/pull_test.go +++ b/models/pull_test.go @@ -237,3 +237,34 @@ func TestChangeUsernameInPullRequests(t *testing.T) { } CheckConsistencyFor(t, &PullRequest{}) } + +func TestPullRequest_IsWorkInProgress(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + + pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 2}).(*PullRequest) + pr.LoadIssue() + + assert.False(t, pr.IsWorkInProgress()) + + pr.Issue.Title = "WIP: " + pr.Issue.Title + assert.True(t, pr.IsWorkInProgress()) + + pr.Issue.Title = "[wip]: " + pr.Issue.Title + assert.True(t, pr.IsWorkInProgress()) +} + +func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) { + assert.NoError(t, PrepareTestDatabase()) + + pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 2}).(*PullRequest) + pr.LoadIssue() + + assert.Empty(t, pr.GetWorkInProgressPrefix()) + + original := pr.Issue.Title + pr.Issue.Title = "WIP: " + original + assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix()) + + pr.Issue.Title = "[wip] " + original + assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix()) +} From 404541a6b28c2011e3bfa4b72e5aff35e3ab7f60 Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Thu, 2 Aug 2018 12:15:58 +0200 Subject: [PATCH 09/12] typo --- docs/content/doc/usage/pull-request.en-us.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/doc/usage/pull-request.en-us.md b/docs/content/doc/usage/pull-request.en-us.md index 29565f4ad4d59..171c944ac06b8 100644 --- a/docs/content/doc/usage/pull-request.en-us.md +++ b/docs/content/doc/usage/pull-request.en-us.md @@ -28,4 +28,4 @@ The first value of the list will be used in helpers. ## Pull Request Templates -You can find more information about pull request templates into the dedicated page : [Issue and Pull Request templates](../issue-pull-request-templates) +You can find more information about pull request templates in the dedicated page : [Issue and Pull Request templates](../issue-pull-request-templates) From 6f766a2d6d0bae3bab3aa7a0d9085e7eb5426a23 Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Sun, 12 Aug 2018 23:00:33 +0200 Subject: [PATCH 10/12] simplify javascript --- public/js/index.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/public/js/index.js b/public/js/index.js index 7c167281258f7..a4702a4138f7d 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1662,17 +1662,13 @@ function initWipTitle() { var $issueTitle = $("#issue_title"); var value = $issueTitle.val().trim().toUpperCase(); - var addPrefix = true; for (var i in wipPrefixes) { if (value.startsWith(wipPrefixes[i].toUpperCase())) { - addPrefix = false; - break; + return; } } - if (addPrefix) { - $issueTitle.val(wipPrefixes[0] + " " + $issueTitle.val()); - } + $issueTitle.val(wipPrefixes[0] + " " + $issueTitle.val()); }); } From 7dbb84226ad35a01ecfc2552c14d0f4971a55141 Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Mon, 13 Aug 2018 01:41:02 +0200 Subject: [PATCH 11/12] fix api test --- integrations/api_pull_test.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/integrations/api_pull_test.go b/integrations/api_pull_test.go index e59b8034f8360..e56b91d8b9384 100644 --- a/integrations/api_pull_test.go +++ b/integrations/api_pull_test.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" + "code.gitea.io/gitea/modules/setting" api "code.gitea.io/sdk/gitea" "github.com/stretchr/testify/assert" @@ -36,8 +37,14 @@ func TestAPIMergePullWIP(t *testing.T) { prepareTestEnv(t) repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 1}).(*models.Repository) owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User) - pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{Status: models.PullRequestStatusMergeable, HasMerged: false}).(*models.PullRequest) + pr := models.AssertExistsAndLoadBean(t, &models.PullRequest{Status: models.PullRequestStatusMergeable}, models.Cond("has_merged = ?", false)).(*models.PullRequest) pr.LoadIssue() + pr.Issue.ChangeTitle(owner, setting.Repository.PullRequest.WorkInProgressPrefixes[0]+" "+pr.Issue.Title) + + // force reload + pr.LoadAttributes() + + assert.Contains(t, pr.Issue.Title, setting.Repository.PullRequest.WorkInProgressPrefixes[0]) session := loginUser(t, owner.Name) req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/merge", owner.Name, repo.Name, pr.Index), &auth.MergePullRequestForm{ From cdecb10a125afde7856d9fcf67dba2dc26834b5a Mon Sep 17 00:00:00 2001 From: Julien Tant Date: Mon, 13 Aug 2018 20:35:09 +0200 Subject: [PATCH 12/12] fix js+remove useless quotes in documentation --- options/locale/locale_en-US.ini | 6 +++--- templates/repo/issue/new_form.tmpl | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 6b39f89855bf6..cf02576977111 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -841,8 +841,8 @@ pulls.tab_files = Files Changed pulls.reopen_to_merge = Please reopen this pull request to perform a merge. pulls.merged = Merged pulls.has_merged = The pull request has been merged. -pulls.title_wip_desc = 'Start the title with %s to prevent the pull request from being merged accidentally.' -pulls.cannot_merge_work_in_progress = "This pull request is marked as a work in progress. Remove the %s prefix from the title when it's ready" +pulls.title_wip_desc = `Start the title with %s to prevent the pull request from being merged accidentally.` +pulls.cannot_merge_work_in_progress = This pull request is marked as a work in progress. Remove the %s prefix from the title when it's ready pulls.data_broken = This pull request is broken due to missing fork information. pulls.is_checking = "Merge conflict checking is in progress. Try again in few moments." pulls.can_auto_merge_desc = This pull request can be merged automatically. @@ -850,7 +850,7 @@ pulls.cannot_auto_merge_desc = This pull request cannot be merged automatically pulls.cannot_auto_merge_helper = Merge manually to resolve the conflicts. pulls.no_merge_desc = This pull request cannot be merged because all repository merge options are disabled. pulls.no_merge_helper = Enable merge options in the repository settings or merge the pull request manually. -pulls.no_merge_wip = "This pull request can not be merged because it is marked as being a work in progress." +pulls.no_merge_wip = This pull request can not be merged because it is marked as being a work in progress. pulls.merge_pull_request = Merge Pull Request pulls.rebase_merge_pull_request = Rebase and Merge pulls.squash_merge_pull_request = Squash and Merge diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index 59be2fb5d1eed..943a9b2467082 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -154,6 +154,6 @@
{{if .PageIsComparePull}} - + {{end}}