|
|
|
import os |
|
import requests |
|
import json |
|
import datetime |
|
|
|
token = os.getenv("SYSTEM_ACCESSTOKEN") |
|
headers = { |
|
'Authorization': f'Bearer {token}', |
|
'Content-Type': 'application/json' |
|
} |
|
print(f'token {token[:10]}...') |
|
|
|
# Azure DevOps configuration |
|
organization = "tolle" # Replace with your organization name |
|
project = "project1" # Replace with your project name |
|
userstory_id = 1456 # User story ID to query |
|
me = "anatoly" |
|
hours_to_add = 10 |
|
|
|
# Get work items that are children of user story 124686 |
|
base_url = f"https://dev.azure.com/{organization}/{project}/_apis/wit" |
|
query_url = f"{base_url}/wiql?api-version=7.0" |
|
|
|
|
|
wiql_query = { |
|
"query": f"SELECT [System.Id], [System.Title], [System.WorkItemType] FROM WorkItemLinks WHERE ([Source].[System.Id] = {userstory_id}) AND ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') MODE (Recursive)" |
|
} |
|
|
|
# Execute the query |
|
query_response = requests.post(query_url, headers=headers, json=wiql_query) |
|
query_result = query_response.json() |
|
|
|
print(json.dumps(query_result, indent=2)) |
|
|
|
# Extract work item IDs from the query result |
|
work_item_ids = [] |
|
if 'workItemRelations' in query_result: |
|
for relation in query_result['workItemRelations']: |
|
if relation.get('target'): |
|
work_item_ids.append(relation['target']['id']) |
|
|
|
print(f"Found {len(work_item_ids)} child work items") |
|
|
|
# Get detailed information for each work item |
|
if work_item_ids: |
|
ids_string = ",".join(map(str, work_item_ids)) |
|
details_url = f"{base_url}/workitems?ids={ids_string}&api-version=7.0" |
|
|
|
details_response = requests.get(details_url, headers=headers) |
|
work_items = details_response.json()['value'] |
|
|
|
# Find the task with "anatoly" in its name |
|
anatoly_task = None |
|
for item in work_items: |
|
# Get current week number in Sweden (ISO week) |
|
current_week = datetime.date.today().isocalendar()[1] |
|
week_format = f"v{current_week}" |
|
|
|
title = item['fields'].get('System.Title', '').lower() |
|
if 'anatoly' in title and week_format in title and item['fields'].get('System.WorkItemType') == 'Task': |
|
anatoly_task = item |
|
break |
|
else: |
|
print(f"No child work items found for user story {userstory_id}") |
|
|
|
if anatoly_task: |
|
print(json.dumps(anatoly_task, indent=2)) |
|
print(anatoly_task['fields']['System.Title']) |
|
|
|
# Create a copy of headers with updated Content-Type for patch operations |
|
patch_headers = headers.copy() |
|
patch_headers['Content-Type'] = 'application/json-patch+json' |
|
|
|
if anatoly_task: |
|
task_id = anatoly_task['id'] |
|
print(f"Found Anatoly's task: {anatoly_task['fields']['System.Title']} (ID: {task_id})") |
|
|
|
# Update the "Completed" field with 10 hours |
|
update_url = f"{base_url}/workitems/{task_id}?api-version=7.0" |
|
|
|
update_data = [ |
|
{ |
|
"op": "add", |
|
"path": "/fields/Microsoft.VSTS.Scheduling.CompletedWork", |
|
"value": hours_to_add |
|
} |
|
] |
|
|
|
update_response = requests.patch(update_url, headers=patch_headers, json=update_data) |
|
|
|
if update_response.status_code == 200: |
|
print(f"Successfully updated Completed Work to {hours_to_add} hours") |
|
updated_task = update_response.json() |
|
print(f"Updated task: {updated_task['fields']['System.Title']}") |
|
print(f"Completed Work: {updated_task['fields'].get('Microsoft.VSTS.Scheduling.CompletedWork', 'Not set')}") |
|
else: |
|
print(f"Failed to update task. Status code: {update_response.status_code}") |
|
print(f"Error: {update_response.text}") |
|
else: |
|
print(f"No task with 'anatoly' in the name found among the children of user story {userstory_id}") |