Command line interface¶
Added in version 9.0.0.
Install momotor-bundles to use the standalone commands. The same commands are
available through python -m momotor.bundles. Use them when you want to
build a bundle, update its metadata, or sign and verify it without writing
Python code. Commands that write a bundle (build, update-meta, and
sign) print the path they wrote. The verify and
inspect-signatures commands write nothing. They print a report instead,
with the verdict printed last for verify.
Build a bundle¶
Build the bundle in the current directory:
momotor-bundles build
Use a development directory, XML file, or ZIP bundle as the source:
momotor-bundles build path/to/recipe
momotor-bundles build path/to/config.xml
momotor-bundles build path/to/product.zip
The existing bundle reader loads the source. The writer collects referenced
attachments and local repository directories. The output is ZIP when the bundle
has attachments or --zip is set. Otherwise, the output is XML. Builds use the
library’s generator option to include the library generator in root metadata.
Self-test reports support the same metadata and filename rules as other bundles.
The generated filename is <name>-<bundle-type>-<version>.xml or .zip.
The name comes from root metadata, then the bundle ID, then the bundle type.
The version suffix is omitted when metadata has no version. Name and version
components are sanitized for portable filenames.
By default, the command writes to the current working directory. Use
--output-dir to keep the generated filename in another directory. Use
--output to supply an exact filename, regardless of the output format:
momotor-bundles build --output-dir dist
momotor-bundles build recipe.xml --output release/recipe-bundle.zip --zip
--output and --output-dir are mutually exclusive. Missing destination
directories are created. Builds cannot overwrite the source XML or archive.
For directory and ZIP sources with a custom XML filename, use
--input-xml-name. Use --xml-name to change the XML member in the generated
ZIP:
momotor-bundles build source.zip --input-xml-name original.xml --xml-name recipe.xml
Construction options¶
The command preserves the defaults and validation of
FileConstructionArguments.
These boolean options accept both positive and negative forms, such as
--sign-files and --no-sign-files:
--pretty-xml--sign-files--optimize--deduplicate--deduplicate-attachments--zip--always-recompress
The remaining options accept values:
Option |
Value |
|---|---|
|
Attachment namespace path. |
|
XML encoding, such as |
|
Generated ZIP’s XML member name. |
|
One or more algorithm names, such as |
|
|
|
Integer compression level accepted by the selected compression method. |
--deduplicate-attachments requires --deduplicate. Directory output,
dir_mode, the deprecated use_lxml argument, and generator overrides are
not exposed by build.
Update metadata¶
Update root metadata in an XML file or ZIP bundle:
momotor-bundles update-meta recipe.xml --version 2.1
momotor-bundles update-meta recipe.zip --author 'First author' --author 'Second author'
Without output options, the input is updated in place. --output-dir uses the
input’s filename, including its extension. --output uses the exact supplied
filename. A destination resolving to the input also performs an in-place update:
momotor-bundles update-meta recipe.zip --version 2.1 --output-dir dist
momotor-bundles update-meta recipe.xml --name 'Release recipe' --output release/recipe.xml
At least one metadata operation is required. --name and --version accept
one value each. --author, --source, --description, and --generator
can be repeated. Each supplied option replaces that field’s values across all
direct root <meta> blocks. The replacement values go into the first block.
A root metadata block is created when needed. Nested metadata is left untouched.
Omitted fields remain unchanged.
An empty string removes a field. Repeated options cannot mix empty and nonempty values. Replacement descriptions contain plain text without language or markup attributes:
momotor-bundles update-meta recipe.xml --source '' --description 'Release recipe'
Generators are preserved unless --generator replaces or removes them.
--generator-name appends the library generator. With a name, it appends
NAME (momotor-bundles VERSION). Existing identical generator values are not
added again. --generator and --generator-name are mutually exclusive:
momotor-bundles update-meta recipe.zip --generator-name
momotor-bundles update-meta recipe.zip --generator-name 'release pipeline'
momotor-bundles update-meta recipe.zip --generator ''
For ZIP input, the command selects the single root XML member containing a
Momotor bundle. Only the defined default bundle XML names at the ZIP root
are candidates. Selection precedes XML parsing, and more than one candidate
is always an error. Select an exact member name with
--input-xml-name:
momotor-bundles update-meta bundles.zip --input-xml-name recipe.xml --version 2.1
Metadata updates use lxml without expanding XInclude or applying stylesheets. Comments, processing instructions, namespaces, whitespace, and untouched descriptions are preserved. XML serialization can change the document’s byte representation. Other ZIP members retain their compressed payloads and member metadata. Archive comments are preserved.
Both commands write to a temporary sibling file and replace the destination only after success. Failed writes leave existing files intact. Replacement preserves existing destination permissions. New build files follow the process umask. New metadata copies inherit the input’s permissions. Each successful command prints the completed output path.
CI examples¶
Build a recipe from its development directory and store it as a CI artifact:
build-bundle:
script:
- pip install momotor-bundles
- momotor-bundles build --output-dir dist
artifacts:
paths:
- dist/
Update an existing bundle’s version before publishing it:
momotor-bundles update-meta recipe.zip --version "$CI_COMMIT_TAG" --generator-name 'release pipeline'
To retain the original bundle, add --output-dir dist or an exact --output
path. These commands can be adopted independently of recipe CI migration.
Public-key signing and verification¶
Added in version 9.0.0.
See Create a keypair for compatible OpenSSL commands.
Install momotor-bundles[signing] for cryptographic operations. Private-key
passwords are read with a terminal prompt, never an argument:
momotor-bundles sign recipe.zip --private-key author.pem --output signed.zip
momotor-bundles sign signed.zip --private-key release.pem --mode add
momotor-bundles verify signed.zip --trusted-key author.pub.pem --policy any --json
momotor-bundles verify signed.zip --trusted-key author.pub.pem --policy all-present
momotor-bundles inspect-signatures signed.zip
Repeat --private-key, --trusted-key and --require-signer KEY_ID as
needed. Verification uses only caller-supplied public keys. all-present
requires every present record to be trusted and valid. any requires at least
one; required signer IDs add independent mandatory signers. Inspection is
explicitly unauthenticated. See Bundle verification for the complete trust model.
All three commands accept standalone XML files, ZIP files and directories.
--input-xml-name selects the XML file or member; --xml-name is an alias
on these commands. Selection is strict and ambiguous candidates are refused.
Sign updates the input by default; --output or --output-dir selects a
new destination. Directory signing in place updates only the selected XML:
momotor-bundles sign recipe-directory --private-key author.pem
momotor-bundles verify recipe-directory --trusted-key author.pub.pem
momotor-bundles build recipe-directory --private-key author.pem --output signed.zip
build --private-key signs the fully serialized output, including every
referenced attachment, even with --no-sign-files. Signed directory exports
require a new destination; direct in-place signing is supported.
update-meta refuses signed inputs unless both a matching public and private
key are supplied:
momotor-bundles update-meta recipe.xml --version 2.1 \
--trusted-key author.pub.pem --private-key author.pem
This operation verifies the supplied signer as mandatory under ANY, edits the captured document, discards old signatures and signs with the supplied key. Other unknown co-signers do not defeat ANY. Public-only, private-only, mismatched keys and invalid required signatures are refused before publication. There is no implicit signature-removal mode.
Verification exits with 0 for VERIFIED, 1 for FAILED, 2 for usage or operational
errors and 3 for UNSIGNED. Successful signing and building exit with 0.
--json emits the structured report. Unreferenced files are never claimed as
authenticated. Missing signing dependencies are operational errors, not UNSIGNED.