yandex_tracker_client provides python interface to Yandex Tracker v2 API.
yandex_tracker_client could be installed by pip:
pip install yandex_tracker_client
The Yandex Tracker API uses the OAuth 2.0 protocol for application authorization. Applications use the OAuth 2.0 protocol to access Yandex services on behalf of a user. You can get your token here. You can also use IAM tokens for Yandex Cloud organizations. Read here about IAM tokens.
To use client you need to initialize client first:
from yandex_tracker_client import TrackerClient
client = TrackerClient(token=<token>, org_id=<org_id>)
For Yandex Cloud organizations you need to use cloud_org_id instead of org_id parameter. Use iam_token parameter for temporary IAM tokens.
Getting issue:
issue = client.issues['MYQUEUE-42']
print issue.deadline, issue.updatedAt
Handling 404 exceptions:
from yandex_tracker_client.exceptions import NotFound
try:
issue = client.issues['MYQUEUE-42']
except NotFound:
pass
Creating issue: Full field list here. .. code:: python
- client.issues.create(
- queue='MYQUEUE', summary='API Test Issue', type={'name': 'Bug'}, description='test description'
)
Updating issue:
issue = client.issues['MYQUEUE-42']
issue.update(summary='East or west, Yandex Tracker is the best', priority='minor')
Searching for issues:
issues = client.issues.find('Queue: MYQUEUE Assignee: me()') #You can copy this query from ui tracker interface
print [issue.key for issue in issues]
Using the 'filter' parameter possible to pass the parameters of the filtering as a dictionary:
issues = client.issues.find(
filter={'queue': 'MYQUEUE', 'assignee': 'me()', 'created': {'from': '2019-03-02'}},
order=['update','-status', '+priority'],
per_page=15
)
print [issue.key for issue in issues]
Obtaining list of transitions:
transitions = issue.transitions.get_all()
for transition in transitions:
print transition
Executing transition:
issue = client.issues['MYQUEUE-42']
issue.transitions['close'].execute()
Executing transition with comment and resolution:
issue = client.issues['MYQUEUE-42']
transition = issue.transitions['close']
transition.execute(comment='Fixed', resolution='fixed')
Queue info:
queue = client.queues['MYQUEUE']
or:
queue = client.issues['MYQUEUE-42'].queue
Queue list:
queues = client.queues.get_all()[:3]
List issue attachments:
attachments = client.issues['MYQUEUE-42'].attachments
Downloading attachments to specified directory:
[attachment.download_to('some/path') for attachments in client.get_attachments('MYQUEUE-42')]
Uploading an attachment
issue = client.issues['MYQUEUE-42']
issue.attachments.create('path/to/file')
Deleting an attachment
ATTACHMENTS_TO_DELETE = {'to_delete.txt', 'smth.jpeg'}
issue = client.issues['MYQUEUE-42']
for attach in issue.attachments:
if attach.name in ATTACHMENTS_TO_DELETE:
attach.delete()
or
issue.attachments[42].delete()
List issue comments:
issue = client.issues['MYQUEUE-42']
comments = list(issue.comments.get_all())[:3]
Add comment:
issue = client.issues['MYQUEUE-42']
comment = issue.comments.create(text='Test Comment')
Add comment with attachments:
issue = client.issues['MYQUEUE-42']
comment = issue.comments.create(text='Test comment', attachments=['path/to/file1', 'path/to/file2'])
Update comment:
issue = client.issues['MYQUEUE-42']
comment = issue.comments[42]
comment.update(text='New Text')
Deleting a comment:
issue = client.issues['MYQUEUE-42']
comment = issue.comments[42]
comment.delete()
List issue links:
issue = client.issues['MYQUEUE-42']
links = issue.links
Add link:
issue = client.issues['MYQUEUE-42']
link = issue.links.create(issue='TEST-42', relationship='relates')
Deleting a link:
issue = client.issues['MYQUEUE-42']
link = issue.links[42]
link.delete()
Add remote link:
issue = client.issues['MYQUEUE-42']
link = issue.remotelinks.create(origin="ru.yandex.lunapark", key="MYQUEUE-42", relationship="relates")
Bulk update:
bulkchange = client.bulkchange.update(
['MYQUEUE-42', 'MYQUEUE-43', 'MYQUEUE-44'],
priority='minor',
tags={'add': ['minored']})
print bulkchange.status
bulkchange = bulkchange.wait()
print bulkchange.status
Bulk transition:
bulkchange = client.bulkchange.transition(
['MYQUEUE-42', 'MYQUEUE-43'], 'need_info', priority='minor')
bulkchange.wait()
Bulk move:
bulkchange = client.bulkchange.move(['MYQUEUE-42', 'MYQUEUE-43'], 'TEST')
bulkchange.wait()
Perform actions with objects
Client allows to make arbitrary subqueries to entities, for example in
order to archive version you have to make request
POST /v2/versions/<id>/_archive
In order to support such separate subqueries exists method perform_action, usage example:
version = client.versions[60031] version.perform_action('_archive', 'post', ignore_empty_body=True)
Some of tracker api endpoints doesn't work correctly with blank ({}
)
body, in this case you should pass ignore_empty_body=True
to this
method.
If endpoint require list in body use list_data
param
and just pass needed kwargs otherwise.
Change assignee in all tickets
from yandex_tracker_client import TrackerClient
client = TrackerClient(token=<token>, org_id=<org_id>)
def sent_employee_to_vacation(assignee, replace_with):
"""
:param assignee: login in Yandex Tracker
:type assignee: ``str``
:param replace_with: login in Yandex Tracker
:type replace_with: ``str``
:return: is operation was successful
:rtype: ``bool``
"""
issues_to_transfer = client.issues.find(filter={'queue': 'MYQUEUE', 'assignee': assignee})
bulk_change = client.bulkchange.update(issues_to_transfer, assignee=replace_with)
bulk_change.wait()
if bulk_change.status == 'COMPLETED':
log.info('Successfully change assignee in bulkchange {}'.format(bulk_change.id))
for issue in issues_to_transfer:
issue.comments.create('Your ticket will be processed by another employee - {}'.format(replace_with))
successful = True
else:
log.error('Bulkchange operation {} failed'.format(bulk_change.id))
successful = False
return successful
Create related issues
def start_new_feature_creation_process(feature):
feature_type = get_feature_type(feature)
manager = get_manager_by_type(feature_type)
# manager = 'manager_login'
main_issue = client.issues.create(
queue='MAINQUEUE',
assignee=manager,
summary='New feature request: {}'.format(feature),
type={'name': 'Task'},
description='New feature request arrived'
)
if feature_type.need_design:
design_issue = client.issues.create(
queue='DESIGN',
summary='Feature "{}" design'.format(feature),
type={'name': 'Task'},
description='Need design for new feature, main task: {}'.format(main_issue.id)
)
main_issue.links.create(issue=design_issue.id, relationship='relates')
if feature_type.add_followers:
followers = get_followers(feature_type)
# followers = ['my_login', 'someoneelse_login']
main_issue.update(followers={'add': followers})
if feature_type.need_testing:
tester = get_random_tester()
# tester = 'tester_login'
main_issue.update(qa=tester)
log.info('Successfully start new feature creation process')
return main_issue.id
./run_tests.sh