Mozilla Ubiquity – Ajouter un bug à un tracker Mantis

fév 22nd, 2009 by Mushiro in Javascript, web

Ubiquity est une extension Firefox de Mozilla Labs. C’est une sorte de ligne de commande pour lancer différentes actions à partir de votre navigateur. Comme toujours, l’extension permet d’etre étendue par l’intermédiaire de commandes supplémentaires, qu’il est assez facile de développer soi-même.

Dans le cadre d’un projet sur lequel je travaille, et aussi pour m’amuser un peu avec Ubiquity, je voulais être capable d’insérer un nouveau bug dans notre tracker de bugs Mantis. Je voulais faire un truc assez simple et basique, c’est-à-dire insérer le bug dans un projet, une catégorie, une sévérité, une priorité… définis. Mantis offre une API sous forme de Web service accessible en SOAP. Les requêtes SOAP étant essentiellement des requêtes HTTP postant une trame XML, je me suis dit que ça devait pouvoir se faire un appel à la méthode d’ajout de bug en javascript.

Ubiquity est livré avec le framework javascript jQuery. Cela simplifie pas mal de chose, par exemple la gestion des requêtes ajax, que je vais utiliser pour les requêtes HTTP SOAP. Je ne vais pas m’attarder sur la création de commandes dans Ubiquity, le tutorial de Mozilla est bien rédigé (je me suis basé dessus). Dans cet article je veux m’attarder sur le principe pour appeler l’API de Mantis. Une fois l’exemple décrit, il est facile d’ajouter d’autres méthodes, pour par exemple récupérer la liste des bugs ouverts d’un projet précis.

Dans la suite de l’article, [MANTIS_SITE] représente l’adresse vers votre installation de Mantis.

Le webservice SOAP Mantis Connect

Mantis propose son API à traver un web service SOAP, accessible par http://[MANTIS_SITE]/api/soap/mantisconnect.php. La WSDL est disponible à http://[MANTIS_SITE]/api/soap/mantisconnect.php?wsdl. Pour info, le serveur SOAP est codé avec la librairie nusoap.

La méthode qui nous intéresse ici est mc_issue_add.

1
2
3
4
5
6
7
<operation name="mc_issue_add">
  <documentation>
    Submit the specified issue details.
  </documentation>
  <input message="tns:mc_issue_addRequest"/>
  <output message="tns:mc_issue_addResponse"/>
</operation>

Elle permet d’ajouter un bug au tracker. On passe en plus du login et password de l’utilisateur, une structure IssueData, qui contient toutes les informations du bug : titre, priorité, sévérité, catégorie, projet, résumé…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<xsd:complexType name="IssueData">
  <xsd:all>
    <xsd:element name="id" type="xsd:integer" minOccurs="0"/>
    <xsd:element name="view_state" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="last_updated" type="xsd:dateTime" minOccurs="0"/>
    <xsd:element name="project" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="category" type="xsd:string" minOccurs="0"/>
    <xsd:element name="priority" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="severity" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="status" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="reporter" type="tns:AccountData" minOccurs="0"/>
    <xsd:element name="summary" type="xsd:string" minOccurs="0"/>
    <xsd:element name="version" type="xsd:string" minOccurs="0"/>
    <xsd:element name="build" type="xsd:string" minOccurs="0"/>
    <xsd:element name="platform" type="xsd:string" minOccurs="0"/>
    <xsd:element name="os" type="xsd:string" minOccurs="0"/>
    <xsd:element name="os_build" type="xsd:string" minOccurs="0"/>
    <xsd:element name="reproducibility" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="date_submitted" type="xsd:dateTime" minOccurs="0"/>
    <xsd:element name="sponsorship_total" type="xsd:integer" minOccurs="0"/>
    <xsd:element name="handler" type="tns:AccountData" minOccurs="0"/>
    <xsd:element name="projection" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="eta" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="resolution" type="tns:ObjectRef" minOccurs="0"/>
    <xsd:element name="fixed_in_version" type="xsd:string" minOccurs="0"/>
    <xsd:element name="description" type="xsd:string" minOccurs="0"/>
    <xsd:element name="steps_to_reproduce" type="xsd:string" minOccurs="0"/>
    <xsd:element name="additional_information" type="xsd:string" minOccurs="0"/>
    <xsd:element name="attachments" type="tns:AttachmentDataArray" minOccurs="0"/>
    <xsd:element name="relationships" type="tns:RelationshipDataArray" minOccurs="0"/>
    <xsd:element name="notes" type="tns:IssueNoteDataArray" minOccurs="0"/>
    <xsd:element name="custom_fields" type="tns:CustomFieldValueForIssueDataArray" minOccurs="0"/>
  </xsd:all>
</xsd:complexType>

La plupart des informations à renseigner sont des entiers, genre l’id du projet, de la catégorie, de la sévérité… Je vous invite à utiliser firebug sur le formulaire d’édition d’un bug (pas d’ajout, celui de modification possède tous les champs dont on veut connaitre les valeurs possibles). Repérez donc l’id du rapporteur, du projet, de la cétégorie, etc, dans lesquelles vous désirez mettre votre bug.

La commande Ubiquity « mantis »

Infos sur la commande

Pour éditer une commande Ubiquity, vous pouvez soit utiliser l’éditeur intégré, soit ouvrir le fichier dans un éditeur séparé (voir sur chrome://ubiquity/content/editor.html). Ci-dessous les infos sur la commande mantis :

1
2
3
4
5
6
7
8
CmdUtils.CreateCommand({
  name: "mantis",
  author: { name: "Jonathan Fretin", email: "jfretin at gmail dot com"},
  license: "MIT",
  icon: "http://www.mantisbt.org/favicon.ico",
  description: "Inserts a bug in Mantis Bug Tracker",
  help: "Inserts a bug in Mantis. Use it for example with a copy/paste from an email, with the mantis command.",
  takes: {"the bug": noun_arb_text},

J’ai choisi de mettre en favicon celle du site officiel. La commande s’utilise en tapant « mantis mon bug est le suivant : blabla… ». Un exemple en image :

La commande 'mantis'
La commande 'mantis'

Méthode « execute »

Les commandes Ubiquity sont lancées avec la méthode execute.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
execute: function(the_bug) {
    var _mantis_connect_uri = "http://[MANTIS_SITE]/api/soap/mantisconnect.php";
   
    jQuery.ajax( { type: "POST",
     url: _mantis_connect_uri,
     dataType: "xml",
     contentType: "text/xml;charset=UTF-8",
     data: this._prepare_xml(the_bug),
     processData: false,
     success: function(mantis_response) {
       var issue_number = jQuery("return", mantis_response).text();
       displayMessage( "Bug added in Mantis with issue number #" + issue_number + ".");
     }
    });
  }

Analysons ça de plus près. Le but est de faire la requête HTTP, et lui passer le XML SOAP. C’est _prepare_xml(the_bug) (sur laquelle nous reviendrons après) qui s’occupe de « préparer » le XML qui sera envoyé. Donc pour la requête, nous allons utiliser la méthode ajax de jQuery. On précise :

  • qu’on va recevoir du XML (dataType: « xml »),
  • qu’on passe du XML (contentType: « text/xml;charset=UTF-8″),
  • et qu’on ne veut pas que jQuery transforme le XML en paramètres (processData: false).
Exemple d'utilisation
Exemple d'utilisation

Le XML reçu en réponse contient l’id du bug créé :

1
2
3
4
5
6
7
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Body>
      <ns1:mc_issue_addResponse xmlns:ns1="http://futureware.biz/mantisconnect">
         <return xsi:type="xsd:integer">22</return>
      </ns1:mc_issue_addResponse>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

On récupère la valeur de cet id, pour l’afficher dans un message de confirmation (lignes 11 et 12) :

_prepare_xml

Le plus important est bien de préparer le XML qui sera envoyé par la requête. Il suffit de remplir les champs avec vos bons id de projet, de rapporteur, de categorie…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
_prepare_xml: function(the_bug) {
    summary = the_bug.summary;
    the_bug = the_bug.text;
    xml = '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:man="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\
   <soapenv:Header/>\
   <soapenv:Body>\
      <man:mc_issue_add soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\
         <username xsi:type="xsd:string">jfretin</username>\
         <password xsi:type="xsd:string">XXXXXXX</password>\
         <issue xsi:type="man:IssueData">\
            <view_state xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </view_state>\
            <project xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">3</id>\
            </project>\
            <category xsi:type="xsd:string">Graph</category>\
            <priority xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">30</id>\
            </priority>\
            <severity xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">60</id>\
            </severity>\
            <status xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </status>\
            <reporter xsi:type="man:AccountData">\
               <id xsi:type="xsd:integer">2</id>\
            </reporter>\
            <summary xsi:type="xsd:string">'
+ summary + '</summary>\
            <reproducibility xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </reproducibility>\
            <handler xsi:type="man:AccountData">\
               <id xsi:type="xsd:integer">0</id>\
            </handler>\
            <projection xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </projection>\
            <eta xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">20</id>\
            </eta>\
            <resolution xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </resolution>\
            <description xsi:type="xsd:string"><![CDATA[\
'
+ the_bug + '\
]]></description>\
         </issue>\
      </man:mc_issue_add>\
   </soapenv:Body>\
</soapenv:Envelope>'
;
    return xml;
  }

Pensez à préciser vos login et mot de passe en ligne 8 et 9. Le début de la description sera utilisé en tant que titre du bug (ligne 2 et 3).

Le bug a bien été ajouté !

Le résultat dans Mantis
Le résultat dans Mantis

Le fichier source dans son intégralité

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
CmdUtils.CreateCommand({
  name: "mantis",
  author: { name: "Jonathan Fretin", email: "jfretin at gmail dot com"},
  license: "MIT",
  icon: "http://www.mantisbt.org/favicon.ico",
  description: "Inserts a bug in Mantis Bug Tracker",
  help: "Inserts a bug in Mantis. Use it for example with a copy/paste from an email, with the mantis command.",
  takes: {"the bug": noun_arb_text},

_prepare_xml: function(the_bug) {
    summary = the_bug.summary;
    the_bug = the_bug.text;
    xml = '<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:man="http://futureware.biz/mantisconnect" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">\
   <soapenv:Header/>\
   <soapenv:Body>\
      <man:mc_issue_add soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">\
         <username xsi:type="xsd:string">jfretin</username>\
         <password xsi:type="xsd:string">XXXXXXX</password>\
         <issue xsi:type="man:IssueData">\
            <view_state xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </view_state>\
            <project xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">3</id>\
            </project>\
            <category xsi:type="xsd:string">Graph</category>\
            <priority xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">30</id>\
            </priority>\
            <severity xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">60</id>\
            </severity>\
            <status xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </status>\
            <reporter xsi:type="man:AccountData">\
               <id xsi:type="xsd:integer">2</id>\
            </reporter>\
            <summary xsi:type="xsd:string">'
+ summary + '</summary>\
            <reproducibility xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </reproducibility>\
            <handler xsi:type="man:AccountData">\
               <id xsi:type="xsd:integer">0</id>\
            </handler>\
            <projection xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </projection>\
            <eta xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">20</id>\
            </eta>\
            <resolution xsi:type="man:ObjectRef">\
               <id xsi:type="xsd:integer">10</id>\
            </resolution>\
            <description xsi:type="xsd:string"><![CDATA[\
'
+ the_bug + '\
]]></description>\
         </issue>\
      </man:mc_issue_add>\
   </soapenv:Body>\
</soapenv:Envelope>'
;
    return xml;
  },
 

  execute: function(the_bug) {
    var _mantis_connect_uri = "http://[MANTIS_SITE]/api/soap/mantisconnect.php";
   
    jQuery.ajax( { type: "POST",
     url: _mantis_connect_uri,
     dataType: "xml",
     contentType: "text/xml;charset=UTF-8",
     data: this._prepare_xml(the_bug),
     processData: false,
     success: function(mantis_response) {
       var issue_number = jQuery("return", mantis_response).text();
       displayMessage( "Bug added in Mantis with issue number #" + issue_number + ".");
     }
    });
  }
})

Vous pouvez aussi télécharger le fichier javascript : mantis-add.js

TODO

  • ajouter d’autres méthodes du web service
  • trouver un moyen de configurer plus facilement l’uri, le login et mot de passe, au lieu de le saisir dans le script.

1 Comment