Setup
I have several gitlab repos where the general setup involves having a master
branch, a stage
(pre-release) branch and a dev
branch.
Push permissions are disabled for all 3 branches.
The workflow is to fork from the dev
branch for any hot-fixes, bug fixes and features. When you are satisfied with the release you would submit a merge-request to dev
. Eventually, when a stable build is ready inside dev
; a merge-request would be submitted for the stage
branch. Lastly, when you are satisfied with the pre-release you would submit a merge-request for the master
branch.
I have CI/CD configured so that tests, builds and deployments are automatically executed from the master
and stage
branches with the automatic generation of CHANGELOG.md
files. stage
branch deploys to the UAT s3 Bucket and master
deploys to the production s3 Bucket.
Deployment is handled through Semantic Versioning 2.0.0
which is responsible for bumping versions, generating changelogs and deploying.
I have a similar setup to the one just described above except it is a monorepo so I am using Lerna
to handle the publishing (deploying) with {"conventionalCommits": true}
to replicate Semantic Versioning 2.0.0
's behaviour. I am using independent versioning inside the monorepo.
Both the Semantic Versioning 2.0.0
and the Lerna
setup force the master
branch to always be either behind or equal with the stage
and dev
branches; and the stage
branch to always be behind or equal to the dev
branch in kind of like a cascading effect.
dev
>= stage
>= master
The Problem
Both Lerna Publish
and Semantic Versioning
make several changes to the files when publishing/deploying. Some of these changes include updating the CHANGELOG.md
file and bumping the version inside of the package.json
file.
Both Lerna and Semantic Versioning eventually push these changes to the branch they are run from through the CI/CD.
What this means is that if I merge from dev
to stage
, stage would then have the bumped version numbers and new changelogs pushed into it through either the Semantic Versioning or Lerna Publish executions. This would cause the stage
branch to be ahead of the dev
branch and would cause all the future forks from the dev
branch to detach from the stage
branch meaning that the next time I merge from dev
to stage
it's not going to be a simple fast-forward
merge like it's meant to be and the merge will most likely encounter conflicts which would prevent any future merges or may fail the CI/CD.
My Workaround
For Semantic Versioning:
- I have disabled the push feature so that the new, changed files are no longer committed and pushed (tags are still created and pushed)
- I have created a script that converts the
CHANGELOG.md
file to a PDF and sends it to my teams email
This works out well because Semantic Versioning uses tags to determine the changed files and decide how to bump the version. So, although the version inside the repo remains constant at 1.0.0
for example, Semantic Versioning is smart enough to increment the version from the latest tag not from what's in the package.json
This unfortunately doesn't hold true for Lerna which still uses tags to determine changed files but then bumps from the version inside package.json
which means that by not pushing the updated package.json
with the new version, Lerna always bumps me from 1.0.0
to either 1.0.1
, 1.1.0
, or 2.0.0
So I am stumped with Lerna.
Question
How should I be setting up my CI/CD to avoid the problem? I know the structure of my repo is common, and I haven't found anyone addressing this issue despite the countless users of Lerna and Semantic Versioning which tells me that I have obviously missed something as it is not a wide-spread issue.
Possible Solution
As I was writing this question, it crossed my mind that maybe I should only bump versions in dev
and then deploy from stage
and master
. This would prevent stage
and master
from ever being ahead of dev
, would this be the right way to do it?