Metav is a library that helps the release and versioning process of Clojure projects, particularly the one using tools.deps.
Using tools.deps, add several alias in your deps.edn
for each main task (display, spit, release) like this:
{:aliases {:metav {:extra-deps {jgrodziski/metav {:git/url "https://github.com/jgrodziski/metav.git" :sha "63b8286e5c8c0513431e8024a7d2f9a57bc2c18b"}}}
:artifact-name {:extra-deps {jgrodziski/metav {:git/url "https://github.com/jgrodziski/metav.git" :sha "63b8286e5c8c0513431e8024a7d2f9a57bc2c18b"}}
:main-opts ["-m" "metav.display"]}
:release {:extra-deps {jgrodziski/metav {:git/url "https://github.com/jgrodziski/metav.git" :sha "63b8286e5c8c0513431e8024a7d2f9a57bc2c18b"}}
:main-opts ["-m" "metav.release"]}}}
One liner:
clj -Sdeps '{:deps {jgrodziski/metav {:git/url "https://github.com/jgrodziski/metav.git" :sha "63b8286e5c8c0513431e8024a7d2f9a57bc2c18b"}}}' -m metav.display
If you've installed Metav's dependency in deps.edn
like in the above Installation section, just run:
clj -A:artifact-name
Release is the process invoked by the developer when a code related to a change is ready for prime time, hence releasable. The release process does the following:
One liner:
clj -Sdeps '{:deps {jgrodziski/metav {:git/url "https://github.com/jgrodziski/metav.git" :sha "63b8286e5c8c0513431e8024a7d2f9a57bc2c18b"}}}' -m metav.release
If you've installed Metav's dependency in deps.edn
like in the above Installation section, just run:
clj -A:release minor
Will execute the release process, the tag used for the release is printed in the standard output.
clj -A:metav -m metav.spit
At every moment we should be able to link a SCM hash to a software's binary artefact and also the inverse: link a binary artefact to a point in the SCM tree.
The idea is to drive the version from git instead of the other way around.
Release means some source code changes in one or several commits are ready to be "published" in the repository for later deployment. The Release process assigns a version number, tags the repo with it and push the changes. The Release task is invoked by developer when she considers changes in source code are ready. Pushing binary artefact (JAR, docker image) is out of the scope of the Release process and should be the responsibility of the CI system.
When releasing, developer indicates the characteristic of the changes regarding the breaks potentially introduced (major level change), whether new features were pushed (minor level with no breaking change) or just a fix with no new features nor breaking changes (patch level). The Release process takes care of dealing with the SCM and version number to left the developer only decides what she's releasing to the world.
SCM repository organization is important, with many decisions to make: mono or multirepos, modules slicing, links with the CI and build process. Monorepos are a popular way of organizing source code at the moment to promote better code sharing behavior, knowledge spreading, refactoring, etc. (see the article "Monorepos and the fallacy of scale"). The library is intended to accomodate Monorepos and Multirepos style of organization, in case of Monorepos style Metav's tagging behavior ensures isolation between components living in the same repo. Many tools implicitly depends on having a dedicated repository per component, in our case the way we manage the version and release from the source code should be independant of whether the source code is in a dedicated repo (Multirepos) or a shared one (Monorepos).
Each version should gives a clear semantic about the content of the change, Semantic Versioning is a great way to do that. I'm fond of using git tags to denote the current version of a component whether we use a Monorepo or a Multirepo.
Extract from the semver website:
Given a version number MAJOR.MINOR.PATCH, increment the:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards-compatible manner, and
- PATCH version when you make backwards-compatible bug fixes. Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
Every artifact should be reproduceable from the source code hash (git reference)
Version is deduced from the current state of the SCM working copy:
1.5.2
1.5.2+f34b91
(use the commit hash in version number)1.5.2-f34b91-DIRTY
The version is never persisted somewhere in source code to avoid any desynchronisation between SCM state and version number. However, the library can optionaly spit the metadata (module name and version) in file to be included in an artefact during the build process.
The SCM state drives the version.
Version uses the Semantic Versioning scheme.
We never use SNAPSHOT in version number as it's difficult to know what's really inside the binary artefact.
We believe repo layout should follows some convention regarding the system, container, component organization and relationships (following the C4 model for example, but any other layout should be possible). Hence the naming scheme should reflect that organization, if we take the same example used in the C4 model documentation, the folders in the monorepo should be:
Monorepo root
Internet_Banking
(System in C4 model)
Web_Application
Single_Page_Application
Mobile_App
API
(Container in C4 model, actual project that delivers an artefact whose name is Internet_Banking-API
)
src/
test/
resources/
deps.edn
Database
Mainframe_Banking
Email
Module's name is by default deduced from the repo layout (but can also be overriden) and is given by Metav along the version.
In case of a dedicated repo for the module Metav takes the folder name containing the working copy (aka. containing the .git
folder)
Each release invocation tags the current SCM state with the following naming scheme: system-container-version
.
The tagging function use git annotated tag using the naming scheme describe previously, the message contains an EDN data structure described the module that is tagged:
{:module-name "Internet_banking-API"
:version "1.5.2"
:path "Internet_Banking/API"
:msg "Add new attachment feature in the message part of the system"}
Metadata, like module name and version, should be deduced from the SCM and include in the binary artefact (JAR, docker image) but never commited as file along the source code to avoid any desynchronisation. Metadata file is called meta.edn
.
Metadata are:
See spit function.
Copyright © 2019 Jeremie Grodziski
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close