Validating a package before publishing
This page is for developers and reviewers who check a site package before it is published. A version on the package server is used by every installation that reads its index, so a broken package fails for everyone at once. Each check below catches something the others miss; run them in this order, from the cheapest to the one that needs a test installation.
Contents
- The checks at a glance
- Check the definition with xmllint
- Look inside the archive
- Run ezpm validate
- Upload it to a test installation
- The Validate button
- What no check covers
- Related pages
The checks at a glance
| Check | Needs | Catches |
|---|---|---|
xmllint --noout package.xml | Nothing but the file | XML that is not well formed |
tar -tzf and find -type l | The archive and the source folder | Wrong layout, links, files that should not be there |
php ezpm.php validate | An Exponential installation, from the shell | The definition as the kernel reads it, the name, missing documents |
Upload on package/upload | A test installation and the package/import policy | Everything the upload inspector checks |
| A fresh install | A sandbox | Dependencies, install scripts, the site itself |
Check the definition with xmllint
xmllint --noout packages/example_site/package.xml && echo well-formedNo output from xmllint means the document is well formed. All 16 package.xml files of the two 7x source
repositories and the 6.0.15 index.xml pass this check (2026-10-18). It says nothing about the content: an empty
<name> is well formed.
Look inside the archive
tar -tzf example_site.ezpkg | head -20
find packages/example_site -type lWhat to see, and why:
- To do:
package.xmlas the plain entrypackage.xml, not inside a folder: the import looks for an entry of exactly that name (eZPackage::importUnaudited()).packages/build.shrunstarfrom inside each package folder over*, which gives this layout. - To do: Only the directories the package uses:
documents/,files/,settings/,simplefiles/and the sub-directories of its install items (ezcontentclass/,ezcontentobject/,ezextension/). - To do: No
.git,.DS_Store, editor backups ornode_modules:build.shleaves them out with itsEXCLUDESlist. - To do:
find -type lprints nothing. A link to a file of the package is imported as a copy of it, but a link out of the package, to a directory or to nothing, a device or a fifo is left out with a notice (link_outside,link_directory,link_missing,special_file), so what the package needs is missing; an entry with..or an absolute path makes every import refuse the package (unsafe_path).
Warning
Files at the top of a package next to package.xml survive build.sh, which archives the whole folder, but not
an export from the administration or ezpm.php export: eZPackage::exportToArchive() copies only the definition,
documents/, files/, simplefiles/, settings/ and the install items' sub-directories.
cjw_multisite_democontent keeps four files at its top (cjw-class-additions.xml, cjw-explayouts.json,
cjw-paths.json, cjw-starter-import.json), so it must be rebuilt from its source folder, never re-exported.
Run ezpm validate
ezpm.php at the project root has a validate command (kernel/private/classes/commands/ezpm.php). It takes an
archive, a package directory or the name of an imported package, and imports nothing:
php ezpm.php validate var/tmp/example_site.ezpkg
php ezpm.php validate packages/example_site
php ezpm.php help validateIt runs expPackageJson::validateDirectory() (kernel/classes/exppackagejson.php), which checks:
- that there is a
package.xmlorpackage.json; - every document as XML, and in the JSON format against
share/package/schema/package-v1.jsonand the SHA-256 checksums ofpackage.json; - the definition as the kernel reads it (
eZPackage::parseDOMTree()): a name, plain version and type tokens; - the name with
eZPackage::isValidName(); - that every document an install item names (
<sub-directory>/<filename>.xml, and the object files of content items) is in the package.
It ends with PASS <name> (xml): N documents, M files, or prints one error line per problem and
FAIL <source>: N error(s) with exit code 1, so it can stop a build script. An archive is extracted into a private
work directory first, refusing unsafe entries the same way an import does, and the directory is removed afterwards.
Note
validate does not run the upload inspector's checks of the file name, the gzip signature, the size limits or
the <ezpublish> and <packaging> elements. The upload below does.
Upload it to a test installation
package/upload in the administration is the strictest door
(Packages guide, uploading). Before anything is extracted,
eZPackageUploadInspector::inspect() checks, in this order: a file was sent; its name ends in an allowed suffix;
it is not larger than MaxArchiveSize; it starts with the gzip signature; every entry is safe and within
MaxEntries and MaxUnpackedSize; there is a package.xml or package.json at the top, at most 16 MiB; the
definition has a <package> root without DOCTYPE, a valid name, <ezpublish>, <packaging> and a usable vendor.
Then it runs the same validateDirectory() as ezpm.php validate and shows the first 20 errors.
The messages are the ones in eZPackageUploadInspector::message(), such as "The package.xml of the archive lacks
its version or packaging information". The limits are in settings/package.ini [UploadSettings].
Use a test installation: an upload imports the package for real, and the same name cannot be imported twice. To try again, remove the package on its page first.
The Validate button
An imported package's page (package/view/full/<name>) has a Validate button. It runs validateDirectory() on
the package as it lies in the repository and shows the result on the page until the next action on the package. It
is the quickest way to check a package that was imported by the setup wizard, which does not validate.
What no check covers
None of the checks above reads the meaning of a package. These are left to a test install and to review:
- whether every
<require>can be found and is new enough (Declaring dependencies); - whether every
<settings-file>exists (a missing one is skipped silently by the create sites step); - whether the install scripts run on the database engines you support;
- whether the
md5sumattributes match their files; - whether the license, the changelog and the thumbnail are there and right.
Run a full install in a sandbox before publishing: Testing in a sandbox.
Related pages
- Documentation requirements for site packages
- The requirements checklist
- Required package.xml fields
- Rebuilding with build.sh
- ezpm: the package manager on the command line
- The JSON package format
- Site packages: start here
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.