The Updater for xTuple ERP is an application that helps you update your PostBooks databases from one release to the next, to upgrade from one xTuple ERP edition to another, such as from PostBooks to Manufacturing Edition, and to load extensions developed by third parties into your xTuple database. The Updater reads and processes upgrade scripts or packages, which are collections of files bundled together into
.gz files. This page describes the basics of creating update packages. Additional details are provided on subsequent pages for creating extensions and core updates.
Here are some other related documents:
- If you want to know how to use the Updater to upgrade a database or install an add-on, look at UpdaterDoc
- If you are having problems running an upgrade, such as failures during the prerequisite checking, look at DebuggingUpgradeErrors
- To view extension packages currently available for xTuple ERP, visit the xChange
What is a Package?
A Package is a compressed collection of files which may contain either a) custom software designed to extend the functionality of xTuple ERP without touching the core xTuple ERP source code or b) upgrade bundles designed to migrate xTuple ERP databases from one version to the next. xTuple creates packages to upgrade databases from one release to the next and to upgrade from one edition to another, such as from PostBooks to OpenMFG. Using Packages, third-party software developers can add features without needing C++ programming skills. These features can be integrated seamlessly into xTuple ERP independent of the release cycles and source code requirements defined by xTuple. In short, Packages are flexible. They make it easy for software developers to add new features -- or even just simple tweaks -- to customize and enhance the xTuple ERP experience.
The structure of an Updater Package
At the most basic level, Updater Packages are compressed tar files. This format has been adopted as one of several standards for bundling files for distribution over the Internet.
The contents of the tar file have a fairly uniform structure. At the top level is a single directory. Inside this directory there must be a file called
package.xml. This file describes to the Updater how to load the rest of the package. The other files included in the package are either SQL scripts to run to modify the database or any of the following items to load into the database:
- user interface forms
- application scripts
- report definitions
- MetaSQL statements
These may all be directly in the top level directory of the package or arranged in subdirectories. For example, the fixCountry extension is structured like this:
resources + package.xml + client + scripts + bulkFixCountry.js | | + fixCountries.js | | + initMenu.js | | | + ui + bulkFixCountry.ui | + fixCountries.ui | + database + metasql + fixcountry_strictcountrycheck.mql
and the reencrypt extension is even simpler:
reencrypt + package.xml + alterencrypt.sql + configureEncryption.js + reencrypt.js + reencrypt.ui
Getting started building an Updater Package
The first thing you need to do when building an Updater package is to create a directory:
$ mkdir sampledir
Everything that you want to include in this package should eventually be put into this directory. The first thing you should put in this directory is a
package.xml file. Building a package is an iterative process of adding files to the directory, modifying
package.xml, bundling everything together, and testing. So don't worry yet about having all of the pieces together.
The package.xml file contains the information required to orchestrate a database upgrade or package addition to an xTuple database. The syntax is described in full on the Package Syntax page. The file is, as its name suggests, an XML file. The root element must be
<package>. Attributes of the
<package> element name the package, provide a consistency check with the package's top-level directory, and let the creator specify a minimum Updater version to use when loading the package:
<package id="sampledir" name="samplepackage" version="1.0alpha" developer="xTuple" descrip="Sample described on the Create Updater Packages page." updater="2.2.0beta2"> <pkgnotes> This is an example for the page describing the packaging functionality in xTuple ERP's Updater utility. </pkgnotes> ... </package>
In order of appearance, here's what this all means:
idattribute says that the contents of this package all come from a directory named sampledir.
- By providing a
name, the author is telling the Updater that this is an extension package, rather than an update to the core xTuple ERP application. The package will be stored with the name
versionindicates this is an alpha release of the first version of this package.
- This package was developed by the company
- If this is an extension package, the
descripwill be displayed on the Packages and Package windows in xTuple ERP.
- This package cannot be loaded by any version of the Updater before
2.2.0Beta2. This means that this package cannot be loaded by Updater 1.0, 1.1, or even 2.0.0beta. It can be loaded by Updater 2.2.0, 2.2.1ALPHA, or 3.2.7.
<pkgnotes>are stored as comments for extensions and are visible on the Package window in the xTuple ERP application.
updater attributes of the
<package> element allow for simplistic consistency checking:
- Does this package contain the expected directory and are you running a version of the Updater that can load this package. This is rarely sufficient for loading a package of any real complexity.
The Updater lets you provide database queries to make more interesting checks. xTuple uses these
query prerequisites extensively in upgrade packages to confirm that the starting database version for the upgrade matches expectations and to check for data that need to be fixed before the upgrade will be successful. The sole criterion for writing a correct prerequisite query is that it return an SQL boolean
TRUE value if it is safe for the Updater to load this package.
Here is an example:
<prerequisite type="query" name="Checking if xtbatch is installed" > <query>SELECT COUNT(*) = 1 FROM pkghead WHERE pkghead_name = 'xtbatch';</query> <message> This package must be applied to an xTuple ERP database with the xTuple Connect extension installed. </message> </prerequisite>
typeattributes says that this
<prerequisite>element is a database query.
- Before the Updater runs the statement in the
<query>element it writes the value of the
"Checking if xtbatch is installed", to the Updater's message window.
<query>element then gets run, checking to see if this is an xTuple database with the
xtbatchpackage. If the database is a basic PostBooks database (
xtbatchis not part of the basic PostBooks installation), or if the database does not have a
pkgheadtable (therefore not an xTuple ERP database), then the prerequisite check will fail.
- If the query fails then the contents of the
<message>element will be written to the Updater's message window, probably in red type.
All of the prerequisites are checked before the Updater returns from this phase of processing. This lets the user learn about all of the problems that s/he must fix before trying to run the Updater again to load this package.
This also imposes an obligation on the package developer: Create prerequisite checks for any database modifications that might lead to upgrade or installation failures.
There is also a
license prerequisite, which allows the package developer to present the user with an end-user license agreement. The user must click an Accept button before the Updater will allow the package to be installed. This license is not written anywhere by the Updater. The license text in the
<message> element may contain rich text, as defined by Qt:
<prerequisite type="license" name="sampleLicense" > <message> <p>This is the content of a <i>rich text</i> license. <hr /> You must either accept or not.</p> </message> </prerequisite>
< in several places. Because this is an XML file, the
< character used to mark the beginnings of rich text tags must be escaped so they are not treated as part of the
<package> element tree. xTuple has tested the Updater using
< substitution for
<. Using XML CDATA sections should also work but xTuple has not tested this.
Most of the work is described in external files
Now that the preliminaries have been dispensed with, how do we actually load things into the database? For the most part by creating small files that do (or contain) just one thing.
You can create arbitrary database scripts. If you have several changes that you want to make to the database that are all related, they should go in a single script file. If there are several unrelated changes, create several different files. Put these script files into the package directory and add a line to
package.xml for each:
<script file="runFirst.sql" /> <script file="runSecond.sql"/>
The Updater has several different elements for specific kinds of database object. These can be used for either update or extension packages; the syntax was specifically designed to support the bookkeeping necessary for extensions but may also be used in database upgrade or xTuple ERP edition upgrade packages. Put a script file for each of the following sample lines into the package directory:
<createtable file="pkgtest.sql" name="pkgtest" /> <createfunction file="pkgtesttriggerfunction.sql" name="_pkgtestbefore" /> <createtrigger file="pkgtesttrigger.sql" name="pkgtestbefore" /> <createview file="pkgtestview.sql" name="pkgtestview" />
The Updater will run all four of these scripts. The
> elements are run in the order they appear in the file grouped by type to minimize conflicts. In general use
> because the Updater will automatically do the proper bookkeeping for storing extensions as a unit in the database and reporting the extension contents accurately. If this default order does not work, you must use
<finalscript> elements to force a sequence that does work. The actual sequence in which elements are run is described here.
The Updater also has different elements for xTuple ERP objects. These are stored in special tables used by the xTuple ERP database. The files used for the following elements are not database scripts. Instead they hold the actual objects themselves.
<loadmetasql file="sampleQuery.mql" /> <loadreport file="sampleReport.xml" /> <loadappscript file="sampleScreen.js" name="sampleScreen" /> <loadappui file="sampleScreen.ui" /> <loadimage file="sampleImage.png" name="aPicture" />
- Read a MetaSQL statement from the file
sampleQuery.mqland save it in the database. See the Special notes on MetaSQL definitions for more information.
- Read an OpenRPT report definition from the file
sampleReport.xmland save it in the database.
- Read an application script from
sampleScreen.jsand save it in the database with the name
sampleScreen. This name allows it to work nicely with the next item in the package.
- Read an application user interface definition from
sampleScreen.uiand save it in the database.
- Read an image from the file
sampleImage.pngand save it in the database as an image with the application-level name
If you have a complex package with more than a handful of files, you'll probably want to create a small directory structure to organize the files. We recommend the structure described on the page describing xTuple Desktop Extensions. Each
file attribute will need to hold the directory path to the file, not just the simple file name. For example, if you put all of your report definitions in a reports subdirectory, the
loadreport line above would have to set the
A few things are described in the file itself
You could create new xTuple privileges and custom commands using
<script> elements. However, these things are so simple and so common in xTuple ERP that the Updater has direct support for creating them without SQL scripts.
To create a new privilege:
<loadpriv name="ViewSampleScreen" module="System"> Allowed to view the sample screen </loadpriv>
This creates a privilege named
ViewSampleScreen. It can be assigned to users or groups of users by selecting
System from the Module combo box on the User Information or Group windows.
To create a new custom command:
<loadcmd name="SampleCMD" title="Sample Screen" privname="ViewSampleScreen" module="System" executable="!customuiform"> Sample Screen Custom Command Description - view mode <arg value="uiform=sampleScreen" /> <arg value="mode=view" /> </loadcmd>
This creates a new custom command in the xTuple ERP desktop client called
SampleCMD, which appears in the menu system as System > Custom Commands > Sample Screen. When the user selects this menu item, the application opens the User Interface form
sampleScreen loaded earlier, and passes it the argument
Creating the Package itself
After you have written all of the scripts,
.mql files, OpenRPT
.xml files, etc. to your package directory, you can bundle all of the pieces together with a single command:
$ tar czf packagedir.gz packagedir
If you run
tar on a Mac with an older version of OS X, the Updater may not be able to read the
.gz file. If this happens, then try the following command instead:
$ gnutar czf packagedir.gz --format gnu packagedir