fix(api): adding issue labels by name attaches both the repo and the org label (#39873)

Fixes #39651

When an org-owned repo has a repo label and an org label with the same
name, `POST`/`PUT /repos/{owner}/{repo}/issues/{index}/labels` with
label names attached both of them.

---------

Signed-off-by: Nazem <214302554+nazem-droubi@users.noreply.github.com>
Co-authored-by: Nazem <214302554+nazem-droubi@users.noreply.github.com>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
authored and GitHub committed 2026-10-22 20:54:33 +00:00
1 parent 269b116b1b
commit 7448b49aac
5 files changed
+53 -5

No files matched your search

+34
View File
@@ -175,6 +175,40 @@ func TestAPIAddIssueLabelsWithLabelNames(t *testing.T) {
MakeRequest(t, req, http.StatusNoContent)
}
func TestAPIAddIssueLabelsWithSharedRepoAndOrgLabelName(t *testing.T) {
assert.NoError(t, unittest.LoadFixtures())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 6, RepoID: repo.ID})
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
repoLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 10, RepoID: repo.ID})
orgOnlyLabel := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4, OrgID: owner.ID})
assert.NoError(t, issues_model.NewLabel(t.Context(), &issues_model.Label{OrgID: owner.ID, Name: repoLabel.Name, Color: "#abcdef"}))
token := getTokenForLoggedInUser(t, loginUser(t, "user1"), auth_model.AccessTokenScopeWriteIssue)
urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issues/%d/labels", owner.Name, repo.Name, issue.Index)
for _, method := range []string{"POST", "PUT"} {
t.Run(method, func(t *testing.T) {
req := NewRequest(t, "DELETE", urlStr).AddTokenAuth(token)
MakeRequest(t, req, http.StatusNoContent)
req = NewRequestWithJSON(t, method, urlStr, &api.IssueLabelsOption{
Labels: []any{repoLabel.Name, orgOnlyLabel.Name},
}).AddTokenAuth(token)
resp := MakeRequest(t, req, http.StatusOK)
apiLabels := DecodeJSON(t, resp, []*api.Label{})
var apiLabelIDs []int64
for _, label := range apiLabels {
apiLabelIDs = append(apiLabelIDs, label.ID)
}
assert.ElementsMatch(t, []int64{repoLabel.ID, orgOnlyLabel.ID}, apiLabelIDs)
})
}
}
func TestAPIReplaceIssueLabels(t *testing.T) {
assert.NoError(t, unittest.LoadFixtures())