You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: reduce complexity of execute_impl in update_work_item.rs (#368)
Extract four focused helpers from the monolithic execute_impl:
- check_target_config: validates the configured target constraint
- check_field_permissions: data-driven table check replacing 7 sequential if-guards
- check_prefix_guards: fetches the work item and verifies title-/tag-prefix rules
- build_patch_document: assembles the JSON Patch operations
execute_impl is now ~100 lines of linear, easy-to-follow orchestration;
each extracted function has a single responsibility and is independently testable.
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
only \"*\" or an integer ID are valid — all updates are blocked",
203
+
p
204
+
);
205
+
false
206
+
}
207
+
};
208
+
if target_allowed {
209
+
None
210
+
}else{
211
+
Some(ExecutionResult::failure(format!(
212
+
"Work item #{id} is not permitted by the update-work-item target configuration"
213
+
)))
214
+
}
215
+
}
216
+
217
+
/// Validate that every field the agent requested to update is enabled in the configuration.
218
+
/// Returns `Some(failure)` on the first disabled field, `None` when all are allowed.
219
+
fncheck_field_permissions(
220
+
params:&UpdateWorkItemResult,
221
+
config:&UpdateWorkItemConfig,
222
+
) -> Option<ExecutionResult>{
223
+
let checks:&[(&str,bool,bool)] = &[
224
+
("Title updates are not enabled in the update-work-item configuration; set 'title: true' in safe-outputs", params.title.is_some(), config.title),
225
+
("Body/description updates are not enabled in the update-work-item configuration; set 'body: true' in safe-outputs", params.body.is_some(), config.body),
226
+
("State/status updates are not enabled in the update-work-item configuration; set 'status: true' in safe-outputs", params.state.is_some(), config.status),
227
+
("Area path updates are not enabled in the update-work-item configuration; set 'area-path: true' in safe-outputs", params.area_path.is_some(), config.area_path),
228
+
("Iteration path updates are not enabled in the update-work-item configuration; set 'iteration-path: true' in safe-outputs", params.iteration_path.is_some(), config.iteration_path),
229
+
("Assignee updates are not enabled in the update-work-item configuration; set 'assignee: true' in safe-outputs", params.assignee.is_some(), config.assignee),
230
+
("Tag updates are not enabled in the update-work-item configuration; set 'tags: true' in safe-outputs", params.tags.is_some(), config.tags),
231
+
];
232
+
for(msg, field_set, field_enabled)in checks {
233
+
if*field_set && !field_enabled {
234
+
returnSome(ExecutionResult::failure(*msg));
235
+
}
236
+
}
237
+
None
238
+
}
239
+
240
+
/// Fetch the current work item and verify title-prefix / tag-prefix guards when configured.
241
+
/// Returns `Ok(Some(failure))` if a guard blocks the update, `Ok(None)` if all guards pass,
242
+
/// or `Ok(Some(failure))` when the fetch itself fails.
243
+
asyncfncheck_prefix_guards(
244
+
client:&reqwest::Client,
245
+
org_url:&str,
246
+
project:&str,
247
+
token:&str,
248
+
id:u64,
249
+
config:&UpdateWorkItemConfig,
250
+
) -> anyhow::Result<Option<ExecutionResult>>{
251
+
if config.title_prefix.is_none() && config.tag_prefix.is_none(){
252
+
returnOk(None);
253
+
}
254
+
255
+
debug!(
256
+
"Fetching work item #{} to check prefix guards (title_prefix={:?}, tag_prefix={:?})",
257
+
id, config.title_prefix, config.tag_prefix
258
+
);
259
+
260
+
let wi = matchfetch_work_item(client, org_url, project, token, id).await{
261
+
Ok(wi) => wi,
262
+
Err(e) => {
263
+
returnOk(Some(ExecutionResult::failure(format!(
264
+
"Failed to fetch work item #{id} for prefix validation: {e}"
265
+
))));
266
+
}
267
+
};
268
+
269
+
// title-prefix check
270
+
ifletSome(prefix) = &config.title_prefix{
271
+
let current_title = wi
272
+
.get("fields")
273
+
.and_then(|f| f.get("System.Title"))
274
+
.and_then(|t| t.as_str())
275
+
.unwrap_or("");
276
+
if !current_title.starts_with(prefix.as_str()){
277
+
returnOk(Some(ExecutionResult::failure(format!(
278
+
"Work item #{id} title '{current_title}' does not start with the required prefix '{prefix}' (configured in title-prefix)"
0 commit comments