Project export and import¶
Various tools are used to export and import a project structure. Those tools can be use to export and import inside the same Tuleap instance or between two different Tuleap instances.
Attention
Known issues / limitation
Before going into details, here is the list of the known issues and limitation of the export and import scripts:
- The export and import scripts have to be run as
codendiadm
. If they are run byroot
, you can experience some permissions denied while copying an imported artifact with attachments. - Copied artifacts have their first changeset not well exported in XML.
- Permissions on artifact can have a different value during the export in a specific case. If the field is checked to
restrict access to
all_users
, we assume that the field has no value set. The access to the artifact is not changed, only the field value. - The cross-references in followup comments are modified by adding a space between # and the number in order to not leak data in the import in another Tuleap instance.
Project Export¶
The export script is located in /usr/share/tuleap/src/utils/export_project_xml.php
and
must be use like:
$> su - codendiadm $> cd /usr/share/tuleap/ $> src/utils/php-launcher.sh src/utils/export_project_xml.php \ -p PROJECT_ID_EXPORT \ -u SITE_ADMIN_USERNAME \ -t TRACKER_V5_ID \ -o PATH_TO_ARCHIVE
This will generate a zip archive with:
- a
project.xml
file that contains project data (usergroups with members + tracker structure + artifacts historized) - a
users.xml
file that contains users involved in project data - a folder
data
that contains artifact attachments, svn repository and so on.
This archive is ready to be imported in a Tuleap instance.
Project Import¶
The imported archive contains a list of users. Those users are not necessarily present on the target Tuleap instance. Therefore we need to know what action must be taken for unknown users; in some cases we will need to map to another existing users (jdoe on source instance may be john.doe on target instance), or we may have to create a new user.
This is done thanks to a mapping file in csv format. Hopefully a script is here to generate this mapping file based on the archive and current users on target instance:
$> su - codendiadm $> cd /usr/share/tuleap/ $> src/utils/php-launcher.sh src/utils/generate_user_mapping_for_project_import.php \ -u SITE_ADMIN_USERNAME \ -i PATH_TO_ARCHIVE \ -o PATH_TO_MAPPING_FILE
The generated file will look like:
name,action,comments jdoe,noop,"Status of existing user jdoe is [S]" nterray,create:S,"Nicolas Terray (nterray) <nterray@example.com> must be created" yrossetto,map:,"There is an existing user yrossetto but its email <yannis@example.com> does not match <yrossetto@example.com>. Use action "map:yrossetto" to confirm the mapping" ...
In this example:
jdoe
is a suspended user on the target instance. You may decide to do nothing (noop
), or you can decide to mapjdoe
to another user (see below).nterray
does not exist, it should be created. It will be created with suspended statuscreate:S
, with active statuscreate:A
or with restricted statuscreate:R
. Default status is suspended.yrossetto
seems to already exist on the target platform but the email is not the same than the source one. In order to not impersonate someone, you must confirm that both accounts relate to the same person. Maybe it is someone else, therefore you canmap:
to another account.
Comments column should give you all needed information about current status.
Note
Please note that this column is only informative and will not be used during the import.
Note
The following diagram explains how the décision is made while parsing the users.xml:
After having reviewed/edited the mapping file, you should pass it through a script in order to know if your choices are valid in regards to current status of the target instance:
$> src/utils/php-launcher.sh src/utils/check_user_mapping_for_project_import.php \ -u SITE_ADMIN_USERNAME \ -i PATH_TO_ARCHIVE \ -m PATH_TO_MAPPING_FILE
This will generate some feedback about the wellness of the mapping file. You must fix any remaining errors before doing the real import:
$> su - codendiadm $> cd /usr/share/tuleap/ $> tuleap import-project-xml -p PROJECT_ID_IMPORT \ -u PROJECT_ADMIN_USERNAME \ -i PATH_TO_ARCHIVE \ -m PATH_TO_MAPPING_FILE
Import format¶
Tuleap is able to import a project with it’s content from an XML file. This section describes what is the content of this file and how to proceed to generate an XML compatible with the import tool.
Note
As of today, the following things are covered by the import tool:
- user groups definition with members
- trackers with contents and history
- subversion
- Git
- Agile dashboard
- FRS
- Mediawiki
General informations¶
The import should be a zip archive with
- description of project content in
project.xml
file - list of all users that will appear in project.xml in
users.xml
file - data blob (should be referenced in project.xml) in
data
directory
Users management¶
In project.xml
, when we have to refer to a user the pattern is the following <node format="format">identifier</node>
where format
can either be:
id
a user unique id (integer)username
a user unique login name (string)ldap
user reference in LDAP, useful for in house data migration (string)
You can pick whatever format you want.
Important
Anonymous users
Another format can be used: email
. This is only to reference anonymous users on the source instance.
At import time, if the email match an existing user, it will be used (instead of treating the user as anonymous).
As soon as you reference a user in project.xml
, this user must be defined in users.xml
like:
<user>
<id>101</id>
<username>john_doe</username>
<realname><![CDATA[John Doe]]></realname>
<email><![CDATA[john.doe@example.com]]></email>
<ldapid><![CDATA[johndoe]]></ldapid>
</user>
The 5 nodes should be present but the most important are username
, realname
and email
those elements
will be used to decide whether the user already exists on the platform or not (and create the corresponding account if needed).
id
should be unique but will only be used if you are using <node format="id">123</node>
references in project.xml. We recommend to have a numeric sequence (1, 2, 3…) here.
ldapid
can be empty but if you move data from one service to another within the same organization,
this might be useful to share the user base. This should be the unique identifier of the user in LDAP.
Possible values from LDAP fields uid
, uuid
, etc. 99% of the time it’s the unique part of LDAP dn
.
Example of users.xml:
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user>
<id>101</id>
<username>john_doe</username>
<realname><![CDATA[John Doe]]></realname>
<email><![CDATA[john.doe@example.com]]></email>
<ldapid><![CDATA[johndoe]]></ldapid>
</user>
<user>
<id>102</id>
<username>alice</username>
<realname><![CDATA[Alice Grant]]></realname>
<email><![CDATA[alice.grant@example.com]]></email>
<ldapid></ldapid>
</user>
</users>
Danger
if a user in project.xml
is not referenced in users.xml
then the script will stop during the import, leading
to half imported data.
Core¶
All projects related information (core & services) are stored in project.xml
.
Core information imported as of today:
- Project metadata: unix name, full name, description, long description, and access (for more information see “Create a new project”)
- User groups and membership (user are referenced by username or ldapId, and group name can be dynamic group names where applicable)
- Services to be enabled. If a service is not specified, the enabled status is taken from the template project.
- Dashboards: create dashboards with widgets. No dashboards are inherited from template starting 9.18 when import of
dashboards where introduced. Following widgets can be imported:
- projectdescription
- projectmembers
- projectheartbeat
- projectlatestfilereleases
- projectlatestnews
- projectpublicareas
- projectlatestsvncommits
- projectlatestcvscommits
- projectsvnstats
- projectrss (with ‘rss’ preference: 2 values ‘title’ and ‘url’)
- projectimageviewer (with ‘image’ preference: 2 values ‘title’ and ‘url’)
- projectcontact
- plugin_agiledashboard_projects_kanban (with ‘kanban’ preference: 1 reference ‘id’ that must refer to a kanban ‘id’)
<?xml version="1.0" encoding="UTF-8"?>
<project
unix-name="project42"
full-name="Project 42"
description="Secret project to find the answer"
access="public">
<long-description>
This is the long description of project 42
</long-description>
<ugroups>
<ugroup name="project_members" description="">
<members>
<member format="username">joey_star</member>
<member format="username">alice</member>
<member format="username">bob</member>
</members>
</ugroup>
<ugroup name="project_admins" description="">
<members>
<member format="username">alice</member>
<member format="username">bob</member>
</members>
</ugroup>
<ugroup name="Developers" description="">
<members>
<member format="username">joey_star</member>
</members>
</ugroup>
</ugroups>
<services>
<service shortname="svn" enabled="true" />
<service shortname="cvs" enabled="false" />
<service shortname="plugin_git" enabled="true" />
<service shortname="plugin_tracker" enabled="true" />
</services>
<dashboards>
<dashboard name="Dashboard">
<line layout="two-columns-small-big">
<column>
<widget name="projectdescription" />
<widget name="projectmembers" />
<widget name="projectheartbeat" />
</column>
<column>
<widget name="plugin_agiledashboard_projects_kanban">
<preference name="kanban">
<reference name="id" REF="K01"></reference>
<value name="title">Todo</value>
</preference>
</widget>
</column>
</line>
</dashboard>
...
</dashboards>
<!-- ... services ... -->
</project>
Note
Users that are suspended won’t be part of the imported project.
All services can then be configured using its own tag.
Trackers¶
Basics:
<trackers>
node contains a list of<tracker>
, then<triggers>
and finally<references>
- Within a
<tracker>
there is first the structure of the tracker and then the data themselves within<artifacts>
node. - The tracker structure is made of metadata (like
<name>
), fields (<formElements>
), semantics (<semantics>
), Workflow & field dependencies (<rules>
,<workflow>
), reports (<reports>
) and permissions (<permissions>
). - An
<artifact>
is made of<changeset>
, each<changeset>
corresponds to a modification of the artifact. Order matters! the first <changeset> is the artifact creation. - A
<changeset>
is composed of a<comment>
(can be intext
orhtml
format) and a set of<field_change>
. Each<field_change>
refers to a field referenced in the<formElements>
section of<tracker>
.
Example of a simple tracker with a few fields¶
The example below is a simple tracker made of following fields
- Id (type: artifact id)
- Submitted by (type: submitted by)
- Title (type: string, associated to “title” semantic)
- Dependency (type: artifact link)
- Description (type: text)
- 2 structure fields columns (C1 and C2)
- Product (type: multiselectbox)
- Status (type: selectbox, associated to “status” semantic)
Some insights to better understand how this works:
- L73: definition of status semantic uses reference to field F6680, this will automatically refer to the field defined L51. And same applies for values considered as “Open” (<open_values>, L78) that uses references V7678, V7679 and V7680 defined L56-59.
- L146: the artifact creation set a value to this status field (<field_change field_name=”status”>) and the value (<value format=”id”>7678</value>) refers to V7678 L56.
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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | <?xml version="1.0" encoding="UTF-8"?>
<project>
<services>
<service shortname="plugin_tracker" enabled="true" />
...
</services>
...
<trackers use-natures="true">
<tracker id="T239" parent_id="0" instantiate_for_new_projects="1">
<name><![CDATA[Simple Tracker]]></name>
<item_name>simple</item_name>
<description><![CDATA[simple tracker example]]></description>
<color>inca_silver</color>
<cannedResponses/>
<formElements>
<formElement type="aid" ID="F6683" rank="3">
<name>id</name>
<label><![CDATA[Id]]></label>
</formElement>
<formElement type="subby" ID="F6684" rank="4">
<name>submitted_by</name>
<label><![CDATA[Submitted by]]></label>
</formElement>
<formElement type="string" ID="F6677" rank="5">
<name>title</name>
<label><![CDATA[Title]]></label>
<properties size="30"/>
</formElement>
<formElement type="art_link" ID="F6676" rank="6">
<name>depends</name>
<label><![CDATA[Depends]]></label>
</formElement>
<formElement type="text" ID="F6678" rank="11892">
<name>description</name>
<label><![CDATA[Description]]></label>
<properties rows="10" cols="50"/>
</formElement>
<formElement type="column" ID="F6681" rank="11893">
<name>c1</name>
<label><![CDATA[C1]]></label>
<formElements>
<formElement type="msb" ID="F6679" rank="0">
<name>product</name>
<label><![CDATA[Product]]></label>
<properties size="7"/>
<bind type="static" is_rank_alpha="0">
<items>
<item ID="V7675" label="UI" is_hidden="0"/>
<item ID="V7676" label="Database" is_hidden="0"/>
<item ID="V7677" label="API" is_hidden="0"/>
</items>
</bind>
</formElement>
</formElements>
</formElement>
<formElement type="column" ID="F6682" rank="11894">
<name>c2</name>
<label><![CDATA[C2]]></label>
<formElements>
<formElement type="sb" ID="F6680" rank="0">
<name>status</name>
<label><![CDATA[Status]]></label>
<bind type="static" is_rank_alpha="0">
<items>
<item ID="V7678" label="New" is_hidden="0"/>
<item ID="V7679" label="Under analysis" is_hidden="0"/>
<item ID="V7680" label="Under verification" is_hidden="0"/>
<item ID="V7681" label="Done" is_hidden="0"/>
</items>
</bind>
</formElement>
</formElements>
</formElement>
</formElements>
<semantics>
<semantic type="title">
<shortname>title</shortname>
<label>Title</label>
<description>Define the title of an artifact</description>
<field REF="F6677"/>
</semantic>
<semantic type="status">
<shortname>status</shortname>
<label>Status</label>
<description>Define the status of an artifact</description>
<field REF="F6680"/>
<open_values>
<open_value REF="V7678"/>
<open_value REF="V7679"/>
<open_value REF="V7680"/>
</open_values>
</semantic>
<semantic type="tooltip"/>
<semantic type="plugin_cardwall_card_fields"/>
</semantics>
<rules>
<date_rules/>
<list_rules/>
</rules>
<reports>
<report is_default="0">
<name>Default</name>
<description>The system default artifact report</description>
<criterias>
<criteria rank="0">
<field REF="F6680"/>
</criteria>
</criterias>
<renderers>
<renderer type="table" rank="0" chunksz="15">
<name>Results</name>
<columns>
<field REF="F6683"/>
<field REF="F6677"/>
<field REF="F6680"/>
<field REF="F6679"/>
</columns>
</renderer>
</renderers>
</report>
</reports>
<workflow/>
<permissions>
<permission scope="tracker" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_ACCESS_FULL"/>
<permission scope="field" REF="F6683" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6684" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6676" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6676" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6676" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6677" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6677" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6677" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6678" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6678" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6678" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6679" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6679" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6679" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6680" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6680" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6680" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
</permissions>
<artifacts>
<artifact id="445">
<changeset>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:19+01:00</submitted_on>
<comments/>
<field_change field_name="title" type="string">
<value><![CDATA[A demo bug]]></value>
</field_change>
<field_change field_name="description" type="text">
<value format="text"><![CDATA[With some content]]></value>
</field_change>
<field_change field_name="product" type="list" bind="static">
<value format="id">7675</value>
</field_change>
<field_change field_name="status" type="list" bind="static">
<value format="id">7678</value>
</field_change>
</changeset>
<changeset>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:46+01:00</submitted_on>
<comments>
<comment>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:46+01:00</submitted_on>
<body format="text"><![CDATA[Some work done]]></body>
</comment>
</comments>
<field_change field_name="status" type="list" bind="static">
<value format="id">7680</value>
</field_change>
</changeset>
</artifact>
<artifact id="446">
<changeset>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:19+01:00</submitted_on>
<comments/>
<field_change field_name="title" type="string">
<value><![CDATA[A demo bug (2)]]></value>
</field_change>
<field_change field_name="description" type="text">
<value format="text"><![CDATA[With some content]]></value>
</field_change>
<field_change field_name="product" type="list" bind="static">
<value format="id">7675</value>
</field_change>
<field_change field_name="status" type="list" bind="static">
<value format="id">7678</value>
</field_change>
</changeset>
<changeset>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:46+01:00</submitted_on>
<comments>
<comment>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:46+01:00</submitted_on>
<body format="text"><![CDATA[Some work done]]></body>
</comment>
</comments>
<field_change field_name="Artifact Links" type="art_link">
<value nature="reported_in">1234</value>
<value nature="_is_child">12</value>
<value>42</value>
</field_change>
<field_change field_name="status" type="list" bind="static">
<value format="id">7680</value>
</field_change>
</changeset>
</artifact>
</artifacts>
</tracker>
</trackers>
</project>
|
Artifact link types¶
When importing a project that uses custom artifact link types (aka. natures), you should check that the target Tuleap platform has the same artifact link types by adding a <natures>
node.
The XML importer will check that all artifact link types defined in this node exist on the target platform. If one or more types don’t exist, it will stop the import safely before anything is imported.
In addition, the children <nature>
tags will allow the user to define if this type is used or not in the target project:
- if
is_used="0"
, the type will be disabled in project - if
is_used="1"
or is_used is missing, the type will be used in the project.
<trackers use-natures="true">
...
</trackers>
<natures>
<nature>my_custom_nature_shortname</nature>
<nature is_used="0">my_custom_nature_shortname2</nature>
</natures>
Attention
You must set the use-natures
attribute to false
on trackers to not use the typed artifact links.
Since Tuleap 9.14, trackers now use by default the typed artifact links.
Folders¶
If you have existing folders you want to keep at import, you have to define the tracker which will be flagged as folder with the attribute “is_folder”.
To import your artifacts with link “In folder”, the system nature _in_folder will be used.
<?xml version="1.0" encoding="UTF-8"?>
<project>
<services>
<service shortname="plugin_tracker" enabled="true" />
...
</services>
...
<trackers use-natures="true">
<tracker id="T239" parent_id="0" instantiate_for_new_projects="1" is_folder="true">
<name><![CDATA[Simple Tracker]]></name>
<item_name>simple</item_name>
<description><![CDATA[simple tracker example]]></description>
<color>inca_silver</color>
<cannedResponses/>
<formElements>
<formElement type="computed" ID="F123" rank="97">
<name>computed_field_name</name>
<label><![CDATA[Computed_Field_Label]]></label>
</formElement>
</formElements>
...
<artifacts>
<artifact id="445">
<changeset>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:19+01:00</submitted_on>
<comments/>
<field_change field_name="Artifact Links" type="art_link">
<value nature="_in_folder">12</value>
</field_change>
</changeset>
...
</artifact>
</artifacts>
</tracker>
</trackers>
</project>
Computed field import¶
The new computed field can have have manual or autocomputed values. The <manual_value> node enable to keep the manual value for the field, the <is_autocompute> node keeps the field in autocompute mode.
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 | <?xml version="1.0" encoding="UTF-8"?>
<project>
<services>
<service shortname="plugin_tracker" enabled="true" />
...
</services>
...
<trackers use-natures="true">
<tracker id="T239" parent_id="0" instantiate_for_new_projects="1">
<name><![CDATA[Simple Tracker]]></name>
<item_name>simple</item_name>
<description><![CDATA[simple tracker example]]></description>
<color>inca_silver</color>
<cannedResponses/>
<formElements>
<formElement type="computed" ID="F123" rank="97">
<name>computed_field_name</name>
<label><![CDATA[Computed_Field_Label]]></label>
</formElement>
</formElements>
...
<artifacts>
<artifact id="445">
<changeset>
<submitted_by format="username">vaceletm</submitted_by>
<submitted_on format="ISO8601">2015-11-10T09:05:19+01:00</submitted_on>
<comments/>
<field_change field_name="computed_field_name" type="computed">
<manual_value><![CDATA[11]]></manual_value>
</field_change>
<field_change field_name="computed_field_name" type="computed">
<is_autocomputed>1</is_autocomputed>
</field_change>
</changeset>
...
</artifact>
</artifacts>
</tracker>
</trackers>
</project>
|
Permissions¶
In the previous example, you can see a block for permissions management at the end
<permissions>
<permission scope="tracker" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_ACCESS_FULL"/>
<permission scope="field" REF="F6683" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6684" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6677" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6677" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6677" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6678" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6678" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6678" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6679" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6679" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6679" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
<permission scope="field" REF="F6680" ugroup="UGROUP_ANONYMOUS" type="PLUGIN_TRACKER_FIELD_READ"/>
<permission scope="field" REF="F6680" ugroup="UGROUP_REGISTERED" type="PLUGIN_TRACKER_FIELD_SUBMIT"/>
<permission scope="field" REF="F6680" ugroup="UGROUP_PROJECT_MEMBERS" type="PLUGIN_TRACKER_FIELD_UPDATE"/>
</permissions>
There are 2 scopes for permissions:
- tracker
- field
Fore each we have the same type of attributes:
- REF reference a field defined in tracker structure
- ugroup is one group that have the given type of permission
- type is the access right granted (depend of the scope)
Supported ugroup values:
- UGROUP_ANONYMOUS
- UGROUP_REGISTERED
- UGROUP_PROJECT_MEMBERS
- UGROUP_PROJECT_ADMIN
- Any custom ugroup name
If several ugroups should have the same permission, there should be several lines
Supported type value for tracker scope:
- PLUGIN_TRACKER_ADMIN grant tracker administration capabilities to group
- PLUGIN_TRACKER_ACCESS_FULL grant access to tracker to group
- PLUGIN_TRACKER_ACCESS_ASSIGNEE grant access to all artifacts assigned to people of the group (eg. Alice and Bob belong to “project_members”, Astrid belong to “project admin”. Alice will see all artifacts assigned to herself or assigned to bob but not those assigned to Astrid)
- PLUGIN_TRACKER_ACCESS_SUBMITTER grant access to all artifacts submitted by people from the group (see previous example but with “submitted by” instead of “assigned to”)
- PLUGIN_TRACKER_ACCESS_SUBMITTER_ONLY, for this group people see only the artifacts they submitted (eg. HelpDesk).
Supported type for field scope:
- PLUGIN_TRACKER_FIELD_READ ugroup can see the field content
- PLUGIN_TRACKER_FIELD_SUBMIT ugroup can set value for the field at artifact creation
- PLUGIN_TRACKER_FIELD_UPDATE ugroup can upgrade the field value after creation
Agile Dashboard¶
You can import agiledashboard configuration. There are no data related to agiledashboard itself. The data are in the trackers.
<agiledashboard>
<plannings>
<planning name="Release Planning" plan_title="Release Plan" planning_tracker_id="T1017" backlog_title="Product Backlog">
<backlogs>
<backlog>T1015</backlog>
<backlog>T1020</backlog>
</backlogs>
</planning>
<planning name="Sprint Planning" plan_title="Sprint Plan" planning_tracker_id="T1018" backlog_title="Epic Backlog">
<backlogs>
<backlog>T1015</backlog>
<backlog>T1020</backlog>
</backlogs>
</planning>
</plannings>
<kanban_list title="Kanban">
<kanban tracker_id="T778" name="My personal kanban" ID="K01">
<column wip="1" REF="V9297"/>
...
</kanban>
</kanban_list>
</agiledashboard>
Subversion repositories¶
You can import as many SVN repositories as you want. The XML syntax is:
<project>
<services>
<service shortname="plugin_svn" enabled="true" />
...
</services>
...
<svn>
<repository name="repo-name" dump-file="data/repository.dump">
<!-- Access Rights -->
<access-file><![CDATA[
# Content of the .SVNAccessFile
]]></access-file>
<!-- E-mail subscriptions -->
<notification path="/trunk" emails="project-svn@list.example.com"/>
<notification path="/tags" emails="project-announce@list.example.com, project-devel@lists.example.com"/>
...
</repository>
...
</svn>
...
</project>
- A single
<svn/>
tag containing: - A
<repository/>
tag per repository containing: - The attribute
name
which contains the repository name. It is required. A good default choice is to use the project unix name. - The attribute
dump-file
which references a dump file generated bysvnadmin dump
- The tag
<access-file>
containing the.SVNAccessFile
inline <notification/>
tags, one for each monitored path. E-mails are separated by commas.
Git repositories¶
Multiple Git repositories can be imported. The XML syntax is:
<project>
<services>
<service shortname="plugin_git" enabled="true" />
...
</services>
...
<git>
<ugroups-admin>
<ugroup>Contributors</ugroup>
...
</ugroups-admin>
<repository bundle-path="tuleap_dev_bundle" name="dev/tuleap" description="Development git repository for tuleap">
<read>
<ugroup>project_members</ugroup>
...
</read>
<write>
<ugroup>Contributors</ugroup>
...
</write>
<wplus>
<ugroup>project_admins</ugroup>
...
</wplus>
</repository>
<repository bundle-path="tuleap_stable_bundle" name="stable/tuleap" description="Frozen git repository for tuleap, contains only tags.">
...
</repository>
...
</git>
...
</project>
- A single
<git/>
tag containing: - An optional
<ugroups-admin>
tag containing: - One or more
<ugroup>
containing the ugroup name. Note that the project administrators ugroup will always be part of the git administrators. - One or more
<repository>
tag containing: - The attribute
bundle-path
which references a bundle file generated bygit bundle create <name_of_bundle> --all
- The attribute
name
to specify the name of the repository. Note that it accepts a “path” notation (see the repository list in the git plugin) - The attribute
description
containing the description of the repository - The tag
<read|write|wplus>
containing one or multiple<ugroup>
tags. It allows to give the different permissions of the repository to the given repository. The<ugroup>
tag must contain only one ugroup name.
Attention
Git service does not export forked repositories.
Another synthax exists for the git XML import:
<project>
<services>
<service shortname="plugin_git" enabled="true" />
...
</services>
...
<git>
<ugroups-admin>
<ugroup>Contributors</ugroup>
...
</ugroups-admin>
<repository bundle-path="tuleap_dev_bundle" name="dev/tuleap" description="Development git repository for tuleap">
<permissions>
<read>
<ugroup>project_members</ugroup>
...
</read>
<write>
<ugroup>Contributors</ugroup>
...
</write>
<wplus>
<ugroup>project_admins</ugroup>
...
</wplus>
<fine_grained enabled="1" use_regexp="1">
<pattern value="*" type="branch">
<write>
<ugroup>Contributors</ugroup>
...
</write>
<wplus>
<ugroup>project_admins</ugroup>
...
</wplus>
</pattern>
<pattern value="*" type="tag">
<write>
<ugroup>Contributors</ugroup>
...
</write>
<wplus>
<ugroup>project_admins</ugroup>
...
</wplus>
</pattern>
</fine_grained>
</permissions>
</repository>
<repository bundle-path="tuleap_stable_bundle" name="stable/tuleap" description="Frozen git repository for tuleap, contains only tags.">
...
</repository>
...
</git>
...
</project>
The big change is in the <repository>
tag:
- The tag
<permissions>
containing<read|write|wplus>
and an optional tag named<fine_grained>
- The tag
<read|write|wplus>
containing one or multiple<ugroup>
tags. It allows to give the different permissions of the repository to the given repository. The<ugroup>
tag must contain only one ugroup name. - The tag
<fine_grained>
containing one or multiple<pattern>
tag. - The attribute
enabled
which defines if this permission option is used for the repository or not - The attribute
use_regexp
which defines if patterns with regexp are authorized or not - The tag
<pattern>
containing<write|wplus>
tags. - The attribute
value
which defines the gitolite path checked by the pattern - The attribute
type
which defines if this permission is a branch or a tag permission. The possible values aretag
andbranch
Releases and Files (FRS)¶
The released files (FRS) can be imported, the XML syntax is:
<project>
<services>
<service shortname="file" enabled="true" />
...
</services>
...
<frs>
<package
id="12"
name="package1"
rank="1"
hidden="false">
<read-access>
<ugroup>project_members</ugroup>
...
</read-access>
<release
id="30"
name="release"
time="2015-12-03T14:55:00"
preformatted="false"
artifact_id="101">
<read-access>
<ugroup>project_members</ugroup>
...
</read-access>
<notes>some notes</notes>
<changes>some changes</changes>
<user format="username">alice</user>
<file
src="data/foobar"
md5sum="9db014ab2eb1df99a730c092a757782b"
name="lefichier-foobar"
release-time="2015-12-03T16:46:00"
post-date="2015-12-03T16:46:00"
arch="x86_64"
filetype="text">
<description>one file to rule them all</description>
<user format="username">alice</user>
</file>
<link name="test" url="http://example.com" release-time="2016-07-19T10:38:19+01:00">
<user format="username">alice</user>
</link>
...
</release>
...
</package>
...
</frs>
...
</project>
The XML must contain a single <frs/>
element containing zero or more packages. The packages can contain zero or more releases, which can contain zero or more files.
A package is constructed using a <package/>
XML element containing:
- A
name
attribute - A
rank
optional integer attribute - A
hidden
optional boolean attribute - A single
<read-access/>
element containing the access definitions. - A
<release/>
element per releease.
A release is constructed using a <release/>
XML element containing:
- A
name
attribute - A
time
attribute containing the ISO-8601 representation of the release date. - A
preformatted
attribute containing a boolean that indicates if the release notes and changelog are preformatted. - An
artifact_id
attribute referencing an artifact that must be present in the XML content. The FRS plugin must be installed to take into account the value. - A single
<read-access/>
element containing the access definitions. - A single
<notes/>
element containing the release notes - A single
<changes/>
element containing the changelog - A single
<user>
element describing the user who made the release - A
<file/>
element per file contained in the release
A file is constructed using a <file/>
XML element containing:
- A
src
attribute pointing to the file to import (relative to the XML file) - A
md5sum
attribute containing the MD5 hash of the file (checked on import, optional) - A
name
attribute: the file name (optional) - A
release-time
attribute: the ISO-8601 representation of the time when the file was released (optional, current time used if not provided) - A
post-date
attribute encoded in ISO-8601 (optional, current time used if not provided) - An
arch
attribute: the name of the architecture of the file as appearing in the tablefrs_processor
. On a fresh install, the processor list isi386
,x86_64
,PPC
,MIPS
,Sparc
,UltraSparc
,IA64
,Alpha
,Any
,Other
. - A
filetype
attribute: the name of the file type of the file as appearing in the columnfrs_filetype
. On a fresh install, the file types available areBinary .rpm
,Binary .deb
,Binary .zip
,Binary .bz2
,Binary .gz
,Binary .tar.gz, .tgz
,Binary .jar
,Binary installer
,Other Binary File
,Source .rpm
,Source .zip
,Source .bz2
,Source .gz
,Source .tar.gz, .tgz
,Other Source File
,.Documentation (any format)
,text
,html
,pdf
,Other
. - An optional
<description/>
element containing a file description - An optional
<user/>
element describing the user who posted the file
Access definitions consists of zero to many <ugroup/>
tags, each containing the name of the user group that is allowed access.
Mediawiki¶
The Mediawiki can also be imported. For the moment only pages import is supported.
The XML syntax is:
<mediawiki pages-backup="wiki_pages.xml" language="fr_FR" files-folder-backup="files">
<read-access>
<ugroup>project_members</ugroup>
</read-access>
<write-access>
<ugroup>project_admins</ugroup>
</write-access>
</mediawiki>
language
is the language of the wiki. Currently only en_EN
and fr_FR
are supported.
pages-backup
is the path to the wiki pages backup done with the dumpBackup.php
maintenance script provided by the Mediawiki project.
files-folder-backup
is the path to the directory where the files to upload are stored into.
All the files must be stored at the root of the folder.
read-access
and write-access
must contain ugroup
tags with ugroup names.
At the moment, you should use the script located at
$TULEAP_ROOT/plugins/mediawiki/bin/mw-maintenance-wrapper.php
to export the pages of a tuleap Mediawiki .
For example, to export the mediawiki of the project named “toto”
use $TULEAP_ROOT/plugins/mediawiki/bin/mw-maintenance-wrapper.php toto dumpBackup.php --full
.
The schema is available here : mediawiki schema.
References¶
If you have existing references you want to keep at import, you can define them, services by services.
Supported references:
- artfXXX for artifacts
- pkgXXX for packages
- relXXX for releases
- wikiXXX for wiki pages
- cmmtXXX for git or svn commits
Note
You need to install and activate the following packages to make it works:
- referencealias_core
- referencealias_git
- referencealias_mediawiki
- referencealias_svn
- referencealias_tracker
Note
When you import serveral times the same project (for test purpose for instance) it can be convenient to have the references that points to the last version of the import.
To do so you can use the –force=references switch on the import command line.
Example of references:
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 | <?xml version="1.0" encoding="UTF-8"?>
<project>
<trackers>
<tracker>
...
<artifact id="469">...</artifact>
</tracker>
<tracker>
<artifact id="470">...</artifact>
...
</tracker>
<references>
<reference source="artf469" target="469" />
<reference source="artf470" target="470" />
</references>
</trackers>
<svn>
<repository>
...
<references>
<reference source="cmmt64324" target="1" />
<reference source="cmmt64372" target="2" />
</references>
</repository>
</svn>
<git>
<repository bundle-path="data/g1" name="arch/x6_64" description="stuff">
<references>
<reference source="cmmt332" target="4caed3441095c01882867e3d302fbab66584087a" />
<reference source="cmmt333" target="606e4b15e7ac6cdbb036010cce201de3421423f0" />
</references>
</repository>
</git>
<frs>
<package id="10012" name="My package">...</package>
<package id="10013" name="My other package">
<release id="2345">...</release>
</package>
<references>
<reference source="pkg23" target="10012" />
<reference source="pkg75" target="10013" />
<reference source="rel465" target="2345" />
</references>
</frs>
<mediawiki pages-backup="wiki_pages.xml" language="fr_FR">
<references>
<reference source="wiki76532" target="Accueil" />
</references>
</mediawiki>
</project>
|