-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Add automated project board #27835
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 automated project board #27835
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1143,6 +1143,83 @@ LEVEL = Info | |||||
;PROJECT_BOARD_BASIC_KANBAN_TYPE = To Do, In Progress, Done | ||||||
;PROJECT_BOARD_BUG_TRIAGE_TYPE = Needs Triage, High Priority, Low Priority, Closed | ||||||
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;[project.automation] | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;ENABLED = false | ||||||
;MAX_RULES_PER_PROJECT = 25 | ||||||
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;[project.automation.kanban] | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;; | ||||||
;; Default rules when creating an automated Kanban project. | ||||||
;; Each rule can specify a list of key/value pairs: | ||||||
;; - trigger (required) see commands below | ||||||
;; - action (required) see commands below | ||||||
;; - target (optional) the rule is only active for these issue types | ||||||
;; one of: issue, pr, default | ||||||
;; can be comma-separated list (e.g. issue,pr) | ||||||
;; the 'default' depends on the action, but most often | ||||||
;; it is the same as issue,pr (notable exceptions are | ||||||
;; commands 'xref', 'approve' and 'assign_reviewer') | ||||||
;; (default value is target=default) | ||||||
;; - context (optional) the rule is only active in this context | ||||||
;; one of: column:{column}, project | ||||||
;; where {column} is a column title | ||||||
;; (default value is context=project) | ||||||
;; | ||||||
;; Commands can have arguments using the command:argument syntax. | ||||||
;; They are available both as a trigger and as an action. | ||||||
;; Available commands: | ||||||
;; - move:{column} where {column} is a column title | ||||||
;; - status:{status} where {status} is one of: closed, reopened | ||||||
;; - assign_project assigns the current project to the issue/pr | ||||||
;; - assign_reviewer adds the current user as a requested reviewer | ||||||
;; - assign assigns the current user to the issue/pr | ||||||
;; when used as a trigger, it triggers when issue/pr is no longer unassigned | ||||||
;; - unassign unassign the current user from the issue/pr | ||||||
;; when used as a trigger, it triggers when issue/pr becomes unassigned | ||||||
;; - approve approves a pull request (default target=pr) | ||||||
;; - unapprove unapproves a pull request (default target=pr) | ||||||
;; - xref:{action} a cross-reference is made between issue and pull request | ||||||
;; where {action} is one of: none, closes, reopens, neutered | ||||||
;; When xref is used as a trigger, target=pr can target a | ||||||
;; pull request which will close an issue in the current project, | ||||||
;; even if that pull request is not currently assigned to the project. | ||||||
;; (default target=issue) | ||||||
Comment on lines
+1189
to
+1194
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm… This does not sound like a good idea. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Side note: I thought the x was for "cross", as in cross-reference. A PR can do a cross-reference which closes an issue when the PR is merged ( I figured that triggering an automation whenever a PR is opened which closes an issue in the project could be a useful thing to have. In the default configuration I added some rules for:
I guess we could rename this command to something else, and also not consider the other XRefActions which are internally supported if it simplifies things. Or remove it completely and make the available commands a bit more slim as a start. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would renaming this to |
||||||
;; - label:{label} adds a label to the issue/pr, where {label} is a label accessible in the current project | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
;; - unlabel:{label} remove label from the issue/pr | ||||||
;RULE1 = trigger=status:closed, action=move:Done | ||||||
;RULE2 = trigger=status:reopened, action=move:To Do | ||||||
;RULE3 = trigger=approve, action=move:Done, target=pr, context=column:In Progress | ||||||
;RULE4 = trigger=xref:closes, action=assign_project, target=pr | ||||||
;RULE5 = trigger=assign_project, action=move:To Do, target=pr | ||||||
;RULE6 = trigger=move:To Do, action=unassign | ||||||
;RULE7 = trigger=move:To Do, action=status:reopened | ||||||
;RULE8 = trigger=move:To Do, action=clear_reviewers | ||||||
;RULE9 = trigger=move:In Progress, action=assign | ||||||
;RULE10 = trigger=move:In Progress, action=status:reopened | ||||||
;RULE11 = trigger=move:In Progress, action=assign_reviewer | ||||||
;RULE12 = trigger=move:Done, action=status:closed, target=issue | ||||||
;RULE13 = trigger=move:Done, action=approve, target=pr | ||||||
;RULE14 = trigger=assign, action=move:In Progress, target=issue, context=column:To Do | ||||||
;RULE15 = trigger=assign_reviewer, action=move:In Progress, target=pr, context=column:To Do | ||||||
;RULE16 = trigger=xref:closes, action=label:Status/Blocked, target=issue, context=column:In Progress | ||||||
;RULE17 = trigger=approve, action=unlabel:Status/Blocked, target=issue, context=column:In Progress | ||||||
;RULE18 = | ||||||
;RULE19 = | ||||||
;RULE20 = | ||||||
;RULE21 = | ||||||
;RULE22 = | ||||||
;RULE23 = | ||||||
;RULE24 = | ||||||
;RULE25 = | ||||||
Comment on lines
+1214
to
+1221
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I think I've already mentioned, do not create a static amount of rules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might have mentioned it, albeit encoded into a single I guess we could do that, but could not see that we did a similar thing elsewhere (iterating over dynamic keys in the config). Thus I decided to kick it off with the "stupidly simple" approach first. |
||||||
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||||||
;[cors] | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -815,6 +815,11 @@ Default templates for project boards: | |
- `PROJECT_BOARD_BASIC_KANBAN_TYPE`: **To Do, In Progress, Done** | ||
- `PROJECT_BOARD_BUG_TRIAGE_TYPE`: **Needs Triage, High Priority, Low Priority, Closed** | ||
|
||
## Project Automation (`project.automation`) | ||
|
||
- `ENABLED`: **false**: Whether automation is enabled for projects. | ||
- `MAX_RULE_PER_PROJECT`: **25**: Maximum number of automation rules per project. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we even need such a setting? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Especially as you then wouldn't need to hardcode the number of rules. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The intent of this setting was to limit the maximum amount of rules considered at runtime, but I understand that this causes confusion at this stage. I agree that this can be removed for the time being, as it can probably be reintroduced at a later time when automation rules can be added via the project settings in the GUI. |
||
|
||
## Issue and pull request attachments (`attachment`) | ||
|
||
- `ENABLED`: **true**: Whether issue and pull request attachments are enabled. | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -47,6 +47,17 @@ func (issue *Issue) ProjectBoardID(ctx context.Context) int64 { | |||||||||||||||||||||||
return ip.ProjectBoardID | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
func (issue *Issue) IsOnProjectBoard(ctx context.Context, board *project_model.Board) bool { | ||||||||||||||||||||||||
var ip project_model.ProjectIssue | ||||||||||||||||||||||||
has, err := db.GetEngine(ctx).Table(project_model.ProjectIssue{}). | ||||||||||||||||||||||||
Where("issue_id=? AND project_board_id=?", issue.ID, board.ID). | ||||||||||||||||||||||||
Get(&ip) | ||||||||||||||||||||||||
if err != nil || !has { | ||||||||||||||||||||||||
return false | ||||||||||||||||||||||||
} | ||||||||||||||||||||||||
return true | ||||||||||||||||||||||||
Comment on lines
+50
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||
} | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
// LoadIssuesFromBoard load issues assigned to this board | ||||||||||||||||||||||||
func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) { | ||||||||||||||||||||||||
issueList := make(IssueList, 0, 10) | ||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright 2023 The Gitea Authors. All rights reserved. | ||
// SPDX-License-Identifier: MIT | ||
|
||
package v1_22 //nolint | ||
|
||
import ( | ||
"code.gitea.io/gitea/modules/timeutil" | ||
|
||
"xorm.io/xorm" | ||
) | ||
|
||
func AddProjectAutomationTable(x *xorm.Engine) error { | ||
type ( | ||
AutomationTriggerType uint8 | ||
AutomationActionType uint8 | ||
AutomationActionTargetType uint8 | ||
) | ||
|
||
type ProjectAutomation struct { | ||
ID int64 `xorm:"pk autoincr"` | ||
Enabled bool `xorm:"INDEX NOT NULL DEFAULT true"` | ||
ProjectID int64 `xorm:"INDEX NOT NULL"` | ||
ProjectBoardID int64 `xorm:"INDEX NOT NULL"` | ||
TriggerType AutomationTriggerType `xorm:"INDEX NOT NULL"` | ||
TriggerData int64 `xorm:"INDEX NOT NULL DEFAULT 0"` | ||
ActionType AutomationActionType `xorm:"NOT NULL DEFAULT 0"` | ||
ActionData int64 `xorm:"NOT NULL DEFAULT 0"` | ||
ActionTarget AutomationActionTargetType `xorm:"NOT NULL DEFAULT 0"` | ||
Sorting int64 `xorm:"NOT NULL DEFAULT 0"` | ||
|
||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | ||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | ||
} | ||
|
||
return x.Sync(new(ProjectAutomation)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, we need something else before that:
board titles
are not unique (per project) at the moment, so we need the UNIQUE INDEX for it first.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, having board titles here were a necessary evil I guess. I initially only supported board IDs, but then I added support for titles when I figured that we need some way to configure this before being able to add automation rules via the web interface.
Then, in the end I basically only kept support for titles as to simplify the configuration interface.
While there is no guarantee of unique board titles, I still think being able to address it a board by title in the configuration is a useful thing to do. (and I don't necessarily think that having duplicate board titles within one project is a likely use-case)
Not quite sure how to proceed with this particular issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should perhaps clarify that the board/column titles are only used at project creation time and are inherently tied to the column labels in the
PROJECT_BOARD_BASIC_KANBAN_TYPE
template. At project creation time, after the boards/columns have been created and have real IDs, the labels here are only used to lookup the IDs which are then stored in the database. Renaming the columns after creation does not "break" the rules. The same goes for labels, which also must exist at project creation time.While I see the value of not letting the user "shoot themselves in the foot" by supplying duplicate titles in the default configuration, I kind of see that as a separate issue that could be fixed separately instead of growing this PR even further.