I wrote [about relez][blog]

This is a description of the different versioning and release management workflows I’m thinking about.

relez-flows focuses on adding minimal manual work to the push-PR-test-review-merge flow that many people are already using, while adding maximum control. There are three versioning schemes I’m interested in: semver and other semantic versioning schemes, numeric (v1, v2) and date based (v2023-02-07-002) incremental versioning, and code-addressed versioning (usually Git commit SHA).

For my most complex workflow, I’m developing and deploying a React Native/Expo app. Here, I want to maintain two parallel version numbers for my releases. We’ve got our internal semantic versioning that’s sort of derived from semver. Here, major versions indicate native code changes, minor versions indicate changes requiring app store review, and patch versions can be pushed straight to the user. Next to that, we maintain a user-facing version which we increment however we want to.

In my least complex workflow, I deploy a backend service to a Docker repository, tagged (or versioned) with the Github commit SHA.

For both of these, I’d like to maintain a changelog/release history somewhere. This will make it easier for me to see what changes are deployed to a certain environment, and I can use it to automatically communicate updates internally, and maybe even externally through the app stores.

I’d like to be able to do all this without leaving Github. Ideally even without using bots.

Global truths

All changes are merged into main. Publishing releases happens from main.

Changelog information should be maintained in JSON files in a simple format. Ideally, I’d find some open source initiative for a standardized format. A Github Action should automatically create a changelog JSON file for each PR.

From these JSON files, a CHANGELOG.md should be created as well as Github Releases. The structure should look something like this:

.changelog
├── draft
│   ├── pr13.json
│   └── pr14.json
├── v0.0.1.json
└── v0.0.2.json
…

One or more release branches and PR should be maintained automatically through a separate branch where all JSON files in the .changelog/draft/ directory are merged into the appropriate vA.B.C.json file, and the CHANGELOG.md is updated.

The PR’s merge commit should be useful, including the new version and a summary of the changes. When merging this PR, a Github Release should be published and the commit should be tagged.

Per type…

Library

Versioning

Libraries should be versioned with semantic versioning, conforming to standard major/minor/patch rules.

PRs should be labeled (preferably automatically) with the appropriate type of version increase (e.g., version: major). This information is also stored in the PR’s changelog file.

Release

There is a simple release branch in which all changes are collected like described above.

As necessary, this “spec” can be extended with a definition of how fixes on older versions can be maintained. Hypothetically, a branch could be created from the desired latest release tag and the system could automatically detect that this change should go into a separate release PR.

Application

Versioning

Applications have at least(!) one version. This may have some type of semantic meaning, but it should probably be a simple date-based vYYYYMMDD-NNN version for most applications.

In React-Native apps, or other apps where the frontend can be deployed either through a reviewed process or directly to the user, the versioning should reflect the type of change. In RN, I use the versioning format vR.M.P, where:

  • R is runtime, requiring a full rebuild of the app when there are changes to native dependencies. This also requires rebuilding the Expo dev app.
  • M is “major” changes, defined as changes that require an App Store/Play Store review.
  • P is “patch” changes, for changes that can bypass the review.

This way it’s easily discernible what type of release is being made.

Additionally, applications can have a user-facing version. This is basically decided entirely by developer or PM/PO preferences.

PRs should be labeled (preferably automatically) with the appropriate type of version increase (e.g., version: major and user-facing-version: patch). This information is also stored in the PR’s changelog file.

Release

There is a simple release branch in which all changes are collected like described above.

Different release workflows could happen based on the different types of releases. For example, a major version increase in a React Native app could trigger an Expo build of the normal app. Merging a PR with a major version increase (without releasing) could trigger a development app build.

Server

Versioning

Servers should be versioned exclusively by Git commit SHA. If a server requires more versioning for some reason it should be treated as an application.

Release