Skip to content

Commit eed0968

Browse files
GiteaBotZettat123
andauthored
Support org labels when adding labels by label names (#32988) (#32996)
Backport #32988 by @Zettat123 Fix #32891 Co-authored-by: Zettat123 <[email protected]>
1 parent a0b65ed commit eed0968

File tree

4 files changed

+50
-10
lines changed

4 files changed

+50
-10
lines changed

models/fixtures/label.yml

+11
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,14 @@
9696
num_issues: 0
9797
num_closed_issues: 0
9898
archived_unix: 0
99+
100+
-
101+
id: 10
102+
repo_id: 3
103+
org_id: 0
104+
name: repo3label1
105+
color: '#112233'
106+
exclusive: false
107+
num_issues: 0
108+
num_closed_issues: 0
109+
archived_unix: 0

models/issues/label.go

+11
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,17 @@ func GetLabelIDsInRepoByNames(ctx context.Context, repoID int64, labelNames []st
349349
Find(&labelIDs)
350350
}
351351

352+
// GetLabelIDsInOrgByNames returns a list of labelIDs by names in a given org.
353+
func GetLabelIDsInOrgByNames(ctx context.Context, orgID int64, labelNames []string) ([]int64, error) {
354+
labelIDs := make([]int64, 0, len(labelNames))
355+
return labelIDs, db.GetEngine(ctx).Table("label").
356+
Where("org_id = ?", orgID).
357+
In("name", labelNames).
358+
Asc("name").
359+
Cols("id").
360+
Find(&labelIDs)
361+
}
362+
352363
// BuildLabelNamesIssueIDsCondition returns a builder where get issue ids match label names
353364
func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
354365
return builder.Select("issue_label.issue_id").

routers/api/v1/repo/issue_label.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -335,18 +335,30 @@ func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption)
335335
labelIDs = append(labelIDs, int64(rv.Float()))
336336
case reflect.String:
337337
labelNames = append(labelNames, rv.String())
338+
default:
339+
ctx.Error(http.StatusBadRequest, "InvalidLabel", "a label must be an integer or a string")
340+
return nil, nil, fmt.Errorf("invalid label")
338341
}
339342
}
340343
if len(labelIDs) > 0 && len(labelNames) > 0 {
341344
ctx.Error(http.StatusBadRequest, "InvalidLabels", "labels should be an array of strings or integers")
342345
return nil, nil, fmt.Errorf("invalid labels")
343346
}
344347
if len(labelNames) > 0 {
345-
labelIDs, err = issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, labelNames)
348+
repoLabelIDs, err := issues_model.GetLabelIDsInRepoByNames(ctx, ctx.Repo.Repository.ID, labelNames)
346349
if err != nil {
347350
ctx.Error(http.StatusInternalServerError, "GetLabelIDsInRepoByNames", err)
348351
return nil, nil, err
349352
}
353+
labelIDs = append(labelIDs, repoLabelIDs...)
354+
if ctx.Repo.Owner.IsOrganization() {
355+
orgLabelIDs, err := issues_model.GetLabelIDsInOrgByNames(ctx, ctx.Repo.Owner.ID, labelNames)
356+
if err != nil {
357+
ctx.Error(http.StatusInternalServerError, "GetLabelIDsInOrgByNames", err)
358+
return nil, nil, err
359+
}
360+
labelIDs = append(labelIDs, orgLabelIDs...)
361+
}
350362
}
351363

352364
labels, err := issues_model.GetLabelsByIDs(ctx, labelIDs, "id", "repo_id", "org_id", "name", "exclusive")

tests/integration/api_issue_label_test.go

+15-9
Original file line numberDiff line numberDiff line change
@@ -117,27 +117,33 @@ func TestAPIAddIssueLabels(t *testing.T) {
117117
func TestAPIAddIssueLabelsWithLabelNames(t *testing.T) {
118118
assert.NoError(t, unittest.LoadFixtures())
119119

120-
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
121-
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{RepoID: repo.ID})
120+
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
121+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 6, RepoID: repo.ID})
122122
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
123+
repoLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 10, RepoID: repo.ID})
124+
orgLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4, OrgID: owner.ID})
123125

124-
session := loginUser(t, owner.Name)
125-
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteIssue)
126-
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels",
127-
repo.OwnerName, repo.Name, issue.Index)
126+
user1Session := loginUser(t, "user1")
127+
token := getTokenForLoggedInUser(t, user1Session, auth_model.AccessTokenScopeWriteIssue)
128+
129+
// add the org label and the repo label to the issue
130+
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels", owner.Name, repo.Name, issue.Index)
128131
req := NewRequestWithJSON(t, "POST", urlStr, &api.IssueLabelsOption{
129-
Labels: []any{"label1", "label2"},
132+
Labels: []any{repoLabel.Name, orgLabel.Name},
130133
}).AddTokenAuth(token)
131134
resp := MakeRequest(t, req, http.StatusOK)
132135
var apiLabels []*api.Label
133136
DecodeJSON(t, resp, &apiLabels)
134137
assert.Len(t, apiLabels, unittest.GetCount(t, &issues_model.IssueLabel{IssueID: issue.ID}))
135-
136138
var apiLabelNames []string
137139
for _, label := range apiLabels {
138140
apiLabelNames = append(apiLabelNames, label.Name)
139141
}
140-
assert.ElementsMatch(t, apiLabelNames, []string{"label1", "label2"})
142+
assert.ElementsMatch(t, apiLabelNames, []string{repoLabel.Name, orgLabel.Name})
143+
144+
// delete labels
145+
req = NewRequest(t, "DELETE", urlStr).AddTokenAuth(token)
146+
MakeRequest(t, req, http.StatusNoContent)
141147
}
142148

143149
func TestAPIReplaceIssueLabels(t *testing.T) {

0 commit comments

Comments
 (0)