Skip to content

Commit 1c039b4

Browse files
authored
Fix Bug in Issue Config when only contact links are set (#26521)
Blank Issues should be enabled if they are not explicit disabled through the `blank_issues_enabled` field of the Issue Config. The Implementation has currently a Bug: If you create a Issue Config file with only `contact_links` and without a `blank_issues_enabled` field, `blank_issues_enabled` is set to false by default. The fix is only one line, but I decided to also improve the tests to make sure there are no other problems with the Implementation. This is a bugfix, so it should be backported to 1.20.
1 parent 1f00bc4 commit 1c039b4

File tree

3 files changed

+172
-16
lines changed

3 files changed

+172
-16
lines changed

services/issue/template.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func GetTemplateConfig(gitRepo *git.Repository, path string, commit *git.Commit)
7272
return GetDefaultTemplateConfig(), err
7373
}
7474

75-
issueConfig := api.IssueConfig{}
75+
issueConfig := GetDefaultTemplateConfig()
7676
if err := yaml.Unmarshal(configContent, &issueConfig); err != nil {
7777
return GetDefaultTemplateConfig(), err
7878
}

tests/integration/api_issue_config_test.go

Lines changed: 144 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,167 @@ import (
1515
"code.gitea.io/gitea/tests"
1616

1717
"github.com/stretchr/testify/assert"
18+
"gopkg.in/yaml.v3"
1819
)
1920

20-
func TestAPIReposGetDefaultIssueConfig(t *testing.T) {
21-
defer tests.PrepareTestEnv(t)()
21+
func createIssueConfig(t *testing.T, user *user_model.User, repo *repo_model.Repository, issueConfig map[string]any) {
22+
config, err := yaml.Marshal(issueConfig)
23+
assert.NoError(t, err)
2224

23-
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
24-
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
25+
err = createOrReplaceFileInBranch(user, repo, ".gitea/ISSUE_TEMPLATE/config.yaml", repo.DefaultBranch, string(config))
26+
assert.NoError(t, err)
27+
}
2528

26-
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config", owner.Name, repo.Name)
29+
func getIssueConfig(t *testing.T, owner, repo string) api.IssueConfig {
30+
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config", owner, repo)
2731
req := NewRequest(t, "GET", urlStr)
2832
resp := MakeRequest(t, req, http.StatusOK)
2933

3034
var issueConfig api.IssueConfig
3135
DecodeJSON(t, resp, &issueConfig)
3236

33-
assert.True(t, issueConfig.BlankIssuesEnabled)
34-
assert.Equal(t, issueConfig.ContactLinks, make([]api.IssueConfigContactLink, 0))
37+
return issueConfig
38+
}
39+
40+
func TestAPIRepoGetIssueConfig(t *testing.T) {
41+
defer tests.PrepareTestEnv(t)()
42+
43+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
44+
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
45+
46+
t.Run("Default", func(t *testing.T) {
47+
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
48+
49+
assert.True(t, issueConfig.BlankIssuesEnabled)
50+
assert.Len(t, issueConfig.ContactLinks, 0)
51+
})
52+
53+
t.Run("DisableBlankIssues", func(t *testing.T) {
54+
config := make(map[string]any)
55+
config["blank_issues_enabled"] = false
56+
57+
createIssueConfig(t, owner, repo, config)
58+
59+
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
60+
61+
assert.False(t, issueConfig.BlankIssuesEnabled)
62+
assert.Len(t, issueConfig.ContactLinks, 0)
63+
})
64+
65+
t.Run("ContactLinks", func(t *testing.T) {
66+
contactLink := make(map[string]string)
67+
contactLink["name"] = "TestName"
68+
contactLink["url"] = "https://example.com"
69+
contactLink["about"] = "TestAbout"
70+
71+
config := make(map[string]any)
72+
config["contact_links"] = []map[string]string{contactLink}
73+
74+
createIssueConfig(t, owner, repo, config)
75+
76+
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
77+
78+
assert.True(t, issueConfig.BlankIssuesEnabled)
79+
assert.Len(t, issueConfig.ContactLinks, 1)
80+
81+
assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name)
82+
assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL)
83+
assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About)
84+
})
85+
86+
t.Run("Full", func(t *testing.T) {
87+
contactLink := make(map[string]string)
88+
contactLink["name"] = "TestName"
89+
contactLink["url"] = "https://example.com"
90+
contactLink["about"] = "TestAbout"
91+
92+
config := make(map[string]any)
93+
config["blank_issues_enabled"] = false
94+
config["contact_links"] = []map[string]string{contactLink}
95+
96+
createIssueConfig(t, owner, repo, config)
97+
98+
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
99+
100+
assert.False(t, issueConfig.BlankIssuesEnabled)
101+
assert.Len(t, issueConfig.ContactLinks, 1)
102+
103+
assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name)
104+
assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL)
105+
assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About)
106+
})
35107
}
36108

37-
func TestAPIReposValidateDefaultIssueConfig(t *testing.T) {
109+
func TestAPIRepoIssueConfigPaths(t *testing.T) {
38110
defer tests.PrepareTestEnv(t)()
39111

40-
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
112+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
113+
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
114+
115+
templateConfigCandidates := []string{
116+
".gitea/ISSUE_TEMPLATE/config",
117+
".gitea/issue_template/config",
118+
".github/ISSUE_TEMPLATE/config",
119+
".github/issue_template/config",
120+
}
121+
122+
for _, canidate := range templateConfigCandidates {
123+
for _, extension := range []string{".yaml", ".yml"} {
124+
fullPath := canidate + extension
125+
t.Run(fullPath, func(t *testing.T) {
126+
configMap := make(map[string]any)
127+
configMap["blank_issues_enabled"] = false
128+
129+
configData, err := yaml.Marshal(configMap)
130+
assert.NoError(t, err)
131+
132+
_, err = createFileInBranch(owner, repo, fullPath, repo.DefaultBranch, string(configData))
133+
assert.NoError(t, err)
134+
135+
issueConfig := getIssueConfig(t, owner.Name, repo.Name)
136+
137+
assert.False(t, issueConfig.BlankIssuesEnabled)
138+
assert.Len(t, issueConfig.ContactLinks, 0)
139+
140+
_, err = deleteFileInBranch(owner, repo, fullPath, repo.DefaultBranch)
141+
assert.NoError(t, err)
142+
})
143+
}
144+
}
145+
}
146+
147+
func TestAPIRepoValidateIssueConfig(t *testing.T) {
148+
defer tests.PrepareTestEnv(t)()
149+
150+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49})
41151
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
42152

43153
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config/validate", owner.Name, repo.Name)
44-
req := NewRequest(t, "GET", urlStr)
45-
resp := MakeRequest(t, req, http.StatusOK)
46154

47-
var issueConfigValidation api.IssueConfigValidation
48-
DecodeJSON(t, resp, &issueConfigValidation)
155+
t.Run("Valid", func(t *testing.T) {
156+
req := NewRequest(t, "GET", urlStr)
157+
resp := MakeRequest(t, req, http.StatusOK)
158+
159+
var issueConfigValidation api.IssueConfigValidation
160+
DecodeJSON(t, resp, &issueConfigValidation)
161+
162+
assert.True(t, issueConfigValidation.Valid)
163+
assert.Empty(t, issueConfigValidation.Message)
164+
})
165+
166+
t.Run("Invalid", func(t *testing.T) {
167+
config := make(map[string]any)
168+
config["blank_issues_enabled"] = "Test"
169+
170+
createIssueConfig(t, owner, repo, config)
171+
172+
req := NewRequest(t, "GET", urlStr)
173+
resp := MakeRequest(t, req, http.StatusOK)
174+
175+
var issueConfigValidation api.IssueConfigValidation
176+
DecodeJSON(t, resp, &issueConfigValidation)
49177

50-
assert.True(t, issueConfigValidation.Valid)
51-
assert.Empty(t, issueConfigValidation.Message)
178+
assert.False(t, issueConfigValidation.Valid)
179+
assert.NotEmpty(t, issueConfigValidation.Message)
180+
})
52181
}

tests/integration/api_repo_file_helpers.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package integration
66
import (
77
"strings"
88

9+
"code.gitea.io/gitea/models"
910
repo_model "code.gitea.io/gitea/models/repo"
1011
user_model "code.gitea.io/gitea/models/user"
1112
"code.gitea.io/gitea/modules/git"
@@ -29,6 +30,32 @@ func createFileInBranch(user *user_model.User, repo *repo_model.Repository, tree
2930
return files_service.ChangeRepoFiles(git.DefaultContext, repo, user, opts)
3031
}
3132

33+
func deleteFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName string) (*api.FilesResponse, error) {
34+
opts := &files_service.ChangeRepoFilesOptions{
35+
Files: []*files_service.ChangeRepoFile{
36+
{
37+
Operation: "delete",
38+
TreePath: treePath,
39+
},
40+
},
41+
OldBranch: branchName,
42+
Author: nil,
43+
Committer: nil,
44+
}
45+
return files_service.ChangeRepoFiles(git.DefaultContext, repo, user, opts)
46+
}
47+
48+
func createOrReplaceFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) error {
49+
_, err := deleteFileInBranch(user, repo, treePath, branchName)
50+
51+
if err != nil && !models.IsErrRepoFileDoesNotExist(err) {
52+
return err
53+
}
54+
55+
_, err = createFileInBranch(user, repo, treePath, branchName, content)
56+
return err
57+
}
58+
3259
func createFile(user *user_model.User, repo *repo_model.Repository, treePath string) (*api.FilesResponse, error) {
3360
return createFileInBranch(user, repo, treePath, repo.DefaultBranch, "This is a NEW file")
3461
}

0 commit comments

Comments
 (0)