Static contexts
===============

By default, module build contexts are generated by MBS and used to ensure uniqueness for each
NSVC. Static contexts, which can be set in a module's YAML document, allow a user to specify
their own contexts for their builds. This is used to make a module's per stream dependencies
and upgrade paths more explicit for multicontext modules.

There are two methods to declare static contexts, one which uses ``ModuleStreamV2`` and a newer
one which uses ``PackagerV3``. The ``ModuleStreamV2`` method uses the already existing ``xmd``
field to define its contexts, and MBS uses the defined dependencies instead of relying on MSE.
The ``PackagerV3`` method uses a new field ``configurations`` in the YAML document to declare
the contexts, streams, and dependencies, which MBS uses to bypass MSE.

**PackagerV3 Method**

- this method requires a modulemd-packager document, which is declared via ``document`` at the
  start of the file. Also, the Module metadata format version to be set to ``3``.
- the user can set their own context and dependencies when required through ``configurations``.
  ``configurations`` is a list of contexts in the ``data`` section of a YAML document used for
  build configuration, to replace Module Stream Expansion. To make static contexts work, you
  need to define ``context`` and ``platform`` for each platform you're building for. You may also
  optionally set context specific ``requires`` and ``buildrequires`` values.
- The context definition needs to be defined in the initial modulemd yaml file. ``configurations``
  build property overrides any dependencies set through the ``dependencies`` property.
- *static contexts* and *stream expansion* are mutually exclusive i. e. the streams defined in
  ``buildrequires`` and ``requires`` of *static context* will not be expanded and need
  to be precisely defined by the user. (You can not use *stream expansion* notation as ``[]``
  or ``-f28`` as this will result in an error)


**Example**

::

    document: modulemd-packager
    version: 3
        .
        .
        .
        configurations:
            - context: context1
              platform: f28
              buildrequires:
                  module1: stream1
                  .
                  .
                  .
                  moduleN: streamN
              requires:
                  module1: stream1
                  .
                  .
                  .
                  moduleN: streamN
            - context: context2
              platform: f29
              requires:
                  module1: stream1
              .
              .
              .


**ModuleStreamV2 Method**

- the user can specifically set their own context and dependencies when required through
  ``mbs_options``. ``mbs_options`` is a dict which is part of the ``xmd`` property and
  is used to configure additional build options for MBS. To make static contexts work,
  you need to define ``contexts`` dict inside ``mbs_options`` property.
- The context definition needs to be defined in the initial modulemd yaml file. ``contexts``
  build property overrides any dependencies set through the ``dependencies`` property.
- *static contexts* and *stream expansion* are mutually exclusive i. e. the streams defined in
  ``buildrequires`` and ``requires`` of *static context* will not be expanded and need
  to be precisely defined by the user. (You can not use *stream expansion* notation as ``[]``
  or ``-f28`` as this will result in an error)
- *static contexts* only override ``context`` of a module stream i. e. the one which
  is the part of the module streams NSVC. ``build context`` is still calculated and preserved
  in the resulting build in ``mbs`` property in ``xmd`` so the reuse of builds with the
  same ``build contexts`` takes place.
- as per design of the modulemdlib the only types which can be put inside of the ``xmd``
  property are ``dict`` and ``string``.
- the user can set a boolean field ``static_context`` in the ``data`` section of a YAML
  document describing a stream. This field is optional and will default to ``False`` if
  unspecified.
- if ``static_context`` is set to ``True``, dependency solvers will consider the context
  meaningful for determining the upgrade path. Otherwise, if it is set to ``False``,
  a static context will not be used. To maintain backwards compatibility, if the
  ``mbs_options`` dict contains a ``contexts`` dict, ``static_context`` will be treated
  as ``True``.


**Example**:

::

    .
    .
    .
    xmd:
        mbs_options:
            contexts:
                context1:
                    buildrequires:
                        module1: stream1
                        .
                        .
                        .
                        moduleN: streamN
                    requires:
                        moduleN: stream1
                        .
                        .
                        .
                        moduleN: streamN
                .
                .
                .
                contextN:
                    .
                    .
                    .

