Compare commits

...

29 Commits

Author SHA1 Message Date
27166314af refactor(resolved_tasks):add secrets to the .env 2024-03-27 12:51:11 +05:00
Angelina Tingaeva
d73a2da3e6 refactor(resolved_task): make full search 2023-12-14 14:37:46 +05:00
Angelina Tingaeva
98137f11f2 fix(mapping_close_tasks):may be i have done it 2023-12-13 00:03:35 +05:00
Angelina Tingaeva
992e99b25f refactor(mapping): create status closed for tasks_completed 2023-12-12 16:14:44 +05:00
f3cac73622 fix(close_tasks): improper endpoints and data structure manipulation 2023-12-11 19:45:36 +05:00
Angelina Tingaeva
c36858f891 refactor(resolved_tasks):create logs for control the API-answer 2023-12-11 17:21:38 +05:00
Angelina Tingaeva
e1e199c53f refactor(resolved_tasks):add check for getting answer-issue, try to get tasks in response 2023-12-11 17:05:28 +05:00
Angelina Tingaeva
2edd6fd3df feat(resolved): create func for make tasks with resolved statuses 2023-12-10 21:17:56 +05:00
Angelina Tingaeva
f552c08b33 ауфе 2023-12-10 21:15:45 +05:00
0b668f85c5 refactor(core): general refactor for subtasks and their nested mapping 2023-12-08 17:55:38 +05:00
fe39119518 fix(core): a set of data inconsistencies and minor bugs 2023-12-08 15:04:51 +05:00
Angelina Tingaeva
c7cd5dbd1b refactor(mapping_parent):new param for url to take parent_data 2023-12-07 17:53:18 +05:00
Angelina Tingaeva
de1be5a536 refactor(mappping): set the limit for task creation 2023-12-07 16:44:29 +05:00
Angelina Tingaeva
bb26424787 refactor(mappin_parent): change arg for assign_parent_task -> task, for baseurl take task[id] 2023-12-06 19:25:16 +05:00
Angelina Tingaeva
c76bb23c6d refactor(mapping_parent): one more try ti create parent task 2023-12-06 16:08:36 +05:00
Angelina Tingaeva
2a5778bfe4 fix(mapping): check gid in task 2023-12-06 13:50:09 +05:00
Angelina Tingaeva
10eadc8a95 fix(mapping_parent): fix the way(arr) to call the parent func 2023-12-06 13:14:24 +05:00
Angelina Tingaeva
a6961cb19a refactor(mapping): change attr for get_parent_task_ids to task 2023-12-05 18:34:12 +05:00
Angelina Tingaeva
af2805d793 refactor(parent_mapping): check for gid existing 2023-12-05 18:29:31 +05:00
Angelina Tingaeva
24a409cfcf check for gid existing 2023-12-05 18:26:18 +05:00
Angelina Tingaeva
915be612a3 refactor(mapping): add task_parent not last version 2023-12-05 17:04:11 +05:00
Angelina Tingaeva
52deaacf3a refactor(mapping): refactor logging for updating data_parent 2023-12-05 12:50:02 +05:00
Angelina Tingaeva
b703cfbd7c refactor(mapping): refactor uploading with logging 2023-12-05 11:09:26 +05:00
Angelina Tingaeva
528e76f3ee refactor(mapping): refactor updating data and create messages about updating yandex tracker data with parent task 2023-12-05 02:08:07 +05:00
Angelina Tingaeva
007ca43a43 refactor(mapping)delete unusable strings 2023-12-04 11:30:59 +05:00
Angelina Tingaeva
7613b7da06 refeactor(mapping): make global var for queue 2023-12-04 11:23:30 +05:00
Angelina Tingaeva
ad9621641f refeactor(logging): try to encode logs 2023-12-04 11:04:16 +05:00
98c09a6f9c chore: merge commits 2023-12-01 12:13:34 +05:00
b643ba6271 chore(logging): a bunch of corrections in logging - codepage, setting logger file name e.t.c 2023-12-01 12:06:03 +05:00
6 changed files with 865 additions and 654 deletions

File diff suppressed because one or more lines are too long

View File

@@ -1,30 +1,36 @@
import logging
import logging.handlers
import sys
def setup_logging():
sys.stdin.reconfigure(encoding='utf-8')
sys.stdout.reconfigure(encoding='utf-8')
def setup_logging(name):
""" Создание логгера """
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
""" Создание обработчика для записи логов в файл """
file_handler = logging.handlers.RotatingFileHandler(
filename='mapping.log',
maxBytes=1024*1024,
backupCount=5
file_handler = logging.FileHandler(
filename=f"{name}.log",
mode='w',
encoding='utf-8',
delay=True
)
file_handler.setLevel(logging.DEBUG)
""" Создание обработчика для вывода логов на консоль """
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)
console_handler.setLevel(logging.INFO)
""" Форматтер для вывода в файл """
file_formatter = logging.Formatter(
'%(asctime)s [%(levelname)s] [%(name)s] [%(request)s] [%(response)s] - %(message)s'
'%(asctime)s [%(levelname)s] [%(name)s] - %(message)s'
)
""" Форматтер для вывода на консоль """

View File

@@ -2,33 +2,32 @@ import csv
import json
import os
import sys
# import logging
import time
import requests
# logging.basicConfig(level=logging.DEBUG, filename='mapping.log', filemode='w')
from logging_config import setup_logging
from urllib.parse import urlencode
logger = setup_logging()
logger = setup_logging(__name__)
base_dir = os.path.dirname(os.path.realpath(__file__))
asana_data_json = os.path.join(base_dir, './data/data_asana.json')
users_data = os.path.join(base_dir, './data/users.mapping.asana2ya.csv')
sys.stdin.reconfigure(encoding='utf-8')
sys.stdout.reconfigure(encoding='utf-8')
# ниже функция для случаев, когда не будет готового файла для импорта
# def get_data_from_asana():
# """ Получение данных из Asana """
# headers = {
# 'Authorization': 'ASANA_TOKEN',
# }
# response = requests.get('https://api.asana.com/projects/PROJECT_ID/tasks', headers=headers)
# data = response.json()
# return data
QUEUE_NAME = 'TESTIMPORT'
headers = {
'Host': 'api.tracker.yandex.net',
'Authorization': 'OAuth y0_AgAEA7qkB3KjAArkXwAAAADzMlP9oR1lwMzBS2e94jHzdnII8Laxi7k',
'X-Org-ID': '7095769',
'Content-Type': 'appication/json',
}
def get_assignee_data():
@@ -60,13 +59,29 @@ def get_task_status(task):
return status, completed_at
# здесь функция для дальнейшей работы с parent
def get_parent_task_ids(task, ya_imported_task_response):
""" Получение соответствий между идентификаторами подзадач в Асане и Яндекс Трекере """
parent_task_ids = {}
if task.get('parent') and 'gid' in task['parent']:
parent_gid = task['parent']['gid']
if parent_gid in ya_imported_task_response:
parent_id = ya_imported_task_response[parent_gid]
parent_task_ids[task['gid']] = parent_id
return parent_task_ids
def transform_data(data):
""" Преобразование данных из Asana в ЯндексТрекер в совместимом формате """
transformed_data = []
for task in data["data"]:
for task in data:
status, completed_at = get_task_status(task)
transformed_task = {
'gid': task['gid'],
'summary': task['name'],
'description': task['notes'],
'createdAt': task['created_at'],
@@ -74,85 +89,157 @@ def transform_data(data):
'assignee': task['assignee'],
'status': status,
'completedAt': completed_at,
'parent': task['parent'],
'subtasks': transform_data(task['subtasks'])
}
transformed_data.append(transformed_task)
return transformed_data
def create_tasks_in_tracker(data):
def create_task(task):
base_url = 'https://api.tracker.yandex.net/v2/issues/_import'
print(task)
if task.get('assignee') and 'gid' in task['assignee']:
ya_assignee = assignee.get(task['assignee']['gid'], 'dr.cyrill')
else:
ya_assignee = 'dr.cyrill'
payload = {
'queue': QUEUE_NAME,
'summary': task['summary'],
'description': task['description'],
'createdAt': task['createdAt'],
'createdBy': 'dr.cyrill',
'deadline': task['deadline'],
'assignee': ya_assignee,
'status': task['status'],
}
logger.debug('Request: %s', json.dumps(payload))
response = requests.post(
base_url,
headers=headers,
data=json.dumps(payload),
params=urlencode({'parent': task['parent']}) # добавила параметр для parent в url-запрос
)
if response.status_code == 201:
print('Задача успешно создана в ЯндексТрекер')
# здесь добавлено про родительскую задачу
return response.json()['id']
else:
print(
'Ошибка при создании задачи в ЯндексТрекер:',
response.content,
)
logger.debug('Response: %s', response.content)
def create_tasks_in_tracker(data, limit=10):
""" Создание задач в ЯндексТрекер """
base_url = 'https://api.tracker.yandex.net/v2/issues/_import'
datalen = (len(data) if limit==-1 else min(limit, len(data)))
logger.info('Import started. Task count: %d', datalen)
# этот датасет тоже для parent добавлен
ya_imported_task_response = {}
for i in range(datalen):
task = data[i]
task_id = create_task(task)
logger.info('Created task id = %s',task_id)
for subtask in task['subtasks']:
logger.info('Found subtask gid = %s for id = %s',subtask['gid'], task_id)
subtask_id = create_task(subtask)
assign_parent_task(subtask_id, task_id)
# и эта функция для родительской задачи написана
def assign_parent_task(task_id, parent_id):
""" Назначение родительской задачи """
base_url = f'https://api.tracker.yandex.net/v2/issues/{task_id}'
headers = {
'Host': 'api.tracker.yandex.net',
'Authorization': 'OAuth y0_AgAEA7qkB3KjAArkXwAAAADzMlP9oR1lwMzBS2e94jHzdnII8Laxi7k',
'X-Org-ID': '7095769',
'Content-Type': 'appication/json',
'Content-Type': 'application/json',
}
for task in data:
if task.get('assignee') and 'gid' in task['assignee']:
ya_assignee = assignee.get(task['assignee']['gid'], 'dr.cyrill')
else:
ya_assignee = 'dr.cyrill'
payload = {
'queue': 'TESTIMPORT', # Вынести в переменную
'summary': task['summary'],
'description': task['description'],
'createdAt': task['createdAt'],
'createdBy': 'dr.cyrill',
'deadline': task['deadline'],
'assignee': ya_assignee,
# 'milestone': task['milestone'],
# 'memberships': task['memberships'],
# 'parent': task['parent'],
'status': task['status'],
# 'completedAt': task['completedAt']
}
# logger.debug('Запрос: %s', json.dumps(payload))
response = requests.post(
base_url,
headers=headers,
data=json.dumps(payload),
)
if response.status_code == 201:
print('Задача успешно создана в ЯндексТрекер')
else:
print(
'Ошибка при создании задачи в ЯндексТрекер:',
response.content,
)
# logger.debug('Ответ: %s', response.content)
ya_imported_task_response = response.json()
if task.get('parent'):
parent_task_gid = task['parent']['gid']
if parent_task_gid in ya_imported_task_response:
parent_task_id = ya_imported_task_response[parent_task_gid]['id']
update_parent_task(
base_url,
headers,
ya_imported_task_response['id'],
parent_task_id,
)
def update_parent_task(base_url, headers, task_id, parent_task_id):
""" Обновление данных родительской задачи в ЯндексТрекере"""
payload = {
'parent': parent_task_id
'parent': parent_id,
}
update_url = f"{base_url}/{task_id}"
logger.debug('Request: %s', json.dumps(payload))
response = requests.patch(
base_url,
headers=headers,
data=json.dumps(payload),
)
if response.status_code == 200:
print('Родительская задача успешно назначена')
logger.info('Task %s successfully assigned a parent',task_id)
else:
print('Ошибка при назначении родительской задачи:', response.content)
logger.debug('Response: %s', response.content)
time.sleep(1) # добавляем задержку перед следующим запросом к API
# здесь я закончила добавлять про родительскую задачу с большой надеждой
# пробую закрыть задачи уже в Трекере
def close_tasks_for_completedAt(queue_name):
base_url = 'https://api.tracker.yandex.net/v2/issues/_search'
payload = {
"filter": {
"queue": queue_name,
"status": "resolved" # Фильтр для задач cо статусом closed
}
}
response = requests.post(
base_url,
headers=headers,
data=json.dumps(payload)
)
if response.status_code == 200:
logger.debug('Response: %s', response.content)
tasks = response.json()
for task in tasks:
task_id = task['id']
close_payload = {
'resolution': 'fixed'
}
close_url = f'https://api.tracker.yandex.net/v2/issues/{task_id}/transitions/close/_execute'
print(close_url)
print(headers)
close_response = requests.post(
close_url,
headers=headers,
data=json.dumps(close_payload)
)
if close_response.status_code == 200:
print(f'Задача {task_id} закрыта успешно')
else:
print(f'Ошибка при закрытии задачи {task_id}: {close_response.content}')
else:
print(f'Ошибка при получении задач для очереди {queue_name}: {response.content}')
# asana_data = get_data_from_asana()
file = open(asana_data_json, "r", encoding="utf8")
json_data = json.loads(file.read())
yandex_tracker_data = transform_data(json_data)
create_tasks_in_tracker(yandex_tracker_data)
yandex_tracker_data = transform_data(json_data['data'])
create_tasks_in_tracker(yandex_tracker_data, limit=3)
close_tasks_for_completedAt('TESTIMPORT')

View File

@@ -43,3 +43,40 @@ def logRoundtrip(response, *args, **kwargs):
session = requests.Session()
session.hooks['response'].append(logRoundtrip)
session.get('http://secariolabs.com')
# ya_imported_task_response = response.json()
# if task.get('parent'):
# parent_task_gid = task['parent']['gid']
# if parent_task_gid in ya_imported_task_response:
# parent_task_id = ya_imported_task_response[parent_task_gid]['id']
# logger.debug(f'В задаче {task["summary"]} есть связка "parent"', ensure_ascii=False)
# update_parent_task(
# base_url,
# headers,
# ya_imported_task_response['id'],
# parent_task_id,
# )
# def update_parent_task(base_url, headers, task_id, parent_task_id):
# """ Обновление данных родительской задачи в ЯндексТрекере"""
# data = {
# 'parent': parent_task_id
# }
# payload = json.dumps(data)
# update_url = f"{base_url}/{task_id}"
# response = requests.post(update_url, headers=headers, data=payload)
# result = json.loads(response.text)
# logger.warning(json.dumps(result, ensure_ascii=False))
# if response.status_code == 200:
# logger.info('Данные о связи с задачей "parent" успешно обновлены')
# else:
# logger.error(
# 'Ошибка при обновлении данных о связи с задачей "parent": %s',
# response.content,
# )

View File

@@ -1,6 +1,7 @@
certifi==2023.11.17
charset-normalizer==3.3.2
idna==3.4
dotenv==1.0.1
requests==2.31.0
setuptools==69.0.0
six==1.16.0

78
resolved_task.py Normal file
View File

@@ -0,0 +1,78 @@
import json
import os
import sys
import requests
from dotenv import load_dotenv
from logging_config import setup_logging
load_dotenv()
logger = setup_logging(__name__)
base_dir = os.path.dirname(os.path.realpath(__file__))
asana_data_json = os.path.join(base_dir, './data/data_asana.json')
users_data = os.path.join(base_dir, './data/users.mapping.asana2ya.csv')
sys.stdin.reconfigure(encoding='utf-8')
sys.stdout.reconfigure(encoding='utf-8')
QUEUE_NAME = 'TESTIMPORT'
TOKEN = os.getenv('TOKEN')
def close_tasks_in_queue(queue_name):
base_url = 'https://api.tracker.yandex.net/v2/issues/_search'
# base_url = 'https://api.tracker.yandex.net/v2/issues/_search?expand=transitions'
headers = {
'Host': 'api.tracker.yandex.net',
'Authorization': TOKEN,
'X-Org-ID': '7095769',
'Content-Type': 'application/json',
}
payload = {
"filter": {
"queue": queue_name,
"status": "open" # Фильтр для открытых задач в указанной очереди
}
}
while True:
response = requests.post(
base_url,
headers=headers,
data=json.dumps(payload)
)
if response.status_code == 200:
logger.debug('Response: %s', response.content)
tasks = response.json()
for task in tasks:
task_id = task['id']
close_payload = {
'resolution': 'fixed'
}
close_url = f'https://api.tracker.yandex.net/v2/issues/{task_id}/transitions/close/_execute'
print(close_url)
print(headers)
close_response = requests.post(
close_url,
headers=headers,
data=json.dumps(close_payload)
)
if close_response.status_code == 200:
print(f'Задача {task_id} закрыта успешно')
else:
print(f'Ошибка при закрытии задачи {task_id}: {close_response.content}')
else:
print(f'Ошибка при получении задач для очереди {queue_name}: {response.content}')
# Вызов функции для закрытия задач в очереди 'TESTIMPORT'
close_tasks_in_queue('TESTIMPORT')