Defining modules in modulemd

Simply put, modulemd is a file that defines which packages get built for which releases. It includes a summary and a description, a list of source RPM packages, build information i.e. build order and macros, and usage information i.e. installation profiles and licenses.

A typical modulemd example

A typical modulemd file looks similar to the following examples. Read on for more details about each part of the modulemd file.

Feel free to copy/paste this example when creating your new module.

document: modulemd
version: 2
data:
    # === Information about this module ==================================
    # (Can be copied from the main RPM package, but doesn't need to be)
    summary: An example module
    description: >-
        A module for the demonstration of the metadata format. Also,
        the obligatory lorem ipsum dolor sit amet goes right here.

    # === License of this modulemd file ==================================
    # (Package licenses will be added automatically by the build system)
    license:
        module:
            - MIT

    # === Modular dependencies ===========================================
    # (For which Fedora releases to build?)
    dependencies:
      - buildrequires:
            platform: [] # <- Build for all Fedora releases
        requires:
            platform: [] # <- Run on all Fedora releases

    # === Module API (optional, but encouraged) ==========================
    # (Which packages are API-stable?)
    api:
        rpms:
            - package-one        # <- Binary RPM package name
            - package-one-extras # <- Binary RPM package name
            - package-one-cli    # <- Binary RPM package name
            - package-one-devel  # <- Binary RPM package name
            - package-two        # <- Binary RPM package name

    # === Installation profiles (optional, but encouraged) ===============
    # (Helping users with installation by providing predefined groups)
    profiles:
        default:  # <- Name of the profile
            description: A standard installation.
            rpms:
                - package-one         # <- Binary RPM package name
                - package-one-extras  # <- Binary RPM package name
                - package-two         # <- Binary RPM package name
        cli:      # <- Name of the profile
            description: A command-line client.
            rpms:
                - package-one-cli     # <- Binary RPM package name

    # === Packages in this module ========================================
    # (Referenced by their dist-git repo name + branch name)
    components:
        rpms:
            first-package:  # <- Source RPM package name
                ref: 3.0    # <- Branch name in dist-git
                rationale: Provides the core functionality.
            second-package: # <- Source RPM package name
                ref: latest # <- Branch name in dist-git
                rationale: Web UI for the first-package.

Common modulemd definitions

These are the common parts of a modulemd file, used in the example above. Advanced definitions, including a complex example of Module Stream Expansion (MSE), are towards the end of this page.

Document header

Every modulemd starts with these three lines:

document: modulemd
version: 2
data:
    ... (1)
1 All the following definitions go here, under data.

Information about this module

Tell users what this module represents by writing a summary and a description.

    summary: An example module
    description: >-  (1)
        A module for the demonstration of the metadata format. Also,
        the obligatory lorem ipsum dolor sit amet goes right here.
1 The >- means new line in YAML. Useful for longer blocks of text, such as the description!

License of this modulemd file

This is a license of this very modulemd file and it doesn’t need to be modified. The build system adds licenses of all packages to this list automatically.

    license:
        module:
            - MIT  (1)
1 A license for this modulemd file. Fedora content, such as SPEC files or patches not included upstream, uses the MIT license by default, unless the component packager declares otherwise.

Modular dependencies

Simply put: For which Fedora releases to build?

To build your module for all Fedora releases that are actively maintained, use the following definition. For anything more than this, such as building against other modules or requiring other modules during run time, please see the Advanced section below.

    dependencies:
      - buildrequires:
            platform: []
        requires:
            platform: []

Installation profiles (optional, but encouraged)

To help users install your module, define installation profiles. These profiles represent a specific use case of your module. Most modules have at least a default profile. But you can specify more. For example, a database module can have a server and a client profile.

    profiles:
        default:  (1)
            description: A standard installation.  (2)
            rpms:
                - package-one         (3)
                - package-one-extras  (3)
                - package-two         (3)
        cli:
            description: A command-line client.
            rpms:
                - package-one-cli
        ...  (4)
1 Name of the profile.
2 A quick summary of the profile.
3 Binary packages to be installed with this profile.
4 List as many profiles as you need.

Module API (optional, but encouraged)

List all binary RPM packages in your module that you consider to be the main stable feature of the module. Other (unlisted) packages should be considered unsupported, or an implementation detail.

    api:
        rpms:
            - package-one
            - package-one-extras
            - package-one-cli
            - package-one-devel
            - package-two

Packages in this module

List all source SRPM packages this module should include, referenced them by their dist-git repo name + branch name.

    components:
        rpms:
            first-package:  (1)
                rationale: Provides the core functionality.  (2)
                ref: 3.0  (3)
            second-package:
                rationale: Web UI for the first-package.
                ref: latest
            ...  (4)
1 Name of the package — maps to a DistGit repository name.
2 The reason why is this package here. Mostly for humans.
3 DistGit branch, tag, or a commit — so the right version of the package gets included.
4 List as many packages as you need.

Advanced definitions

References to the upstream (optional)

You can also provide references to the upstream community, documentation, or to an issue tracker.

    references:
        community: http://www.example.com/  (1)
        documentation: http://www.example.com/  (2)
        tracker: http://www.example.com/  (3)
1 Upstream community website, if it exists.
2 Upstream documentation, if it exists.
3 Upstream bug tracker, if it exists.

Building in a specific order (optional)

Packages are built in batches. By default, all packages are part of a single group, and therefore built concurrently.

To build packages in a specific order, assign them to multiple build groups. Build groups are identified by an integer. Groups with lower number are built first. Negative values are allowed, 0 is the implicit default value.

In this specific example, first-package gets built first, and second-package gets built second.

    components:
        rpms:
            first-package:
                rationale: Provides the core functionality.
                ref: 3.0
                buildorder: 0  (1)
            second-package:
                rationale: Web UI for the first-package.
                ref: latest
                buildorder: 10  (1)
1 A number of the build group.

Build macros (optional)

Use this if you need to build your packages with a specific RPM macro. Applies to all packages in the module.

    buildopts:
        rpms:
            macros: |
                %demomacro 1
                %demomacro2 %{demomacro}23

Advanced dependencies (optional)

modules can be

  • built against other modules

  • require other modules during run time

  • built against one or more streams of the same module

  • work with one or more streams of another module

Building only for Fedora 28:

    dependencies:
      - buildrequires:
            platform: [f28]
        requires:
            platform: [f28]

Building for everything else than Fedora 28:

    dependencies:
      - buildrequires:
            platform: [-f28]
        requires:
            platform: [-f28]

Building only for Fedora 28 and Fedora 29:

    dependencies:
      - buildrequires:
            platform: [f28, f29]
        requires:
            platform: [f28, f29]

Building against other modules::

Your module can also depend on another modules. Specific streams can be referenced the same way as above in "Building for a specific Fedora release(s) only".

    dependencies:
      - buildrequires:
            platform: []
            nodejs: []
        requires:
            platform: []
            nodejs: []

A complex example:

Simple things should simple, complex things should be possible. Let’s say my module requires nodejs during build and run time. It also requires build-tools only during build. To make it even more complex, it also requires a specific stream of a pizza-module during build and run time, but only on Fedora 27.

    dependencies:
      - buildrequires:
            platform: [-f27]
            buildtools: [v1, v2]
            nodejs: []
        requires:
            platform: [-f27]
            nodejs: []
      - buildrequires:
            platform: [f27]
            buildtools: [v1, v2]
            nodejs: []
            pizza-module: [3.6]
        requires:
            platform: [f27]
            nodejs: []
            pizza-module: [3.6]

For even more complex scenarios, please study the modulemd specification.

Excluding binary packages (optional)

One source RPM package might produce multiple binary RPM packages. If you don’t want to include some binary packages, list them under filter.

Filtered RPMs are still available to use as build dependencies in subsequent stages of the module build, but are not included in the composed repository for users.

    filter:
        rpms:
            - first-package-debuginfo
            - second-package-nope

Creating build-only components (optional)

In addition to filtering subpackages, it’s possible to filter out all of the artifacts produced by a component in a module. This is useful in cases where your module’s primary packages have a build-time dependency that you do not want to ship. An example of such a case would be if you need to build with a specially-patched documentation-generator that would conflict with the version used as the default in Fedora.

    components:
        rpms:
            customdocgen:
                rationale: A patched version of docgen that enables an experimental feature.
                ref: experimental
                buildorder: 0
                buildonly: 1
            myapp:
                rationale: My application
                ref: latest
                buildorder: 10

In this example, customdocgen would be built first and made available in the buildroot for myapp to use during its build. Once the module build is finished and it is composed into a DNF repository, only the unfiltered artifacts from myapp will be available. All of the customdocgen artifacts will be automatically added to the data.filters.rpms section of the module metadata.

A minimal modulemd

An absolute minimum

This module includes two source RPM packages built for all Fedora releases.

document: modulemd
version: 2
data:
    summary: An example module
    description: >-
        A module for the demonstration of the metadata format. Also,
        the obligatory lorem ipsum dolor sit amet goes right here.
    license:
        module:
            - MIT
    dependencies:
      - buildrequires:
            platform: []
        requires:
            platform: []
    components:
        rpms:
            first-package:
                rationale: Provides the core functionality.
                ref: 3.0
            second-package:
                rationale: Web UI for the first-package.
                ref: latest

This module includes two source RPM packages built for all Fedora releases. It makes clear which packages are considered the API, and helps users with installation thanks to the profiles.

document: modulemd
version: 2
data:
    summary: An example module
    description: >-
        A module for the demonstration of the metadata format. Also,
        the obligatory lorem ipsum dolor sit amet goes right here.
    license:
        module:
            - MIT
    dependencies:
      - buildrequires:
            platform: []
        requires:
            platform: []
    api:
        rpms:
            - package-one
            - package-one-extras
            - package-one-cli
            - package-one-devel
            - package-two
    profiles:
        default:
            description: A standard installation.
            rpms:
                - package-one
                - package-one-extras
                - package-two
        cli:
            description: A command-line client.
            rpms:
                - package-one-cli
    components:
        rpms:
            first-package:
                rationale: Provides the core functionality.
                ref: 3.0
            second-package:
                rationale: Web UI for the first-package.
                ref: latest

Using fedmod

To get started quickly, you can use the fedmod tool (from the package of the same name) to create a skeletal modulemd file for your module based on one or more source packages, e.g.

$ fedmod fetch-metadata
$ fedmod rpm2module dwm > dwm.yaml

If you specify more than one package it will fill in the summary and description fields from their counterparts in the first specified package.