Add Taiga integration.

This commit is contained in:
Antek Grzanka
2016-04-28 16:46:00 +03:00
committed by Tim Abbott
parent 755695d3c0
commit 646ea3214a
48 changed files with 3482 additions and 1 deletions

View File

@@ -9,7 +9,7 @@ All notable changes to this project will be documented in this file.
- Added documentation on using Hubot to integrate with useful services
not yet integrated with Zulip directly (e.g. Google Hangouts).
- Added new management command to test sending email from Zulip.
- Added Codeship, Pingdom, Teamcity, and Yo integrations.
- Added Codeship, Pingdom, Taiga, Teamcity, and Yo integrations.
- Refactored the Zulip puppet modules to be more modular.
- Refactored the Tornado event system, fixing old memory leaks.
- Implemented running queue processors multithreaded in development,

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -221,6 +221,12 @@
<span class="integration-label">Subversion</span>
</a>
</div>
<div class="integration-lozenge integration-taiga">
<a class="integration-link integration-taiga" href="#taiga">
<img class="integration-logo" src="/static/images/integrations/logos/taiga.png" alt="Taiga logo" />
<span class="integration-label">Taiga</span>
</a>
</div>
<div class="integration-lozenge integration-teamcity">
<a class="integration-link integration-teamcity" href="#teamcity">
<img class="integration-logo" src="/static/images/integrations/logos/teamcity.png" alt="Teamcity logo" />
@@ -1718,6 +1724,88 @@ key = NAGIOS_BOT_API_KEY
<img class="screenshot" src="/static/images/integrations/svn/001.png" />
</div>
<div id="taiga" class="integration-instructions">
<p>Go on your <a href="/#settings">Zulip settings page</a>, create a Taiga bot.
Please note the bot name and API key.</p>
<p>Since Taiga allows you to integrate services on a per
project basis, you have to perform the following steps
for <b>every project</b> that you want to send
notifications to Zulip.</p>
<ol>
<li>
<p>Go to Admin <b>></b> Integration <b>></b> Webhooks menu.</p>
</li>
<li>
<p>Click <b>Add a new webhook</b>.</p>
</li>
<li>
<p>Fill out the form by following the instructions:
<ul>
<li>
<b>Name</b> - to recognize this service, preferably <code>Zulip</code>
</li>
<li>
<b>URL</b> -
<pre>
{{ external_api_uri }}/v1/external/taiga?stream=STREAM_NAME&amp;topic=TOPIC_NAME&amp;api_key=BOT_API_KEY</pre>
<ul>
<li><code>STREAM_NAME</code> - The url-encoded name of
stream which you want to receive notifications.
You can use an existing Zulip stream or create a
new one for this.
</li>
<li><code>TOPIC_NAME</code> - The url-encoded
topic where your Taiga notifications will be
posted. (Read the notes below.)</li>
<li><code>BOT_API_KEY</code> - API key created in Zulip.</li>
</ul>
<p>Remember to url-encode the stream and topic
names. E.g. spaces need to be replaced
with <code>%20</code> (e.g. so if you want your stream
to be called "My awesome project", STREAM_NAME
should be <code>My%20awesome%20project</code>).</p>
</li>
<li>
<b>Secret key</b> - once again the API key created in Zulip.
</li>
</ul>
</p>
</li>
<li>
<p>Click <b>Save</b> once you've finished filling out the form.</p>
</li>
</ol>
<p>That's it! Your actions on Taiga should now cause
notifications on the Zulip stream you specified above.
<img class="screenshot"
src="/static/images/integrations/taiga/001.png" /> <hr />
There are <b>two different ways</b> you may want to consider
when organizing your Taiga - Zulip integration:</p>
<ul>
<li>
Use special Zulip stream for Taiga messages - name
it <code>Taiga</code>. (Make sure to create this stream
first!) For every integrated project, provide a new topic.
<pre>
STREAM_NAME = Taiga
TOPIC = Project</pre>
</li>
<li>
If you already have a Zulip stream for managing a project,
you can also use this existing stream and add Taiga
notifications using special topic.(Remember about
substituting spaces with <code>%20</code>).<pre>
STREAM_NAME = My%20existing%20Zulip%20stream
TOPIC = Taiga</pre>
</li>
</ul>
</div>
<div id="teamcity" class="integration-instructions">
<p>See your Teamcity build status in Zulip!</p>

View File

@@ -0,0 +1,70 @@
{
"type":"issue",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
126383
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"id":270391,
"version":3,
"is_blocked":false,
"blocked_note":"",
"ref":13,
"status":864973,
"severity":616377,
"priority":371208,
"type":372884,
"milestone":null,
"project":123471,
"created_date":"2016-04-13T19:36:12+0000",
"modified_date":"2016-04-14T10:15:51+0000",
"finished_date":null,
"subject":"Aaaa",
"description":"",
"external_reference":null
},
"change":{
"diff":{
"assigned_to":{
"to":126383,
"from":null
}
},
"snapshot":null,
"values":{
"users":{
"126383":"Antek"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"dd7a7a38-0229-11e6-a7fd-52540016253e",
"created_at":"2016-04-14T10:15:51+0000",
"type":1,
"key":"issues.issue:270391",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"action":"change"
}

View File

@@ -0,0 +1,62 @@
{
"change":{
"diff":{
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"00f6dad6-01af-11e6-ba7b-52540016253e",
"created_at":"2016-04-13T19:36:22+0000",
"type":1,
"key":"issues.issue:270391",
"comment":"Hobbits are in Isengard.",
"comment_html":"<p>Hobbits are in Isengard.</p>",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"issue",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
126383
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":270391,
"version":2,
"is_blocked":false,
"blocked_note":"",
"ref":13,
"status":864973,
"severity":616377,
"priority":371208,
"type":372884,
"milestone":null,
"project":123471,
"created_date":"2016-04-13T19:36:12+0000",
"modified_date":"2016-04-13T19:36:22+0000",
"finished_date":null,
"subject":"Aaaa",
"description":"",
"external_reference":null
}
}

View File

@@ -0,0 +1,72 @@
{
"type":"issue",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
126383
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":128024,
"name":"Han Solo"
},
"id":270391,
"version":6,
"is_blocked":false,
"blocked_note":"",
"ref":13,
"status":864973,
"severity":616377,
"priority":371208,
"type":372884,
"milestone":null,
"project":123471,
"created_date":"2016-04-13T19:36:12+0000",
"modified_date":"2016-04-14T10:18:26+0000",
"finished_date":null,
"subject":"More descriptive name",
"description":"More descriptive description\n",
"external_reference":null
},
"change":{
"diff":{
"description":{
"to":"More descriptive description\n",
"from":""
},
"description_html":{
"to":"<p>More descriptive description</p>",
"from":""
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"3a32ed5a-022a-11e6-9bc0-52540016141a",
"created_at":"2016-04-14T10:18:26+0000",
"type":1,
"key":"issues.issue:270391",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"action":"change"
}

View File

@@ -0,0 +1,68 @@
{
"change":{
"diff":{
"priority":{
"from":367852,
"to":367853
}
},
"snapshot":null,
"values":{
"priority":{
"367853":"High",
"367852":"Normal"
}
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"1ab7d0c4-fcd7-11e5-a7a3-52540016141a",
"created_at":"2016-04-07T15:40:50+0000",
"type":1,
"key":"issues.issue:264165",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":264165,
"version":4,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"status":857143,
"severity":610790,
"priority":367853,
"type":369483,
"milestone":null,
"project":122355,
"created_date":"2016-04-07T15:37:41+0000",
"modified_date":"2016-04-07T15:40:49+0000",
"finished_date":null,
"subject":"A new issue",
"description":"",
"external_reference":null
},
"type":"issue",
"action":"change"
}

View File

@@ -0,0 +1,71 @@
{
"change":{
"diff":{
"assigned_to":{
"to":128024,
"from":126383
}
},
"snapshot":null,
"values":{
"users":{
"128024":"Han Solo",
"126383":"Antek"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"df555558-0229-11e6-b5ec-52540016253e",
"created_at":"2016-04-14T10:15:54+0000",
"type":1,
"key":"issues.issue:270391",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"issue",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
126383
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":128024,
"name":"Han Solo"
},
"id":270391,
"version":4,
"is_blocked":false,
"blocked_note":"",
"ref":13,
"status":864973,
"severity":616377,
"priority":371208,
"type":372884,
"milestone":null,
"project":123471,
"created_date":"2016-04-13T19:36:12+0000",
"modified_date":"2016-04-14T10:15:54+0000",
"finished_date":null,
"subject":"Aaaa",
"description":"",
"external_reference":null
}
}

View File

@@ -0,0 +1,68 @@
{
"change":{
"diff":{
"severity":{
"from":610789,
"to":610790
}
},
"snapshot":null,
"values":{
"severity":{
"610789":"Important",
"610790":"Critical"
}
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"cd061cd2-fcd6-11e5-9191-52540016253e",
"created_at":"2016-04-07T15:38:39+0000",
"type":1,
"key":"issues.issue:264165",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":264165,
"version":2,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"status":857143,
"severity":610790,
"priority":367852,
"type":369481,
"milestone":null,
"project":122355,
"created_date":"2016-04-07T15:37:41+0000",
"modified_date":"2016-04-07T15:38:39+0000",
"finished_date":null,
"subject":"A new issue",
"description":"",
"external_reference":null
},
"type":"issue",
"action":"change"
}

View File

@@ -0,0 +1,68 @@
{
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":264165,
"version":5,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"status":857148,
"severity":610790,
"priority":367853,
"type":369483,
"milestone":null,
"project":122355,
"created_date":"2016-04-07T15:37:41+0000",
"modified_date":"2016-04-07T15:42:52+0000",
"finished_date":"2016-04-07T15:42:52+0000",
"subject":"A new issue",
"description":"",
"external_reference":null
},
"action":"change",
"type":"issue",
"change":{
"diff":{
"status":{
"to":857148,
"from":857143
}
},
"snapshot":null,
"values":{
"status":{
"857148":"Rejected",
"857143":"New"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"6392653e-fcd7-11e5-813a-52540016253e",
"created_at":"2016-04-07T15:42:52+0000",
"type":1,
"key":"issues.issue:264165",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
}
}

View File

@@ -0,0 +1,68 @@
{
"change":{
"diff":{
"subject":{
"to":"More descriptive name",
"from":"Aaaa"
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"33bb1cfe-022a-11e6-a7fd-52540016253e",
"created_at":"2016-04-14T10:18:16+0000",
"type":1,
"key":"issues.issue:270391",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"issue",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
126383
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":128024,
"name":"Han Solo"
},
"id":270391,
"version":5,
"is_blocked":false,
"blocked_note":"",
"ref":13,
"status":864973,
"severity":616377,
"priority":371208,
"type":372884,
"milestone":null,
"project":123471,
"created_date":"2016-04-13T19:36:12+0000",
"modified_date":"2016-04-14T10:18:15+0000",
"finished_date":null,
"subject":"More descriptive name",
"description":"",
"external_reference":null
}
}

View File

@@ -0,0 +1,68 @@
{
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":264165,
"version":3,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"status":857143,
"severity":610790,
"priority":367852,
"type":369483,
"milestone":null,
"project":122355,
"created_date":"2016-04-07T15:37:41+0000",
"modified_date":"2016-04-07T15:39:51+0000",
"finished_date":null,
"subject":"A new issue",
"description":"",
"external_reference":null
},
"action":"change",
"type":"issue",
"change":{
"diff":{
"type":{
"to":369483,
"from":369481
}
},
"snapshot":null,
"values":{
"type":{
"369481":"Bug",
"369483":"Enhancement"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"f79b7ec4-fcd6-11e5-be32-52540016253e",
"created_at":"2016-04-07T15:39:51+0000",
"type":1,
"key":"issues.issue:264165",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
}
}

View File

@@ -0,0 +1,39 @@
{
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":264165,
"version":1,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"status":857143,
"severity":610789,
"priority":367852,
"type":369481,
"milestone":null,
"project":122355,
"created_date":"2016-04-07T15:37:41+0000",
"modified_date":"2016-04-07T15:37:41+0000",
"finished_date":null,
"subject":"A new issue",
"description":"",
"external_reference":null
},
"type":"issue",
"action":"create"
}

View File

@@ -0,0 +1,38 @@
{
"deleted_date":"2016-04-13T19:03:29.859Z",
"type":"issue",
"data":{
"custom_attributes_values":null,
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":270368,
"version":1,
"is_blocked":false,
"blocked_note":"",
"ref":12,
"status":864973,
"severity":616377,
"priority":371208,
"type":372884,
"milestone":null,
"project":123471,
"created_date":"2016-04-13T19:03:20+0000",
"modified_date":"2016-04-13T19:03:20+0000",
"finished_date":null,
"subject":"Aaaa",
"description":"",
"external_reference":null
},
"action":"delete"
}

View File

@@ -0,0 +1,54 @@
{
"action":"change",
"change":{
"diff":{
"estimated_start":{
"from":"2016-04-15",
"to":"2016-04-15"
},
"estimated_finish":{
"from":"2016-04-30",
"to":"2016-04-30"
},
"name":{
"from":"New sprint",
"to":"Newer sprint"
}
},
"snapshot":null,
"values":{
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"a812e8e0-017e-11e6-a40d-52540016253e",
"created_at":"2016-04-13T13:50:17+0000",
"type":1,
"key":"milestones.milestone:70864",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"milestone",
"data":{
"owner":{
"id":126383,
"name":"Antek"
},
"id":70864,
"name":"Newer sprint",
"slug":"new-sprint-71",
"project":123471,
"estimated_start":"2016-04-15",
"estimated_finish":"2016-04-30",
"created_date":"2016-04-13T11:50:24+0000",
"modified_date":"2016-04-13T13:50:17+0000",
"closed":false,
"disponibility":0.0
}
}

View File

@@ -0,0 +1,50 @@
{
"type":"milestone",
"action":"change",
"change":{
"diff":{
"estimated_finish":{
"from":"2016-04-27",
"to":"2016-04-30"
},
"estimated_start":{
"from":"2016-04-15",
"to":"2016-04-15"
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"1e78d370-0173-11e6-8bc7-52540016253e",
"created_at":"2016-04-13T12:27:42+0000",
"type":1,
"key":"milestones.milestone:70864",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"owner":{
"id":126383,
"name":"Antek"
},
"id":70864,
"name":"New sprint",
"slug":"new-sprint-71",
"project":123471,
"estimated_start":"2016-04-15",
"estimated_finish":"2016-04-30",
"created_date":"2016-04-13T11:50:24+0000",
"modified_date":"2016-04-13T12:27:42+0000",
"closed":false,
"disponibility":0.0
}
}

View File

@@ -0,0 +1,20 @@
{
"type":"milestone",
"action":"create",
"data":{
"owner":{
"id":126383,
"name":"Antek"
},
"id":70864,
"name":"New sprint",
"slug":"new-sprint-71",
"project":123471,
"estimated_start":"2016-04-13",
"estimated_finish":"2016-04-27",
"created_date":"2016-04-13T11:50:24+0000",
"modified_date":"2016-04-13T11:50:24+0000",
"closed":false,
"disponibility":0.0
}
}

View File

@@ -0,0 +1,21 @@
{
"action":"delete",
"deleted_date":"2016-04-13T13:54:36.446Z",
"type":"milestone",
"data":{
"owner":{
"id":126383,
"name":"Antek"
},
"id":70864,
"name":"Newer sprint",
"slug":"new-sprint-71",
"project":123471,
"estimated_start":"2016-04-15",
"estimated_finish":"2016-04-30",
"created_date":"2016-04-13T11:50:24+0000",
"modified_date":"2016-04-13T13:50:17+0000",
"closed":false,
"disponibility":0.0
}
}

View File

@@ -0,0 +1,71 @@
{
"change":{
"diff":{
"assigned_to":{
"from":null,
"to":126383
}
},
"snapshot":null,
"values":{
"users":{
"126383":"Antek"
}
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"86df24e4-fcd4-11e5-b9e7-52540016253e",
"created_at":"2016-04-07T15:22:23+0000",
"type":1,
"key":"tasks.task:570983",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"id":570983,
"version":2,
"is_blocked":false,
"blocked_note":"",
"user_story":659643,
"ref":2,
"status":613055,
"project":122355,
"milestone":null,
"created_date":"2016-04-07T15:21:00+0000",
"modified_date":"2016-04-07T15:22:22+0000",
"finished_date":null,
"subject":"Aaaa",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
},
"type":"task",
"action":"change"
}

View File

@@ -0,0 +1,74 @@
{
"type":"task",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":586596,
"version":2,
"is_blocked":true,
"blocked_note":"asdasdas",
"user_story":673841,
"ref":14,
"status":618680,
"project":123471,
"milestone":null,
"created_date":"2016-04-14T09:58:24+0000",
"modified_date":"2016-04-14T09:58:30+0000",
"finished_date":null,
"subject":"A new task",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
},
"change":{
"diff":{
"blocked_note":{
"to":"asdasdas",
"from":""
},
"is_blocked":{
"to":true,
"from":false
},
"blocked_note_html":{
"to":"<p>asdasdas</p>",
"from":""
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"710a127a-0227-11e6-a735-52540016141a",
"created_at":"2016-04-14T09:58:30+0000",
"type":1,
"key":"tasks.task:586596",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"action":"change"
}

View File

@@ -0,0 +1,66 @@
{
"type":"task",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
126383
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"id":584538,
"version":5,
"is_blocked":false,
"blocked_note":"",
"user_story":672975,
"ref":5,
"status":618680,
"project":123471,
"milestone":70898,
"created_date":"2016-04-13T14:11:33+0000",
"modified_date":"2016-04-13T14:24:51+0000",
"finished_date":null,
"subject":"New task assigned and in progress",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
},
"change":{
"diff":{
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"7c42dcac-0183-11e6-8e0d-52540016253e",
"created_at":"2016-04-13T14:24:51+0000",
"type":1,
"key":"tasks.task:584538",
"comment":"New comment to the task!",
"comment_html":"<p>New comment to the task!</p>",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"action":"change"
}

View File

@@ -0,0 +1,70 @@
{
"change":{
"diff":{
"description_html":{
"to":"<p>New, better description.</p>",
"from":""
},
"description":{
"to":"New, better description.",
"from":""
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"6ab05b26-0229-11e6-a735-52540016141a",
"created_at":"2016-04-14T10:12:38+0000",
"type":1,
"key":"tasks.task:586596",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"task",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":586596,
"version":5,
"is_blocked":false,
"blocked_note":"",
"user_story":673841,
"ref":14,
"status":618680,
"project":123471,
"milestone":null,
"created_date":"2016-04-14T09:58:24+0000",
"modified_date":"2016-04-14T10:12:38+0000",
"finished_date":null,
"subject":"Even newer task.",
"us_order":1,
"taskboard_order":1,
"description":"New, better description.",
"is_iocaine":false,
"external_reference":null
}
}

View File

@@ -0,0 +1,72 @@
{
"change":{
"diff":{
"assigned_to":{
"from":126384,
"to":126383
}
},
"snapshot":null,
"values":{
"users":{
"126383":"Antek",
"126384":"Han Solo"
}
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"86df24e4-fcd4-11e5-b9e7-52540016253e",
"created_at":"2016-04-07T15:22:23+0000",
"type":1,
"key":"tasks.task:570983",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"id":570983,
"version":2,
"is_blocked":false,
"blocked_note":"",
"user_story":659643,
"ref":2,
"status":613055,
"project":122355,
"milestone":null,
"created_date":"2016-04-07T15:21:00+0000",
"modified_date":"2016-04-07T15:22:22+0000",
"finished_date":null,
"subject":"Aaaa",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
},
"type":"task",
"action":"change"
}

View File

@@ -0,0 +1,72 @@
{
"change":{
"diff":{
"status":{
"to":618680,
"from":618682
}
},
"snapshot":null,
"values":{
"status":{
"618682":"Ready for test",
"618680":"New"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"cb44c4e2-0182-11e6-8e0d-52540016253e",
"created_at":"2016-04-13T14:19:54+0000",
"type":1,
"key":"tasks.task:584538",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"task",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"id":584538,
"version":3,
"is_blocked":false,
"blocked_note":"",
"user_story":672975,
"ref":5,
"status":618680,
"project":123471,
"milestone":70898,
"created_date":"2016-04-13T14:11:33+0000",
"modified_date":"2016-04-13T14:19:54+0000",
"finished_date":null,
"subject":"New task assigned and in progress",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
}
}

View File

@@ -0,0 +1,66 @@
{
"change":{
"diff":{
"subject":{
"to":"Even newer task",
"from":"New task"
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"13cbec1c-0229-11e6-955a-52540016253e",
"created_at":"2016-04-14T10:10:13+0000",
"type":1,
"key":"tasks.task:586596",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"task",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":586596,
"version":4,
"is_blocked":false,
"blocked_note":"",
"user_story":673841,
"ref":14,
"status":618680,
"project":123471,
"milestone":null,
"created_date":"2016-04-14T09:58:24+0000",
"modified_date":"2016-04-14T10:10:12+0000",
"finished_date":null,
"subject":"Even newer task.",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
}
}

View File

@@ -0,0 +1,74 @@
{
"change":{
"diff":{
"blocked_note_html":{
"to":"",
"from":"<p>asdasdas</p>"
},
"blocked_note":{
"to":"",
"from":"asdasdas"
},
"is_blocked":{
"to":false,
"from":true
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"90eb784a-0227-11e6-955a-52540016253e",
"created_at":"2016-04-14T09:59:23+0000",
"type":1,
"key":"tasks.task:586596",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"task",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":586596,
"version":3,
"is_blocked":false,
"blocked_note":"",
"user_story":673841,
"ref":14,
"status":618680,
"project":123471,
"milestone":null,
"created_date":"2016-04-14T09:58:24+0000",
"modified_date":"2016-04-14T09:59:23+0000",
"finished_date":null,
"subject":"A new task",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
}
}

View File

@@ -0,0 +1,73 @@
{
"change":{
"diff":{
"user_story":{
"to":673326,
"from":672975
},
"taskboard_order":{
"to":0,
"from":1
}
},
"snapshot":null,
"values":{
"user_story":{
"673326":"#6 Greater US",
"672975":"#3 Great US"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"6ea553fa-0182-11e6-9f02-52540016141a",
"created_at":"2016-04-13T14:17:19+0000",
"type":1,
"key":"tasks.task:584537",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"task",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":584537,
"version":2,
"is_blocked":false,
"blocked_note":"",
"user_story":673326,
"ref":4,
"status":618680,
"project":123471,
"milestone":70898,
"created_date":"2016-04-13T14:11:15+0000",
"modified_date":"2016-04-13T14:17:19+0000",
"finished_date":null,
"subject":"A new task",
"us_order":1,
"taskboard_order":0,
"description":"",
"is_iocaine":false,
"external_reference":null
}
}

View File

@@ -0,0 +1,43 @@
{
"type":"task",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"id":584538,
"version":1,
"is_blocked":false,
"blocked_note":"",
"user_story":672975,
"ref":5,
"status":618681,
"project":123471,
"milestone":null,
"created_date":"2016-04-13T14:11:33+0000",
"modified_date":"2016-04-13T14:11:33+0000",
"finished_date":null,
"subject":"New task assigned and in progress",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
},
"action":"create"
}

View File

@@ -0,0 +1,39 @@
{
"deleted_date":"2016-04-13T18:10:06.594Z",
"type":"task",
"data":{
"custom_attributes_values":null,
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"id":585230,
"version":1,
"is_blocked":false,
"blocked_note":"",
"user_story":673841,
"ref":11,
"status":618680,
"project":123471,
"milestone":null,
"created_date":"2016-04-13T18:10:00+0000",
"modified_date":"2016-04-13T18:10:00+0000",
"finished_date":null,
"subject":"hhh",
"us_order":1,
"taskboard_order":1,
"description":"",
"is_iocaine":false,
"external_reference":null
},
"action":"delete"
}

View File

@@ -0,0 +1,94 @@
{
"change":{
"diff":{
"assigned_to":{
"to":126383,
"from":null
}
},
"snapshot":null,
"values":{
"users":{
"126383":"Antek"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"7c33d752-018d-11e6-b12d-52540016141a",
"created_at":"2016-04-13T15:36:26+0000",
"type":1,
"key":"userstories.userstory:672975",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"userstory",
"action":"change",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
}
],
"id":672975,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"milestone":70898,
"project":123471,
"status":721850,
"is_closed":false,
"created_date":"2016-04-13T11:57:38+0000",
"modified_date":"2016-04-13T15:36:26+0000",
"finish_date":null,
"subject":"Great US",
"description":"",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,100 @@
{
"type":"userstory",
"action":"change",
"change":{
"diff":{
"is_blocked":{
"from":false,
"to":true
},
"blocked_note":{
"from":"",
"to":"Unsure what to do."
},
"blocked_note_html":{
"from":"",
"to":"<p>Unsure what to do.</p>"
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"85838e40-016c-11e6-a653-52540016253e",
"created_at":"2016-04-13T11:40:28+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":true,
"blocked_note":"Unsure what to do.",
"ref":2,
"milestone":null,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:40:28+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,103 @@
{
"type":"userstory",
"action":"change",
"change":{
"diff":{
"is_closed":{
"from":false,
"to":true
},
"status":{
"from":721850,
"to":721854
},
"finish_date":{
"from":"None",
"to":"2016-04-13 11:38:06.961674+00:00"
}
},
"snapshot":null,
"values":{
"status":{
"721854":"Done",
"721850":"New"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"311b8ba0-016c-11e6-b505-52540016141a",
"created_at":"2016-04-13T11:38:07+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":null,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:38:06+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,86 @@
{
"type":"userstory",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
}
],
"id":672975,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"milestone":null,
"project":123471,
"status":721850,
"is_closed":false,
"created_date":"2016-04-13T11:57:38+0000",
"modified_date":"2016-04-13T14:04:55+0000",
"finish_date":null,
"subject":"Great US",
"description":"",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
},
"change":{
"diff":{
},
"snapshot":null,
"values":{
},
"user":{
"pk":128024,
"name":"Han Solo"
},
"delete_comment_user":null,
"id":"b37f12ce-0180-11e6-97aa-52540016253e",
"created_at":"2016-04-13T14:04:56+0000",
"type":1,
"key":"userstories.userstory:672975",
"comment":"Hello!",
"comment_html":"<p>Hello!</p>",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"action":"change"
}

View File

@@ -0,0 +1,96 @@
{
"type":"userstory",
"action":"change",
"change":{
"diff":{
"description_html":{
"from":"",
"to":"<p>new description hello</p>"
},
"description":{
"from":"",
"to":"new description hello\n"
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"0ba5fada-016d-11e6-a653-52540016253e",
"created_at":"2016-04-13T11:44:13+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":true,
"blocked_note":"Baaaaaad US.",
"ref":2,
"milestone":null,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:44:13+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"new description hello\n",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,95 @@
{
"action":"change",
"change":{
"diff":{
"milestone":{
"from":70865,
"to":70864
}
},
"snapshot":null,
"values":{
"milestone":{
"70865": "Old sprint",
"70864":"New sprint"
}
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"2aec6342-016e-11e6-9744-52540016141a",
"created_at":"2016-04-13T11:52:15+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"userstory",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":true,
"blocked_note":"Baaaaaad US.",
"ref":2,
"milestone":70864,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:52:15+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"new description hello\n",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,94 @@
{
"action":"change",
"change":{
"diff":{
"milestone":{
"from":null,
"to":70864
}
},
"snapshot":null,
"values":{
"milestone":{
"70864":"New sprint"
}
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"2aec6342-016e-11e6-9744-52540016141a",
"created_at":"2016-04-13T11:52:15+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"userstory",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":true,
"blocked_note":"Baaaaaad US.",
"ref":2,
"milestone":70864,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:52:15+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"new description hello\n",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,110 @@
{
"type":"userstory",
"action":"change",
"change":{
"diff":{
"points":{
"from":{
"750724":1483752,
"750723":1483752,
"750726":1483752,
"750725":1483752
},
"to":{
"750724":1483752,
"750723":1483757,
"750726":1483752,
"750725":1483752
}
}
},
"snapshot":null,
"values":{
"points":{
"1483757":"3",
"1483752":"?"
},
"roles":{
"750724":"Design",
"750723":"UX",
"750726":"Back",
"750725":"Front"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"3a7a4cc4-016a-11e6-a3b9-52540016253e",
"created_at":"2016-04-13T11:24:04+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":null,
"project":123471,
"status":721850,
"is_closed":false,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:24:03+0000",
"finish_date":null,
"subject":"A new hope",
"description":"",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,95 @@
{
"type":"userstory",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":128024,
"name":"Han Solo"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
}
],
"id":672975,
"is_blocked":false,
"blocked_note":"",
"ref":3,
"milestone":70898,
"project":123471,
"status":721850,
"is_closed":false,
"created_date":"2016-04-13T11:57:38+0000",
"modified_date":"2016-04-13T16:54:19+0000",
"finish_date":null,
"subject":"Great US",
"description":"",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
},
"change":{
"diff":{
"assigned_to":{
"to":128024,
"from":126383
}
},
"snapshot":null,
"values":{
"users":{
"126383":"Antek",
"128024":"Han Solo"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"5d94df0c-0198-11e6-811a-52540016253e",
"created_at":"2016-04-13T16:54:19+0000",
"type":1,
"key":"userstories.userstory:672975",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"action":"change"
}

View File

@@ -0,0 +1,103 @@
{
"type":"userstory",
"action":"change",
"change":{
"diff":{
"is_closed":{
"from":true,
"to":false
},
"status":{
"from":721854,
"to":721850
},
"finish_date":{
"from":"2016-04-13 11:38:06.961674+00:00",
"to":"None"
}
},
"snapshot":null,
"values":{
"status":{
"721854":"Done",
"721850":"New"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"311b8ba0-016c-11e6-b505-52540016141a",
"created_at":"2016-04-13T11:38:07+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":null,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:38:06+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,94 @@
{
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1470231,
"name":"?",
"value":null
},
{
"id":1470231,
"name":"?",
"value":null
},
{
"id":1470231,
"name":"?",
"value":null
},
{
"id":1470231,
"name":"?",
"value":null
}
],
"id":659643,
"is_blocked":false,
"blocked_note":"",
"ref":1,
"milestone":null,
"project":122355,
"status":715044,
"is_closed":false,
"created_date":"2016-04-07T14:43:23+0000",
"modified_date":"2016-04-07T15:35:34+0000",
"finish_date":null,
"subject":"A new hope",
"description":"asdasdas",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
},
"action":"change",
"type":"userstory",
"change":{
"diff":{
"status":{
"to":715044,
"from":715040
}
},
"snapshot":null,
"values":{
"status":{
"715044":"Done",
"715040":"New"
}
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"5eb37680-fcd6-11e5-b9e7-52540016253e",
"created_at":"2016-04-07T15:35:34+0000",
"type":1,
"key":"userstories.userstory:659643",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
}
}

View File

@@ -0,0 +1,92 @@
{
"action":"change",
"change":{
"diff":{
"subject":{
"from":"A new hope",
"to":"A newer hope"
}
},
"snapshot":null,
"values":{
},
"user":{
"name":"Antek",
"pk":126383
},
"delete_comment_user":null,
"id":"031ea1ce-016c-11e6-a653-52540016253e",
"created_at":"2016-04-13T11:36:50+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"type":"userstory",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":null,
"project":123471,
"status":721850,
"is_closed":false,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:36:49+0000",
"finish_date":null,
"subject":"A newer hope",
"description":"",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,100 @@
{
"type":"userstory",
"action":"change",
"change":{
"diff":{
"is_blocked":{
"from":true,
"to":false
},
"blocked_note":{
"from":"Unsure what to do.",
"to":""
},
"blocked_note_html":{
"from":"<p>Unsure what to do.</p>",
"to":""
}
},
"snapshot":null,
"values":{
},
"user":{
"pk":126383,
"name":"Antek"
},
"delete_comment_user":null,
"id":"cdf8edb4-016c-11e6-a9ae-52540016253e",
"created_at":"2016-04-13T11:42:30+0000",
"type":1,
"key":"userstories.userstory:672899",
"comment":"",
"comment_html":"",
"delete_comment_date":null,
"is_hidden":false,
"is_snapshot":false
},
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
},
{
"id":1483757,
"name":"3",
"value":3.0
}
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":null,
"project":123471,
"status":721854,
"is_closed":true,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:42:30+0000",
"finish_date":"2016-04-13T11:38:06+0000",
"subject":"A newer hope",
"description":"",
"client_requirement":false,
"team_requirement":true,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,62 @@
{
"action":"create",
"type":"userstory",
"data":{
"custom_attributes_values":{
},
"is_watcher":false,
"total_watchers":0,
"watchers":[
],
"tags":[
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":null,
"points":[
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
},
{
"id":1483752,
"name":"?",
"value":null
}
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":null,
"project":123471,
"status":721850,
"is_closed":false,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:22:00+0000",
"finish_date":null,
"subject":"A new hope",
"description":"",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -0,0 +1,46 @@
{
"type":"userstory",
"action":"delete",
"deleted_date":"2016-04-13T11:56:17.654Z",
"data":{
"custom_attributes_values":null,
"is_watcher":false,
"total_watchers":0,
"watchers":[
128024,
126383
],
"tags":[
"great tag"
],
"external_reference":null,
"owner":{
"id":126383,
"name":"Antek"
},
"assigned_to":{
"id":126383,
"name":"Antek"
},
"points":[
],
"id":672899,
"is_blocked":false,
"blocked_note":"",
"ref":2,
"milestone":70864,
"project":123471,
"status":721851,
"is_closed":false,
"created_date":"2016-04-13T11:22:00+0000",
"modified_date":"2016-04-13T11:54:36+0000",
"finish_date":null,
"subject":"A newer hope",
"description":"new description hello\n",
"client_requirement":false,
"team_requirement":false,
"generated_from_issue":null,
"tribe_gig":null
}
}

View File

@@ -1065,3 +1065,220 @@ class CodeshipHookTests(AuthedTestCase):
result = self.client.post(self._url, json, stream_name=self.STREAM_NAME, content_type="application/json")
self.assert_json_success(result)
return result
class TaigaHookTests(AuthedTestCase):
def send_taiga_message(self, action):
email = "hamlet@zulip.com"
api_key = self.get_api_key(email)
stream = "taiga"
topic = "subject"
mesg = self.fixture_data("taiga", action, file_type="json")
url = "/api/v1/external/taiga?stream=%s&topic=%s&api_key=%s" % (stream, topic, api_key)
self.send_json_payload(email, url, mesg, stream_name=stream, content_type="application/json")
return self.get_last_message()
def test_taiga_userstory_deleted(self):
msg = self.send_taiga_message("userstory_deleted")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':x: Antek deleted user story **A newer hope**.\n')
def test_taiga_userstory_created(self):
msg = self.send_taiga_message("userstory_created")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':package: Antek created user story **A new hope**.\n')
def test_taiga_userstory_changed_unblocked(self):
msg = self.send_taiga_message("userstory_changed_unblocked")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':unlock: Antek unblocked user story **A newer hope**.\n')
def test_taiga_userstory_changed_subject(self):
msg = self.send_taiga_message("userstory_changed_subject")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek renamed user story from A new hope to **A newer hope**.\n')
def test_taiga_userstory_changed_status(self):
msg = self.send_taiga_message("userstory_changed_status")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':chart_with_upwards_trend: Antek changed status of user story **A new hope** from New to Done.\n')
def test_taiga_userstory_changed_reassigned(self):
msg = self.send_taiga_message("userstory_changed_reassigned")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':busts_in_silhouette: Antek reassigned user story **Great US** from Antek to Han Solo.\n')
def test_taiga_userstory_changed_points(self):
msg = self.send_taiga_message("userstory_changed_points")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':game_die: Antek changed estimation of user story **A new hope**.\n')
def test_taiga_userstory_changed_new_milestone(self):
msg = self.send_taiga_message("userstory_changed_new_milestone")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':calendar: Antek added user story **A newer hope** to sprint New sprint.\n')
def test_taiga_userstory_changed_milestone(self):
msg = self.send_taiga_message("userstory_changed_milestone")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':calendar: Antek changed sprint of user story **A newer hope** from Old sprint to New sprint.\n')
def test_taiga_userstory_changed_description(self):
msg = self.send_taiga_message("userstory_changed_description")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek updated description of user story **A newer hope**.\n')
def test_taiga_userstory_changed_closed(self):
msg = self.send_taiga_message("userstory_changed_closed")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':chart_with_upwards_trend: Antek changed status of user story **A newer hope** from New to Done.\n:checkered_flag: Antek closed user story **A newer hope**.\n')
def test_taiga_userstory_changed_reopened(self):
msg = self.send_taiga_message("userstory_changed_reopened")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':chart_with_upwards_trend: Antek changed status of user story **A newer hope** from Done to New.\n:package: Antek reopened user story **A newer hope**.\n')
def test_taiga_userstory_changed_blocked(self):
msg = self.send_taiga_message("userstory_changed_blocked")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':lock: Antek blocked user story **A newer hope**.\n')
def test_taiga_userstory_changed_assigned(self):
msg = self.send_taiga_message("userstory_changed_assigned")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':busts_in_silhouette: Antek assigned user story **Great US** to Antek.\n')
def test_taiga_task_created(self):
msg = self.send_taiga_message("task_created")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':clipboard: Antek created task **New task assigned and in progress**.\n')
def test_taiga_task_changed_status(self):
msg = self.send_taiga_message("task_changed_status")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':chart_with_upwards_trend: Antek changed status of task **New task assigned and in progress** from Ready for test to New.\n')
def test_taiga_task_changed_blocked(self):
msg = self.send_taiga_message("task_changed_blocked")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':lock: Antek blocked task **A new task**.\n')
def test_taiga_task_changed_unblocked(self):
msg = self.send_taiga_message("task_changed_unblocked")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':unlock: Antek unblocked task **A new task**.\n')
def test_taiga_task_changed_assigned(self):
msg = self.send_taiga_message("task_changed_assigned")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':busts_in_silhouette: Antek assigned task **Aaaa** to Antek.\n')
def test_taiga_task_changed_reassigned(self):
msg = self.send_taiga_message("task_changed_reassigned")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':busts_in_silhouette: Antek reassigned task **Aaaa** from Han Solo to Antek.\n')
def test_taiga_task_changed_subject(self):
msg = self.send_taiga_message("task_changed_subject")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek renamed task New task to **Even newer task**.\n')
def test_taiga_task_changed_description(self):
msg = self.send_taiga_message("task_changed_description")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek updated description of task **Even newer task.**.\n')
def test_taiga_task_changed_us(self):
msg = self.send_taiga_message("task_changed_us")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':clipboard: Antek moved task **A new task** from user story #3 Great US to #6 Greater US.\n')
def test_taiga_task_deleted(self):
msg = self.send_taiga_message("task_deleted")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':x: Antek deleted task **hhh**.\n')
def test_taiga_milestone_created(self):
msg = self.send_taiga_message("milestone_created")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':calendar: Antek created sprint **New sprint**.\n')
def test_taiga_milestone_deleted(self):
msg = self.send_taiga_message("milestone_deleted")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':x: Antek deleted sprint **Newer sprint**.\n')
def test_taiga_milestone_changed_time(self):
msg = self.send_taiga_message("milestone_changed_time")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':calendar: Antek changed estimated finish of sprint **New sprint** from 2016-04-27 to 2016-04-30.\n')
def test_taiga_milestone_changed_name(self):
msg = self.send_taiga_message("milestone_changed_name")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek renamed sprint from New sprint to **Newer sprint**.\n')
def test_taiga_issue_created(self):
msg = self.send_taiga_message("issue_created")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':bulb: Antek created issue **A new issue**.\n')
def test_taiga_issue_deleted(self):
msg = self.send_taiga_message("issue_deleted")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':x: Antek deleted issue **Aaaa**.\n')
def test_taiga_issue_changed_assigned(self):
msg = self.send_taiga_message("issue_changed_assigned")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':busts_in_silhouette: Antek assigned issue **Aaaa** to Antek.\n')
def test_taiga_issue_changed_reassigned(self):
msg = self.send_taiga_message("issue_changed_reassigned")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':busts_in_silhouette: Antek reassigned issue **Aaaa** from Antek to Han Solo.\n')
def test_taiga_issue_changed_subject(self):
msg = self.send_taiga_message("issue_changed_subject")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek renamed issue Aaaa to **More descriptive name**.\n')
def test_taiga_issue_changed_description(self):
msg = self.send_taiga_message("issue_changed_description")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':notebook: Antek updated description of issue **More descriptive name**.\n')
def test_taiga_issue_changed_type(self):
msg = self.send_taiga_message("issue_changed_type")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':bulb: Antek changed type of issue **A new issue** from Bug to Enhancement.\n')
def test_taiga_issue_changed_status(self):
msg = self.send_taiga_message("issue_changed_status")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':chart_with_upwards_trend: Antek changed status of issue **A new issue** from New to Rejected.\n')
def test_taiga_issue_changed_severity(self):
msg = self.send_taiga_message("issue_changed_severity")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':warning: Antek changed severity of issue **A new issue** from Important to Critical.\n')
def test_taiga_issue_changed_priority(self):
msg = self.send_taiga_message("issue_changed_priority")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':rocket: Antek changed priority of issue **A new issue** from Normal to High.\n')
def test_taiga_userstory_comment_added(self):
msg = self.send_taiga_message("userstory_changed_comment_added")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':thought_balloon: Han Solo commented on user story **Great US**.\n')
def test_taiga_task_changed_comment_added(self):
msg = self.send_taiga_message("task_changed_comment_added")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':thought_balloon: Antek commented on task **New task assigned and in progress**.\n')
def test_taiga_issue_changed_comment_added(self):
msg = self.send_taiga_message("issue_changed_comment_added")
self.assertEqual(msg.subject, u'subject')
self.assertEqual(msg.content, u':thought_balloon: Antek commented on issue **Aaaa**.\n')

View File

@@ -0,0 +1,248 @@
"""
Taiga integration for Zulip.
Tips for notification output:
*Emojis*: most of the events have specific emojis e.g.
- :notebook: - change of subject/name/description
- :chart_with_upwards_trend: - change of status
etc. If no there's no meaningful emoji for certain event, the defaults are used:
- :thought_balloon: - event connected to commenting
- :busts_in_silhouette: - event connected to a certain user
- :package: - all other events connected to user story
- :calendar: - all other events connected to milestones
- :clipboard: - all other events connected to tasks
- :bulb: - all other events connected to issues
*Text formatting*: if there has been a change of a property, the new value should always be in bold; otherwise the
subject of US/task should be in bold.
"""
from __future__ import absolute_import
from zerver.models import get_client
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
import ujson
from six.moves import range
@api_key_only_webhook_view
@has_request_variables
def api_taiga_webhook(request, user_profile, stream=REQ(default='taiga'), topic=REQ(default='General')):
try:
message = ujson.loads(request.body)
except ValueError:
return json_error("Malformed JSON input")
parsed_events = parse_message(message)
content = ""
for event in parsed_events:
content += generate_content(event) + '\n'
check_send_message(user_profile, get_client('ZulipTaigaWebhook'), 'stream', [stream], topic, content)
return json_success()
templates = {
'userstory': {
'create': u':package: %(user)s created user story **%(subject)s**.',
'set_assigned_to': u':busts_in_silhouette: %(user)s assigned user story **%(subject)s** to %(new)s.',
'changed_assigned_to': u':busts_in_silhouette: %(user)s reassigned user story **%(subject)s** from %(old)s to %(new)s.',
'points': u':game_die: %(user)s changed estimation of user story **%(subject)s**.',
'blocked': u':lock: %(user)s blocked user story **%(subject)s**.',
'unblocked': u':unlock: %(user)s unblocked user story **%(subject)s**.',
'set_milestone': u':calendar: %(user)s added user story **%(subject)s** to sprint %(new)s.',
'changed_milestone': u':calendar: %(user)s changed sprint of user story **%(subject)s** from %(old)s to %(new)s.',
'changed_status': u':chart_with_upwards_trend: %(user)s changed status of user story **%(subject)s** from %(old)s to %(new)s.',
'closed': u':checkered_flag: %(user)s closed user story **%(subject)s**.',
'reopened': u':package: %(user)s reopened user story **%(subject)s**.',
'renamed': u':notebook: %(user)s renamed user story from %(old)s to **%(new)s**.',
'description': u':notebook: %(user)s updated description of user story **%(subject)s**.',
'commented': u':thought_balloon: %(user)s commented on user story **%(subject)s**.',
'delete': u':x: %(user)s deleted user story **%(subject)s**.'
},
'milestone': {
'create': u':calendar: %(user)s created sprint **%(subject)s**.',
'renamed': u':notebook: %(user)s renamed sprint from %(old)s to **%(new)s**.',
'estimated_start': u':calendar: %(user)s changed estimated start of sprint **%(subject)s** from %(old)s to %(new)s.',
'estimated_finish': u':calendar: %(user)s changed estimated finish of sprint **%(subject)s** from %(old)s to %(new)s.',
'delete': u':x: %(user)s deleted sprint **%(subject)s**.'
},
'task': {
'create': u':clipboard: %(user)s created task **%(subject)s**.',
'set_assigned_to': u':busts_in_silhouette: %(user)s assigned task **%(subject)s** to %(new)s.',
'changed_assigned_to': u':busts_in_silhouette: %(user)s reassigned task **%(subject)s** from %(old)s to %(new)s.',
'blocked': u':lock: %(user)s blocked task **%(subject)s**.',
'unblocked': u':unlock: %(user)s unblocked task **%(subject)s**.',
'set_milestone': u':calendar: %(user)s added task **%(subject)s** to sprint %(new)s.',
'changed_milestone': u':calendar: %(user)s changed sprint of task **%(subject)s** from %(old)s to %(new)s.',
'changed_status': u':chart_with_upwards_trend: %(user)s changed status of task **%(subject)s** from %(old)s to %(new)s.',
'renamed': u':notebook: %(user)s renamed task %(old)s to **%(new)s**.',
'description': u':notebook: %(user)s updated description of task **%(subject)s**.',
'commented': u':thought_balloon: %(user)s commented on task **%(subject)s**.',
'delete': u':x: %(user)s deleted task **%(subject)s**.',
'changed_us': u':clipboard: %(user)s moved task **%(subject)s** from user story %(old)s to %(new)s.'
},
'issue': {
'create': u':bulb: %(user)s created issue **%(subject)s**.',
'set_assigned_to': u':busts_in_silhouette: %(user)s assigned issue **%(subject)s** to %(new)s.', #
'changed_assigned_to': u':busts_in_silhouette: %(user)s reassigned issue **%(subject)s** from %(old)s to %(new)s.',
'changed_priority': u':rocket: %(user)s changed priority of issue **%(subject)s** from %(old)s to %(new)s.',
'changed_severity': u':warning: %(user)s changed severity of issue **%(subject)s** from %(old)s to %(new)s.',
'changed_status': u':chart_with_upwards_trend: %(user)s changed status of issue **%(subject)s** from %(old)s to %(new)s.',
'changed_type': u':bulb: %(user)s changed type of issue **%(subject)s** from %(old)s to %(new)s.',
'renamed': u':notebook: %(user)s renamed issue %(old)s to **%(new)s**.',
'description': u':notebook: %(user)s updated description of issue **%(subject)s**.',
'commented': u':thought_balloon: %(user)s commented on issue **%(subject)s**.',
'delete': u':x: %(user)s deleted issue **%(subject)s**.'
},
}
def get_old_and_new_values(change_type, message):
""" Parses the payload and finds previous and current value of change_type."""
values_map = {
'assigned_to': 'users',
'status': 'status',
'severity': 'severity',
'priority': 'priority',
'milestone': 'milestone',
'type': 'type',
'user_story': 'user_story'
}
if change_type in ['subject', 'name', 'estimated_finish', 'estimated_start']:
old = message["change"]["diff"][change_type]["from"]
new = message["change"]["diff"][change_type]["to"]
return old, new
try:
old_id = message["change"]["diff"][change_type]["from"]
old = message["change"]["values"][values_map[change_type]][str(old_id)]
except KeyError:
old = None
try:
new_id = message["change"]["diff"][change_type]["to"]
new = message["change"]["values"][values_map[change_type]][str(new_id)]
except KeyError:
new = None
return old, new
def parse_comment(message):
""" Parses the comment to issue, task or US. """
return {
'event': 'commented',
'type': message["type"],
'values': {
'user': message["change"]["user"]["name"],
'subject': message["data"]["subject"] if "subject" in list(message["data"].keys()) else message["data"]["name"]
}
}
def parse_create_or_delete(message):
""" Parses create or delete event. """
return {
'type': message["type"],
'event': message["action"],
'values':
{
'user': message["data"]["owner"]["name"],
'subject': message["data"]["subject"] if "subject" in list(message["data"].keys()) else message["data"]["name"]
}
}
def parse_change_event(change_type, message):
""" Parses change event. """
evt = {}
values = {
'user': message["change"]["user"]["name"],
'subject': message["data"]["subject"] if "subject" in list(message["data"].keys()) else message["data"]["name"]
}
if change_type in ["description", "points"]:
event_type = change_type
elif change_type in ["milestone", "assigned_to"]:
old, new = get_old_and_new_values(change_type, message)
if not old:
event_type = "set_" + change_type
values["new"] = new
else:
event_type = "changed_" + change_type
values.update({'old': old, 'new': new})
elif change_type == "is_blocked":
if message["change"]["diff"]["is_blocked"]["to"]:
event_type = "blocked"
else:
event_type = "unblocked"
elif change_type == "is_closed":
if message["change"]["diff"]["is_closed"]["to"]:
event_type = "closed"
else:
event_type = "reopened"
elif change_type == "user_story":
old, new = get_old_and_new_values(change_type, message)
event_type = "changed_us"
values.update({'old': old, 'new': new})
elif change_type in ["subject", 'name']:
event_type = 'renamed'
old, new = get_old_and_new_values(change_type, message)
values.update({'old': old, 'new': new})
elif change_type in ["estimated_finish", "estimated_start"]:
old, new = get_old_and_new_values(change_type, message)
if not old == new:
event_type = change_type
values.update({'old': old, 'new': new})
else:
# date hasn't changed
return None
elif change_type in ["priority", "severity", "type", "status"]:
event_type = 'changed_' + change_type
old, new = get_old_and_new_values(change_type, message)
values.update({'old': old, 'new': new})
else:
# we are not supporting this type of event
return None
evt.update({"type": message["type"], "event": event_type, "values": values})
return evt
def parse_message(message):
""" Parses the payload by delegating to specialized functions. """
events = []
if message["action"] in ['create', 'delete']:
events.append(parse_create_or_delete(message))
elif message["action"] == 'change':
if message["change"]["diff"]:
for value in message["change"]["diff"]:
parsed_event = parse_change_event(value, message)
if parsed_event: events.append(parsed_event)
if message["change"]["comment"]:
events.append(parse_comment(message))
return events
def generate_content(data):
""" Gets the template string and formats it with parsed data. """
try:
return templates[data['type']][data['event']] % data['values']
except KeyError:
return json_error("Unknown message")

View File

@@ -154,6 +154,7 @@ urlpatterns += patterns('zerver.views',
url(r'^api/v1/external/pingdom$', 'webhooks.pingdom.api_pingdom_webhook'),
url(r'^api/v1/external/pivotal$', 'webhooks.pivotal.api_pivotal_webhook'),
url(r'^api/v1/external/stash$', 'webhooks.stash.api_stash_webhook'),
url(r'^api/v1/external/taiga$', 'webhooks.taiga.api_taiga_webhook'),
url(r'^api/v1/external/teamcity$', 'webhooks.teamcity.api_teamcity_webhook'),
url(r'^api/v1/external/travis$', 'webhooks.travis.api_travis_webhook'),
url(r'^api/v1/external/yo$', 'webhooks.yo.api_yo_app_webhook'),