Project configuration
---------------------

A releng-tool project defines its configuration options inside the a ``releng``
file at the root of a project. The primary configuration option for a developer
to define is ``packages``, which is used to hold a list of packages to be
processed:

.. code-block:: python

   #!/usr/bin/env python
   # -*- coding: utf-8 -*-

   packages = [
       'package-a',
       'package-b',
       'package-c',
   ]

A series of additional configuration options are available to be defined inside
the project's configuration. A list of common configuration options are as
follows:

.. list-table::
    :widths: auto

    * - .. _CONF_DEFAULT_INTERN:

        ``default_internal``

      - A flag to indicate that projects are implicitly loaded as internal
        projects. By default, packages not explicitly configured as internal
        or external are assumed to be external packages.

        .. code-block:: python

            default_internal = True

        See also `internal and external packages`_.

    * - ``extensions``

      - A list of extensions to load before processing a releng-tool project.
        If an extension cannot be loaded, releng-tool will stop with detailed
        information.

        .. code-block:: python

            extensions = [
                'ext-a',
                'ext-b',
            ]

        See also `loading extensions`_.

    * - ``external_packages``

      - A list of external package locations. By default, packages for a
        project will be searched for in root directory's package folder
        (``<root>/package``). In some build environments, some packages may
        be required or may be preferred to be located in another
        location/repository. To allow packages to be loaded from another
        package container directory, one or more package locations can be
        provided. For example:

        .. code-block:: python

            external_packages = [
                os.environ['MY_EXTERNAL_PKG_DIR'],
            ]

    * - .. _CONF_LICENSE_HEADER:

        ``license_header``

      - As the releng-tool build process is finalized, a license document
        can be generated containing each package's license information. If a
        developer wishes to add a custom header to the generated document, a
        header can be defined by project's configuration. For example:

        .. code-block:: python

            license_header = 'my leading content'

        See also `licenses`_.

    * - ``packages``

      - A list of packages to process. Packages listed will be processed
        by releng-tool till their completion. Package dependencies not
        explicitly listed will be automatically loaded and processed as well.

        .. code-block:: python

            packages = [
                'package-a',
                'package-b',
                'package-c',
            ]

    * - ``prerequisites``

      - A list of host tools to check for before running a releng-tool
        project. Allows a developer to identify tools to check and fail-fast
        if missing, instead of waiting for a stage which requires a specific
        tool and failing later during a building, packaging, etc. phase.

        .. code-block:: python

            prerequisites = [
                'tool-a',
                'tool-b',
                'tool-c',
            ]

    * - .. _CONF_SYSROOT_PREFIX:

        ``sysroot_prefix``

      - Define a custom sysroot prefix to provide to packages during their
        configuration, build and installation stages. By default, the sysroot
        prefix is set to ``/usr`` or ``\usr`` (based on the system's
        default character to separate pathname components).

        .. code-block:: python

            sysroot_prefix = '/usr'

        See also |LIBFOO_PREFIX|_.

    * - ``url_mirror``

      - Specifies a mirror base site to be used for URL fetch requests.
        If this option is set, any URL fetch requests will first be tried
        on the configured mirror before attempting to acquired from the
        defined site in a package definition.

        .. code-block:: python

            url_mirror = 'ftp://mirror.example.org/data/'

.. |CONF_DEFAULT_INTERN| replace:: ``default_internal``
.. |CONF_LICENSE_HEADER| replace:: ``license_header``
.. |CONF_SYSROOT_PREFIX| replace:: ``sysroot_prefix``

A list of more advanced configuration options are as follows:

.. list-table::
    :widths: auto

    * - ``cache_ext``

      - A transform for cache extension interpreting. This is an advanced
        configuration and is not recommended for use except for special use
        cases outlined below.

        When releng-tool fetches assets from remote sites, the site value
        can used to determine the resulting filename of a cached asset. For
        example, downloading an asset from ``https://example.org/my-file.tgz``,
        the locally downloaded file will result in a ``.tgz`` extension;
        however, not all defined sites will result in an easily interpreted
        cache extension. While releng-tool will attempt its best to determine
        an appropriate extension value to use, some use cases may not be
        able to be handled. To deal with these cases, a developer ca
        define a transform method to help translate a site value into a
        known cache extension value.

        Consider the following example: a host is used to acquire assets
        from a content server. The URI to download an asset uses a unique
        request format ``https://static.example.org/fetch/25134``.
        releng-tool may not be able to find the extension for the fetched
        asset, but if a developer knows the expected archive types for
        these calls, a custom transform can be defined. For example:

        .. code-block:: python

            def my_translator(site):
                if 'static.example.org' in site:
                    return 'tgz'
                return None

            cache_ext = my_translator

        The above transform indicates that all packages using the
        ``static.example.org`` site will be ``tgz`` archives.

    * - ``override_extract_tools``

      - A dictionary to be provided to map an extension type to an external
        tool to indicate which tool should be used for extraction. For
        example, when a ``.zip`` archive is being processed for extraction,
        releng-tool will internally extract the archive; however, a user
        may wish to override this tool with their own extraction utility.
        Consider the following example:

        .. code-block:: python

            override_extract_tools = {
                'zip': '/opt/my-custom-unzip {file} {dir}',
            }

        Note that the use of an override option should only be used in
        special cases (see also |CONF_OVERRIDES|).

    * - ``override_revisions``

      - Allows a dictionary to be provided to map a package name to a new
        revision value. Consider the following example: a project defines
        ``module-a`` and ``module-b`` packages with package ``module-b``
        depending on package ``module-a``. A developer may be attempting to
        tweak package ``module-b`` on the fly to test a new capabilities
        against the current stable version of ``module-a``; however, the
        developer does not want to explicitly change the revision inside
        package ``module-b``'s definition. To avoid this, an override
        can be used instead:

        .. code-block:: python

            override_revisions = {
                'module-b': '<test-branch>',
            }

        The above example shows that package ``module-b`` will fetch using
        a test branch instead of what is defined in the actual package
        definition.

        Note that the use of an override option should only be used in
        special cases (see also |CONF_OVERRIDES|).

    * - ``override_sites``

      - A dictionary to be provided to map a package name to a new site
        value. There may be times where a host may not have access to a
        specific package site. To have a host to use a mirror location
        without having to adjust the package definition, the site override
        option can be used. For example, consider a package pulls from
        site ``git@example.com:myproject.git``; however, the host
        ``example.com`` cannot be access from the host machine. If a mirror
        location has been setup at ``git@example.org:myproject.git``, the
        following override can be used:

        .. code-block:: python

            override_sites = {
                '<pkg>': 'git@example.org:mywork.git',
            }

        Note that the use of an override option should only be used in
        special cases (see also |CONF_OVERRIDES|).

    * - .. _CONF_QUIRKS:

        ``quirks``

      - A list of configuration quirks to apply to deal with corner case
        scenarios which can prevent releng-tool operating on a host system.

        .. code-block:: python

            quirks = [
                'releng.<special-quirk-id>',
            ]

        For a list of available quirks, see `quirks`_.

    * - .. _CONF_URLOPEN_CONTEXT:

        ``urlopen_context``

      - Allows a project to specify a custom SSL context [#urlopen]_ to apply
        for URL fetch requests. This can be useful for environments which may
        experience ``CERTIFICATE_VERIFY_FAILED`` errors when attempting to
        fetch files. A custom SSL context can be created and tailored for
        a build environment. For example:

        .. code-block:: python

            import ssl
            ...

            urlopen_context = ssl.create_default_context()

.. |CONF_OVERRIDES| replace:: :ref:`configuration overrides <conf_overrides>`
.. |CONF_QUIRKS| replace:: ``quirks``
.. |CONF_URLOPEN_CONTEXT| replace:: ``urlopen_context``
