Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Organization Wide Labels #10814

Merged
merged 53 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
6548c80
Add organization wide labels
mrsdizzie Mar 24, 2020
b7dc22c
Add migration
mrsdizzie Mar 24, 2020
350569a
remove comments
mrsdizzie Mar 24, 2020
c562eef
fix tests
mrsdizzie Mar 24, 2020
140d87d
Update options/locale/locale_en-US.ini
mrsdizzie Mar 25, 2020
00729a2
show org labels in issue search label filter
mrsdizzie Mar 25, 2020
8af0f6c
Use more clear var name
mrsdizzie Mar 27, 2020
1ac0851
Merge branch 'master' into organization-labels
mrsdizzie Mar 27, 2020
101d4e7
rename migration after merge from master
mrsdizzie Mar 27, 2020
33ca43e
comment typo
mrsdizzie Mar 27, 2020
adf4235
Merge branch 'master' into organization-labels
lafriks Mar 27, 2020
76ae932
Merge branch 'master' into organization-labels
mrsdizzie Mar 27, 2020
13fadae
update migration again after rebase with master
mrsdizzie Mar 27, 2020
a82a29b
check for orgID <=0 per guillep2k review
mrsdizzie Mar 27, 2020
27209ee
fmt
mrsdizzie Mar 27, 2020
eae4724
Apply suggestions from code review
mrsdizzie Mar 27, 2020
a68f6f8
remove unused code
mrsdizzie Mar 27, 2020
3a0b210
Make sure RepoID is 0 when searching orgID per code review
mrsdizzie Mar 27, 2020
f4afe50
more changes/code review requests
mrsdizzie Mar 28, 2020
835ee95
More descriptive translation var per code review
mrsdizzie Mar 28, 2020
503998b
func description/delete comment when issue label deleted instead of h…
mrsdizzie Mar 28, 2020
007ff15
remove comment
mrsdizzie Mar 28, 2020
88c37d1
Merge branch 'master' into organization-labels
mrsdizzie Mar 28, 2020
e4714fe
only use issues in that repo when calculating number of open issues f…
mrsdizzie Mar 29, 2020
70529e2
Add integration test for IssuesSearch API with labels
mrsdizzie Mar 29, 2020
967335e
Merge branch 'master' into organization-labels
mrsdizzie Mar 29, 2020
2604c39
remove unused function
mrsdizzie Mar 29, 2020
72b4c5c
Update models/issue_label.go
mrsdizzie Mar 29, 2020
8c1f393
Use subquery in GetLabelIDsInReposByNames
mrsdizzie Mar 29, 2020
a8517ab
Fix tests to use correct orgID
mrsdizzie Mar 29, 2020
5688933
Merge branch 'master' into organization-labels
mrsdizzie Mar 29, 2020
e5809c4
fix more tests
mrsdizzie Mar 29, 2020
2ecf5d1
Merge branch 'master' into organization-labels
mrsdizzie Mar 29, 2020
1b94717
Merge branch 'master' into organization-labels
mrsdizzie Mar 30, 2020
a01f7a9
IssuesSearch api now uses new BuildLabelNamesIssueIDsCondition. Add a…
mrsdizzie Mar 30, 2020
47d1b8e
update comment for clarity
mrsdizzie Mar 30, 2020
d17c8c2
Revert previous code change now that we can use the new BuildLabelNam…
mrsdizzie Mar 30, 2020
59f0586
Don't sort repos by date in IssuesSearch API
mrsdizzie Mar 30, 2020
8887170
Merge branch 'master' into organization-labels
mrsdizzie Mar 30, 2020
a5bb033
linter is back!
mrsdizzie Mar 30, 2020
e4ed7ec
code review
mrsdizzie Mar 31, 2020
893650b
remove now unused option
mrsdizzie Mar 31, 2020
7e40622
Fix newline at end of files
mrsdizzie Mar 31, 2020
235d420
more unused code
mrsdizzie Mar 31, 2020
fbee66a
Merge branch 'master' into organization-labels
mrsdizzie Mar 31, 2020
731dd89
Merge branch 'master' into organization-labels
mrsdizzie Mar 31, 2020
0013cd3
update to master
mrsdizzie Mar 31, 2020
f74a1b8
check for matching ids before query
mrsdizzie Mar 31, 2020
551f3b5
Update models/issue_label.go
mrsdizzie Mar 31, 2020
d39f303
Update models/issue_label.go
mrsdizzie Mar 31, 2020
0bddcf7
update comments
mrsdizzie Mar 31, 2020
69cf00e
Update routers/org/setting.go
mrsdizzie Mar 31, 2020
aae5286
Merge branch 'master' into organization-labels
mrsdizzie Apr 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions integrations/api_issue_label_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,74 @@ func TestAPIReplaceIssueLabels(t *testing.T) {
models.AssertCount(t, &models.IssueLabel{IssueID: issue.ID}, 1)
models.AssertExistsAndLoadBean(t, &models.IssueLabel{IssueID: issue.ID, LabelID: label.ID})
}

func TestAPIModifyOrgLabels(t *testing.T) {
assert.NoError(t, models.LoadFixtures())

repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 3}).(*models.Repository)
owner := models.AssertExistsAndLoadBean(t, &models.User{ID: repo.OwnerID}).(*models.User)
user := "user1"
session := loginUser(t, user)
token := getTokenForLoggedInUser(t, session)
urlStr := fmt.Sprintf("/api/v1/orgs/%s/labels?token=%s", owner.Name, token)

// CreateLabel
req := NewRequestWithJSON(t, "POST", urlStr, &api.CreateLabelOption{
Name: "TestL 1",
Color: "abcdef",
Description: "test label",
})
resp := session.MakeRequest(t, req, http.StatusCreated)
apiLabel := new(api.Label)
DecodeJSON(t, resp, &apiLabel)
dbLabel := models.AssertExistsAndLoadBean(t, &models.Label{ID: apiLabel.ID, OrgID: owner.ID}).(*models.Label)
assert.EqualValues(t, dbLabel.Name, apiLabel.Name)
assert.EqualValues(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)

req = NewRequestWithJSON(t, "POST", urlStr, &api.CreateLabelOption{
Name: "TestL 2",
Color: "#123456",
Description: "jet another test label",
})
session.MakeRequest(t, req, http.StatusCreated)
req = NewRequestWithJSON(t, "POST", urlStr, &api.CreateLabelOption{
Name: "WrongTestL",
Color: "#12345g",
})
session.MakeRequest(t, req, http.StatusUnprocessableEntity)

//ListLabels
req = NewRequest(t, "GET", urlStr)
resp = session.MakeRequest(t, req, http.StatusOK)
var apiLabels []*api.Label
DecodeJSON(t, resp, &apiLabels)
assert.Len(t, apiLabels, 4)

//GetLabel
singleURLStr := fmt.Sprintf("/api/v1/orgs/%s/labels/%d?token=%s", owner.Name, dbLabel.ID, token)
req = NewRequest(t, "GET", singleURLStr)
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiLabel)
assert.EqualValues(t, strings.TrimLeft(dbLabel.Color, "#"), apiLabel.Color)

//EditLabel
newName := "LabelNewName"
newColor := "09876a"
newColorWrong := "09g76a"
req = NewRequestWithJSON(t, "PATCH", singleURLStr, &api.EditLabelOption{
Name: &newName,
Color: &newColor,
})
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiLabel)
assert.EqualValues(t, newColor, apiLabel.Color)
req = NewRequestWithJSON(t, "PATCH", singleURLStr, &api.EditLabelOption{
Color: &newColorWrong,
})
session.MakeRequest(t, req, http.StatusUnprocessableEntity)

//DeleteLabel
req = NewRequest(t, "DELETE", singleURLStr)
resp = session.MakeRequest(t, req, http.StatusNoContent)

}
65 changes: 64 additions & 1 deletion integrations/api_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestAPIEditIssue(t *testing.T) {
assert.Equal(t, title, issueAfter.Title)
}

func TestAPISearchIssue(t *testing.T) {
func TestAPISearchIssues(t *testing.T) {
defer prepareTestEnv(t)()

session := loginUser(t, "user2")
Expand Down Expand Up @@ -173,3 +173,66 @@ func TestAPISearchIssue(t *testing.T) {
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 1)
}

func TestAPISearchIssuesWithLabels(t *testing.T) {
defer prepareTestEnv(t)()

session := loginUser(t, "user1")
token := getTokenForLoggedInUser(t, session)

link, _ := url.Parse("/api/v1/repos/issues/search")
req := NewRequest(t, "GET", link.String())
resp := session.MakeRequest(t, req, http.StatusOK)
var apiIssues []*api.Issue
DecodeJSON(t, resp, &apiIssues)

assert.Len(t, apiIssues, 9)

query := url.Values{}
query.Add("token", token)
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 9)

query.Add("labels", "label1")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 2)

// multiple labels
query.Set("labels", "label1,label2")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 2)

// an org label
query.Set("labels", "orglabel4")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 1)

// org and repo label
query.Set("labels", "label2,orglabel4")
query.Add("state", "all")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 2)

// org and repo label which share the same issue
query.Set("labels", "label1,orglabel4")
link.RawQuery = query.Encode()
req = NewRequest(t, "GET", link.String())
resp = session.MakeRequest(t, req, http.StatusOK)
DecodeJSON(t, resp, &apiIssues)
assert.Len(t, apiIssues, 2)
}
35 changes: 33 additions & 2 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -1502,10 +1502,41 @@ func (err ErrTrackedTimeNotExist) Error() string {
// |_______ (____ /___ /\___ >____/
// \/ \/ \/ \/

// ErrRepoLabelNotExist represents a "RepoLabelNotExist" kind of error.
type ErrRepoLabelNotExist struct {
LabelID int64
RepoID int64
}

// IsErrRepoLabelNotExist checks if an error is a RepoErrLabelNotExist.
func IsErrRepoLabelNotExist(err error) bool {
_, ok := err.(ErrRepoLabelNotExist)
return ok
}

func (err ErrRepoLabelNotExist) Error() string {
return fmt.Sprintf("label does not exist [label_id: %d, repo_id: %d]", err.LabelID, err.RepoID)
}

// ErrOrgLabelNotExist represents a "OrgLabelNotExist" kind of error.
type ErrOrgLabelNotExist struct {
LabelID int64
OrgID int64
}

// IsErrOrgLabelNotExist checks if an error is a OrgErrLabelNotExist.
func IsErrOrgLabelNotExist(err error) bool {
_, ok := err.(ErrOrgLabelNotExist)
return ok
}

func (err ErrOrgLabelNotExist) Error() string {
return fmt.Sprintf("label does not exist [label_id: %d, org_id: %d]", err.LabelID, err.OrgID)
}

// ErrLabelNotExist represents a "LabelNotExist" kind of error.
type ErrLabelNotExist struct {
LabelID int64
RepoID int64
}

// IsErrLabelNotExist checks if an error is a ErrLabelNotExist.
Expand All @@ -1515,7 +1546,7 @@ func IsErrLabelNotExist(err error) bool {
}

func (err ErrLabelNotExist) Error() string {
return fmt.Sprintf("label does not exist [label_id: %d, repo_id: %d]", err.LabelID, err.RepoID)
return fmt.Sprintf("label does not exist [label_id: %d]", err.LabelID)
}

// _____ .__.__ __
Expand Down
5 changes: 5 additions & 0 deletions models/fixtures/issue_label.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
id: 3
issue_id: 2
label_id: 1

-
id: 4
issue_id: 2
label_id: 4
19 changes: 19 additions & 0 deletions models/fixtures/label.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-
id: 1
repo_id: 1
org_id: 0
name: label1
color: '#abcdef'
num_issues: 2
Expand All @@ -9,7 +10,25 @@
-
id: 2
repo_id: 1
org_id: 0
name: label2
color: '#000000'
num_issues: 1
num_closed_issues: 1
-
id: 3
repo_id: 0
org_id: 3
name: orglabel3
color: '#abcdef'
num_issues: 0
num_closed_issues: 0

-
id: 4
repo_id: 0
org_id: 3
name: orglabel4
color: '#000000'
num_issues: 1
num_closed_issues: 0
mrsdizzie marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 4 additions & 2 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ func (issue *Issue) ClearLabels(doer *User) (err error) {
return err
}
if !perm.CanWriteIssuesOrPulls(issue.IsPull) {
return ErrLabelNotExist{}
return ErrRepoLabelNotExist{}
}

if err = issue.clearLabels(sess, doer); err != nil {
Expand Down Expand Up @@ -894,7 +894,7 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {

for _, label := range labels {
// Silently drop invalid labels.
if label.RepoID != opts.Repo.ID {
if label.RepoID != opts.Repo.ID && label.OrgID != opts.Repo.OwnerID {
continue
}

Expand Down Expand Up @@ -1059,6 +1059,8 @@ type IssuesOptions struct {
IssueIDs []int64
// prioritize issues from this repo
PriorityRepoID int64
//Search for issues that contain any of the label ids above rather than all
HasAnyLabel bool
}

// sortIssuesSession sort an issues-related session based on the provided
Expand Down
Loading