| 100 | == Example: Adding optional Testing with Workflow == |
| 101 | |
| 102 | By adding the following to your [ticket-workflow] section of trac.ini you get optional testing. When the ticket is in new, accepted or needs_work status you can choose to submit it for testing. When it's in the testing status the user gets the option to reject it and send it back to needs_work, or pass the testing and send it along to closed. If they accept it then it gets automatically marked as closed and the resolution is set to fixed. Since all the old work flow remains, a ticket can skip this entire section. |
| 103 | |
| 104 | {{{ |
| 105 | testing = new,accepted,needs_work,assigned,reopened -> testing |
| 106 | testing.name = Submit to reporter for testing |
| 107 | testing.permissions = TICKET_MODIFY |
| 108 | |
| 109 | reject = testing -> needs_work |
| 110 | reject.name = Failed testing, return to developer |
| 111 | |
| 112 | pass = testing -> closed |
| 113 | pass.name = Passes Testing |
| 114 | pass.operations = set_resolution |
| 115 | pass.set_resolution = fixed |
| 116 | }}} |
| 117 | |
| 118 | === How to combine the `tracopt.ticket.commit_updater` with the testing workflow === |
| 119 | |
| 120 | The [[source:trunk/tracopt/ticket/commit_updater.py|tracopt.ticket.commit_updater]] is the optional component that [[TracRepositoryAdmin#trac-post-commit-hook|replaces the old trac-post-commit-hook]], in Trac 0.12. |
| 121 | |
| 122 | By default it reacts on some keywords found in changeset message logs like ''close'', ''fix'' etc. and performs the corresponding workflow action. |
| 123 | |
| 124 | If you have a more complex workflow, like the testing stage described above and you want the ''closes'' keyword to move the ticket to the ''testing'' status instead of the ''closed'' status, you need to adapt the code a bit. |
| 125 | |
| 126 | Have a look at the [[0.11/TracWorkflow#How-ToCombineSVNtrac-post-commit-hookWithTestWorkflow|Trac 0.11 recipe]] for the `trac-post-commit-hook`, this will give you some ideas about how to modify the component. |
| 127 | |
| 128 | == Example: Add simple optional generic review state == |
| 129 | |
| 130 | Sometimes Trac is used in situations where "testing" can mean different things to different people so you may want to create an optional workflow state that is between the default workflow's `assigned` and `closed` states, but does not impose implementation-specific details. The only new state you need to add for this is a `reviewing` state. A ticket may then be "submitted for review" from any state that it can be reassigned. If a review passes, you can re-use the `resolve` action to close the ticket, and if it fails you can re-use the `reassign` action to push it back into the normal workflow. |
| 131 | |
| 132 | The new `reviewing` state along with its associated `review` action looks like this: |
| 133 | |
| 134 | {{{ |
| 135 | review = new,assigned,reopened -> reviewing |
| 136 | review.operations = set_owner |
| 137 | review.permissions = TICKET_MODIFY |
| 138 | }}} |
| 139 | |
| 140 | Then, to integrate this with the default Trac 0.11 workflow, you also need to add the `reviewing` state to the `accept` and `resolve` actions, like so: |
| 141 | |
| 142 | {{{ |
| 143 | accept = new,reviewing -> assigned |
| 144 | […] |
| 145 | resolve = new,assigned,reopened,reviewing -> closed |
| 146 | }}} |
| 147 | |
| 148 | Optionally, you can also add a new action that allows you to change the ticket's owner without moving the ticket out of the `reviewing` state. This enables you to reassign review work without pushing the ticket back to the `new` status. |
| 149 | |
| 150 | {{{ |
| 151 | reassign_reviewing = reviewing -> * |
| 152 | reassign_reviewing.name = reassign review |
| 153 | reassign_reviewing.operations = set_owner |
| 154 | reassign_reviewing.permissions = TICKET_MODIFY |
| 155 | }}} |
| 156 | |
| 157 | The full `[ticket-workflow]` configuration will thus look like this: |
| 158 | |
| 159 | {{{ |
| 160 | [ticket-workflow] |
| 161 | accept = new,reviewing -> assigned |
| 162 | accept.operations = set_owner_to_self |
| 163 | accept.permissions = TICKET_MODIFY |
| 164 | leave = * -> * |
| 165 | leave.default = 1 |
| 166 | leave.operations = leave_status |
| 167 | reassign = new,assigned,reopened -> new |
| 168 | reassign.operations = set_owner |
| 169 | reassign.permissions = TICKET_MODIFY |
| 170 | reopen = closed -> reopened |
| 171 | reopen.operations = del_resolution |
| 172 | reopen.permissions = TICKET_CREATE |
| 173 | resolve = new,assigned,reopened,reviewing -> closed |
| 174 | resolve.operations = set_resolution |
| 175 | resolve.permissions = TICKET_MODIFY |
| 176 | review = new,assigned,reopened -> reviewing |
| 177 | review.operations = set_owner |
| 178 | review.permissions = TICKET_MODIFY |
| 179 | reassign_reviewing = reviewing -> * |
| 180 | reassign_reviewing.operations = set_owner |
| 181 | reassign_reviewing.name = reassign review |
| 182 | reassign_reviewing.permissions = TICKET_MODIFY |
| 183 | }}} |
| 184 | |
| 185 | == Example: Limit the resolution options for a new ticket == |
| 186 | |
| 187 | The above resolve_new operation allows you to set the possible resolutions for a new ticket. By modifying the existing resolve action and removing the new status from before the `->` we then get two resolve actions. One with limited resolutions for new tickets, and then the regular one once a ticket is accepted. |
| 188 | |
| 189 | {{{ |
| 190 | resolve_new = new -> closed |
| 191 | resolve_new.name = resolve |
| 192 | resolve_new.operations = set_resolution |
| 193 | resolve_new.permissions = TICKET_MODIFY |
| 194 | resolve_new.set_resolution = invalid,wontfix,duplicate |
| 195 | |
| 196 | resolve = assigned,accepted,reopened -> closed |
| 197 | resolve.operations = set_resolution |
| 198 | resolve.permissions = TICKET_MODIFY |
| 199 | }}} |
| 200 | |
| 207 | == Adding Workflow States to Milestone Progress Bars == |
| 208 | |
| 209 | If you add additional states to your workflow, you may want to customize your milestone progress bars as well. See [TracIni#milestone-groups-section TracIni]. |
| 210 | |
| 211 | == some ideas for next steps == |
| 212 | |
| 213 | New enhancement ideas for the workflow system should be filed as enhancement tickets against the `ticket system` component. If desired, add a single-line link to that ticket here. Also look at the [th:wiki:AdvancedTicketWorkflowPlugin] as it provides experimental operations. |
| 214 | |
| 215 | If you have a response to the comments below, create an enhancement ticket, and replace the description below with a link to the ticket. |
| 216 | |
| 217 | * the "operation" could be on the nodes, possible operations are: |
| 218 | * '''preops''': automatic, before entering the state/activity |
| 219 | * '''postops''': automatic, when leaving the state/activity |
| 220 | * '''actions''': can be chosen by the owner in the list at the bottom, and/or drop-down/pop-up together with the default actions of leaving the node on one of the arrows. |
| 221 | ''This appears to add complexity without adding functionality; please provide a detailed example where these additions allow something currently impossible to implement.'' |
| 222 | |
| 223 | * operations could be anything: sum up the time used for the activity, or just write some statistical fields like |
| 224 | ''A workflow plugin can add an arbitrary workflow operation, so this is already possible.'' |
| 225 | |
| 226 | * set_actor should be an operation allowing to set the owner, e.g. as a "preop": |
| 227 | * either to a role, a person |
| 228 | * entered fix at define time, or at run time, e.g. out of a field, or select. |
| 229 | ''This is either duplicating the existing `set_owner` operation, or needs to be clarified.'' |
| 230 | |
| 231 | * Actions should be selectable based on the ticket type (different Workflows for different tickets) |
| 232 | ''Look into the [th:wiki:AdvancedTicketWorkflowPlugin]'s `triage` operation.'' |