Contents
Note that this document is just a draft. These aren’t official, approved Fedora guidelines.
The goal of this document is to describe how to create valid module files, document purposes of all the data fields in them, hint best practices and demonstrate some examples.
Each module is defined by a single YAML file and comprises of a number of key-value pairs describing the module’s properties and components it contains. Not everything needs to (or even should) be filled in by the module packager; some of the fields get populated later during the module build or distribution phase. The module file format is commonly known as modulemd.
The original format specification can be found in the modulemd repository.
Every modulemd file MUST contain a modulemd document header which consists of the document type tag and the document format version, and a data section holding the module data.
document: modulemd
version: 1
data:
(...)
The version is an integer and denotes the version of the metadata format the rest of the document is written in. As of now, only one officialy released version of the format exists, version 1.
Every module MUST include human-readable short summary and description. Both should be written in US English.
summary: An example module
description: >
An example long description of an example module, written just
to demonstrate the purpose of this field.
The summary is a one sentence concise description of the module and SHOULD NOT end in a period.
The description expands on this and SHOULD end in a period. Description SHOULD NOT contain installation instructions or configuration manuals.
Every module MUST contain a license section and declare a list of the module’s licenses. Note these aren’t the module’s components’ licenses.
license:
module:
- MIT
Fedora content, such as SPEC files or patches not included upstream, uses the MIT license by default, unless the component packager declares otherwise. Therefore MIT might be a reasonable default for most module authors as well.
See the module content licensing section for details on how to declare components’ licenses.
Every module SHOULD define its name, update stream and version.
name: example
stream: another-example
version: 20161109235500
Note, however, that module packagers SHOULD NOT define these values manually but rather expect the Module Build Service to do it for them, using the module’s dist-git repository name as the module name, the dist-git repository branch name as the stream name and the particular commit timestamp as the version. This simplifies module rebuilds and moving modules between branches or repositories.
Packagers MAY override this behaviour by defining these fields themselves. This behavior may change in the future.
There are currently no formal restrictions for the format of the
name
and stream
properties. The version
, however, must be an
unsigned integer.
If the module includes some RPM or non-RPM content, the packager MAY also define a list of content licenses.
license:
module:
- MIT
content:
- GPL+
- BSD
Not every module includes packages and therefore doesn’t necessarily have to include this field.
Furthermore, the content licenses list should ideally be automatically filled by module build tools rather than the module author.
Modules MAY depend on other modules. These module relationships are listed in the depepdencies section. Dependencies are expressed using module names and their stream names.
dependencies:
buildrequires:
generational-core: master
requires:
generational-core: master
So far modulemd supports two kinds of dependencies:
buildrequires
for listing build dependencies of the module, i.e.
modules that define the buildroot for building the module’s
components; this will typically be the generational-core
module,
at minimumrequires
for listing runtime dependencies of the module, i.e.
modules that need to be available on the target system for this
module to work properly; this too will typically be the
generational-core
module, at minimumEither or both of these sections may be omitted, if necessary.
Modules MAY also contain an extensible metadata block, a list of vendor-defined key-value pairs.
xmd:
user-defined-key: 42
another-user-defined-key:
- the first value of the list
- the second value of the list
Modules MAY define links referencing various upstream resources, such as community website, project documentation or upstream bug tracker.
references:
community: http://www.example.com/
documentation: http://www.example.com/docs/1.23/
tracker: http://www.example.com/bugs/
The module author MAY define lists of packages that would be installed by default, and a minimum, when the module is enabled and the particular profile is selected. Whether the packages actually get installed depends on the user’s configuration. It is possible to define a profile that doesn’t install any packages.
Profile names are arbitrary strings. There is currently one special-purpose profile name defined — default. More special-purpose profile names might be defined in the future.
The default profile lists packages that would be installed unless the user’s configuration dictates otherwise.
In the case of RPM content, the profile package lists reference binary RPM package names.
profiles:
default:
rpms:
- myapplication
- myapplication-plugins
minimal:
description: An example minimal profile installing only the myapplication package.
rpms:
- myapplication
Note
Different use cases
If the primary API component(s) of a module serve different use cases with a different set of subpackages, you should describe these use cases as different install profiles of the module.
Module API are components, symbols, files or abstract features the module explicitly declares to be its supported interface. Everything else is considered an internal detail and shouldn’t be relied on by any other module.
Every module SHOULD define its public API.
api:
rpms:
- mypackage
- mylibrary
- mylibrary-devel
Currently the only supported type of API are binary RPM packages, that is the list of RPMs that are guaranteed to a) be present in the module, and b) not break their interfaces such as binaries their provide or their ABI.
Module filters define lists of components or other content that should not be part of the resulting, composed module deliverable. They can be used to only ship a limited subset of generated RPM packages, for instance.
filter:
rpms:
- mypackage-plugins
Currently the only supported type of filter are binary RPM packages.
Modules MAY, and most modules do contain a components section defining the module’s content.
components:
(...)
Module RPM content is defined in the rpms
subsection of
components
and typically consists of one or more packages described
by their SRPM names and additional extra key-value pairs, some required
and some optional, associated with them.
components:
rpms:
foo:
rationale: The key component of this module.
buildorder: 100
repository: git://git.example.com/foo.git
ref: branch-tag-or-commit-hash
cache: http://www.example.com/lookasidecache/
arches:
- i686
- x86_64
multilib:
- x86_64
dependency-of-foo:
rationale: Needed for foo.
buildorder: 50
repository: git://git.example.com/dependency-of-foo.git
ref: master
cache: http://www.example.com/lookasidecache/
arches: [ i686, x86_64 ]
multilib: [ x86_64 ]
The following key-value pairs extend the SRPM name:
rationale
- every component MUST declare why it was added to the
module; this is currently a free form string. It should end with a
period.buildorder
- marks the component as a member of a specific build
group; components are scheduled to be built in batches according to
their buildorder tags, from the lowest to the highest; built
components are tagged back into the buildroot before the next batch
is built; several components can belong to the same build group by
specifying the same buildorder value; build order within build groups
is undefined; optional, integer, may be negative and defaults to zero
if not specified.repository
- specifies git or other VCS repository to use as the
component’s source; in Fedora, dist-git is used and this option
cannot be overridden.ref
- the repository
reference (a branch or tag name or a
commit hash) that should be built and included in this module;
recommended. If not defined, the current HEAD or equivalent is used.
ref
is always populated by the exact commit hash used by the
Module Build System during build.cache
- points to RPM lookaside cache; in Fedora this option
cannot be overriden.arches
- a list of architectures this component should be built
for; defaults to all available architectures.multilib
- a list of architectures where this component should be
available as multilib, e.g. if x86_64
is listed, x86_64
repositories will also include i686 builds. Defaults to no multilib.Modules may include other modules. This is similar to dependencies (both build- and run-time) but differs in a few key points:
Dependencies and module inclusions can be freely combined. Deciding on which is more fitting for your module varies from application to application.
Module module-style content is defined in the modules subsection of components and typically consists of one or more modules described by their names and additional extra key-value pairs, some required and some optional, associated with them.
components:
modules:
my-favourite-module:
rationale: An example of an included module.
buildorder: 20
repository: git://git.example.com/my-favourite-module.git
ref: 12ab34cd5
The following key-value pairs extend the module-style components:
rationale
- see the description in the RPM content sectionbuildorder
- see the description in the RPM content sectionrepository
- see the description in the RPM content sectionref
- see the description in the RPM content sectionNo other content is currently supported.
A minimal module distributed as example-master-20161109172409, stored in
the modules/example
dist-git repository and its master branch, built
on November 9, 2016, at 17:24:09 UTC, containing no packages, having no
dependencies whatsoever and defining only the minimal set of required
metadata.
document: modulemd
version: 1
data:
summary: An example summary
description: And an example description.
license:
module:
- MIT
Another flavour of the abovementioned module, containing one RPM package
with SRPM name foo
. This module doesn’t define any dependencies or
optional metadata.
document: modulemd
version: 1
data:
summary: An example summary
description: And an example description.
license:
module:
- MIT
components:
rpms:
foo:
rationale: An example RPM component.
Yet another flavour of the minimal module, containing one RPM package
with SRPM name foo
. A build of foo
creates binary packages foo-1.0-1
and the subpackage foo-doc-1.0-1
. Both would get included in the
module for any architecture if no filter were be used. This module
doesn’t define any dependencies or optional metadata.
document: modulemd
version: 1
data:
summary: An example summary
description: And an example description.
license:
module:
- MIT
filter:
rpms:
- foo-docs
components:
rpms:
foo:
rationale: An example RPM component.
Another minimal module, containing no packages or any optional metadata besides dependencies. Modules of this type are, together with modules that include other modules, referred to as stacks.
document: modulemd
version: 1
data:
summary: An example summary
description: And an example description.
license:
module:
- MIT
dependencies:
requires:
generational-core: master
a-framework-module: and-its-stream
Yet another minimal module, containing no optional metadata besides a single included module in the components section. Modules of this type are, together with modules that only depend on other modules, referred to as stacks.
document: modulemd
version: 1
data:
summary: An example summary
description: And an example description.
license:
module:
- MIT
content:
modules:
a-framework-module:
rationale: Bundled for various reasons.
A typical Fedora module defines all the mandatory metadata plus some
useful references, has build and runtime dependencies and contains one
or more packages built from specific refs in dist-git. It relies on the
Module Build Service to extract the name, stream and version properties
from the VCS data and to fill in the licensing information from the
included components and populate the data
→ license
→ content
list.
document: modulemd
version: 1
data:
summary: An example of a common Fedora module
description: This module demonstrates what most Fedora modules look like.
license:
module: [ MIT ]
dependencies:
buildrequires:
generational-core: master
extra-build-environment: master
requires:
generational-core: master
references:
community: http://www.example.com/common-package
documentation: http://www.example.com/common-package/docs/5.67/
profiles:
default:
rpms:
- common-package
- common-plugins
development:
rpms:
- common-package
- common-package-devel
- common-plugins
api:
rpms:
- common-package
- common-package-devel
- common-plugins
components:
rpms:
common-package:
rationale: The key component of this module.
ref: common-release-branch
common-plugins:
rationale: Extensions for common-package.
buildorder: 1
ref: common-release-branch
While not a part of the modulemd specification yet, modules will eventually carry a Service License Agreement (SLA) value and an End Of Life (EOL) value.
The Arbitrary Branching work in Fedora will enable packagers to select independent SLAs and EOLs for both their rpm branches as well as their module branches. Both of these values are associated with the branch in a dist-git repo, but not with the modulemd or spec file contained therein.
Packagers will have to choose from a set of pre-defined SLAs maintained by Release Engineering. More info coming soon!