SkillAgentSearch skills...

Polyvers

Manage sub-project versions in Git monorepos independently

Install / Use

/learn @ankostis/Polyvers
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

================================================================== Polyvers: Bump sub-project versions in Git monorepos independently

.. _opening-start: .. image:: https://img.shields.io/pypi/v/polyvers.svg :alt: Deployed in PyPi? :target: https://pypi.org/pypi/polyvers

.. image:: https://img.shields.io/travis/ankostis/polyvers.svg :alt: TravisCI (linux) build ok? :target: https://travis-ci.org/ankostis/polyvers

.. image:: https://ci.appveyor.com/api/projects/status/lyyjtmit5ti7tg1n?svg=true :alt: Apveyor (Windows) build? :scale: 100% :target: https://ci.appveyor.com/project/ankostis/polyvers

.. image:: https://img.shields.io/coveralls/github/ankostis/polyvers.svg :alt: Test-case coverage report :scale: 100% :target: https://coveralls.io/github/ankostis/polyvers?branch=master&service=github

.. image:: https://readthedocs.org/projects/polyvers/badge/?version=latest :target: https://polyvers.readthedocs.io/en/latest/?badge=latest :alt: Auto-generated documentation status

.. image:: https://pyup.io/repos/github/ankostis/polyvers/shield.svg :target: https://pyup.io/repos/github/ankostis/polyvers/ :alt: Dependencies needing updates?

.. image:: https://api.codacy.com/project/badge/Grade/11b2545fd0264f1cab4c862998833503 :target: https://www.codacy.com/app/ankostis/polyvers_jrc :alt: Code quality metric

:version: |version| :updated: |today| :Documentation: https://polyvers.readthedocs.io :repository: https://github.com/ankostis/polyvers :pypi-repo: https://pypi.org/project/polyvers/, https://pypi.org/project/polyversion/ :keywords: version-management, configuration-management, versioning, git, monorepos, tool, library :copyright: 2018 JRC.C4(STU), European Commission (JRC <https://ec.europa.eu/jrc/>) :license: EUPL 1.2 <https://joinup.ec.europa.eu/software/page/eupl>

A Python 3.6+ command-line tool to manage PEP-440 version-ids <https://www.python.org/dev/peps/pep-0440/>_ of dependent sub-projects hosted in a Git :term:monorepo\s, independently.

The key features are:

  • :term:setuptools integration,
  • x2 :term:repo scheme\s (:term:monorepo, :term:mono-project),
  • configurable :term:version scheme,
  • leaf :term:release scheme,
  • intuitive :term:version-bump algebra (TODO),
  • configurable :term:engravings.

The leaf version scheme feature departs from the logic of :ref:similar-tools. Specifically, when bumping the version of sub-project(s), this tool adds +2 tags and +1 commits:

  • one :term:Version tag in-trunk like foo-proj-v0.1.0,

  • and another :term:Release tag on a new :term:out-of-trunk commit (leaf) like foo-proj-r0.1.0 (the new version-ids are :term:engrave\d only in this release-commit):

    .. figure:: _static/leaf_commits.png :align: center :alt: Leaf-commits & version/release tags for the two repo's sub-projects

    Leaf-commits & version/release-tags for the two sub-project's,
    as shown in this repo's git history.
    

.. Note:: The reason for this feature is to allow exchange code across branches (for the different sub-projects) without :term:engravings getting in your way as merge-conflicts.

Additional capabilities and utilities:

  • It is still possible to use plain version tags (vtags) like v0.1.0, assuming you have a single project (called hereinafter a :term:mono-project)

  • A separate Python 2.7+ polyversion project, which contains API to extract sub-project's version from past tags (provided as a separate subproject so client programs do not get polyvers commands transitive dependencies). The library functions as a :term:setuptools plugin.

.. _opening-end:

.. contents:: Table of Contents :backlinks: top :depth: 4

.. _usage:

Tutorial

Install the tool

And you get the polyvers command:

.. code-block:: console

$ pip install polyvers
...
$ polyvers --version
0.0.0
$ polyvers --help
...

$ polyvers status
polyvers: Neither `setup.py` nor `.polyvers(.json|.py|.salt)` config-files found!

.. Note:: Actually two projects are installed:

- **polyvers** cmd-line tool, for developing python :term:`monorepo`\s,
- **polyversion**: the base python library used by projects developed
  with *polyvers* tool, so that their sources can discover their subproject-version
  on runtime from Git.

Prepare project

Assuming our :term:monorepo project /monorepo.git/ contains two sub-projects, then you need enter the following configurations into your build files::

/monorepo.git/
    +--setup.py               # see below for contents
    +--mainprog/__init__.py
    |                         from polyversion import polyversion, polytime
    |                         __version__ = polyversion()
    |                         __updated__ = polytime()
    |                         ...
    |
    +--core-lib/
        +--setup.py:          # like above
        +--core/__init__.py   # like above
        +--...

.. Tip:: You may see different sample approaches for your setup-files by looking into both polyvers & polyversion subprojects of this repo (because they eat their own dog food).

The polyversion library function as a setuptools "plugin", and adds a new setup() keyword polyversion = (bool | dict) (see :func:polyversion.init_plugin_kw for its content), which you can use it like this:

.. code-block:: python

from setuptools import setup

setup(
    project='myname',
    version=''              # omit (or None) to abort if cannot auto-version
    polyversion={           # dict or bool
        'version_scheme: 'mono-project',
        ...  # See `polyversion.init_plugin_kw()` for more keys.
    },
    setup_requires=[..., 'polyversion'],
    ...
)

.. Hint:: The setup_requires=['polyvers'] keyword (only available with setuptools, and not distutils), enables the new polyversion= setup-keyword.

Alternatively, a subproject may use :pep:0518 to pre-install polyversion library before pip-installing or launching setup.py script. To do that, add the pyproject.toml file below next to your setup script::

[build-system]
requires = ["setuptools", "wheel", "polyversion"]

and then you can simply import polyversion from your setup.py:

.. code-block:: python

from setuptools import setup
from polyversion import polyversion

setup(
    project='myname',
    version=polyversion(mono_project=True)  # version implied empty string.

.. Attention:: To properly install a :pep:0518 project you need pip-v10+ version.

Initialize polyvers

...we let the tool auto-discover the mapping of project folders ↔ project-names and create a traitlets configuration YAML-file <https://traitlets.readthedocs.io>_ named as /monorepo.git/.polyvers.py:

.. code-block:: console

$ cd monorepo.git

$ polyvers init --monorepo
Created new config-file '.polyvers.yaml'.

$ cat .polyvers.yaml
...
PolyversCmd:
  projects:
  - pname: mainprog     # name extracted from `setup.py`.
    basepath: .         # path discovered by the location of `setup.py`
  - pname: core
    basepath: core-lib
...

$ git add .polyvers.yaml
$ git commit -m 'add polyvers config-gile'

And now we can use the polyvers command to inspect the versions of all sub-projects:

.. code-block:: console

$ polyvers status
- mainprog
- core

Indeed there are no tags in in git-history for the tool to derive and display project-versions, so only project-names are shown. With --all option more gets displayed:

.. code-block:: console

$ polyvers status -a
- pname: mainprog
  basepath: .
  gitver:
  history: []
- pname: core
  basepath: core-lib
  gitver:
  history: []

..where gitver would be the result of git-describe.

Bump versions

We can now use tool to set the same version to all sub-projects:

.. code-block:: console

$ polyvers bump 0.0.0 -f noengraves   # all projects implied, if no project-name given
00:52:06       |WARNI|polyvers.bumpcmd.BumpCmd|Ignored 1 errors while checking if at least one version-engraving happened:
  ignored (--force=noengraves): CmdException: No version-engravings happened, bump aborted.
00:52:07       |NOTIC|polyvers.bumpcmd.BumpCmd|Bumped projects: mainprog-0.0.0 --> 0.0.0, core-0.0.0 --> 0.0.0

The --force=noengraves disables a safety check that requires at least one file modification for :term:engrave\ing the current version in the leaf "Release" commit (see next step).

.. code-block:: console

$ polyvers status
- mainprog-v0.0.0
- core-v0.0.0

$ git lg    # Ok, augmented `lg` output a bit here...HEAD --> UPPER branch.
COMMITS BRANCH TAGS                 REMARKS
======= ====== ==================== ========================================
     O  latest mainprog-r0.0.0      - x2 tags on "Release" leaf-commit
    /          core-r0.0.0            outside-of-trunk (not in HEAD).
   O    MASTER mainprog-v0.0.0      - x2 tags on "Version" commit
   |           core-v0.0.0            for bumping both projects to v0.0.0
   O                                - Previous commit, before version bump.

.. Hint:: Note the difference between ABC-v0.0.0 vs ABC-r0.0.0 tags.

In the source code, it's only the "release" commit that has :term:engrave\d* version-ids:

.. code-block:: console

$ cat mainprog/mainprog/__init__.py    # Untouched!
import polyvers

__title__     = "mainprog"
__version__ = 

Related Skills

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated7mo ago
Forks1

Languages

Python

Security Score

82/100

Audited on Aug 7, 2025

No findings