- Notifications
You must be signed in to change notification settings - Fork1
Automatically determine the semantic version based on merge history.
License
AlexAtkinson/github-action-gitops-autover
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Language/content agnostic method of automatically determining thesemantic version for a product based onbranch merge history with MINIMALdiscipline dependencies.
This is accomplished by counting the merges of branches matching thenaming scheme into the [main|master] branch. Folks familiar with Scrum/SAFe or GitFlow/fooFlow strategies will recognize this scheme.
Burning Questions
- Yes - This can indeed be implemented in repos that previously used different version increment methods.
- Yes - Jira will recognize the issue tag anywhere in the branch name -- it does not have to be a prefix for the integration to function.
- Yes - This aligns with and extends onguidance from Atlassian on branch naming schemes.
- 1.0.0: (non-breaking) Addition of support for mono-repos. IE: Discretely version specific directories.
- NOTE: Github, Jira, etc., were designed to host one product per repo/project. DO NOT create new mono-repo projects unless you're specifically tooling out to support them well.
- 0.3.1: Update the checkout action version to v4.
- 0.3.0: Bring back the unshallowing, which ensures the full git log is available.
- TODO: Adjust scripts to use
git log --remotes
to avoid unshallowing large repos.
- TODO: Adjust scripts to use
- 0.2.9: Fix 'ops' increments; add user friendly error outputs.
- Repository Setup
- 1. Disable squash merging in the repository settings.
- ?. If you have a previously established version for the repo, ensure it's tagged like: 'MAJOR.MINOR.PATCH'.
For example, if you have a tag like 'v1.2.3', you will want to add a tag like '1.2.3' to that commit as well, which might look like: git checkout v1.2.3git tag 1.2.3git push --tags
- Workflow Setup
- 2. Ensure your action executes a checkout step prior to using this action.
- 3. Use the outputs from this action as desired. For example, you might use it to update the version of an npm package:
npm version ${{ steps.gitops-autover.outputs.new-version }}
- 4. Tag the repo with the new version at some point in the workflow.
- Team Setup
- 5. Ensure the iteration team adheres to the branch naming scheme defined below. Here's an example workflow. Bonus points for integrating branch management into your issue tracking system.
git checkout -b fix/not-a-featuregit commit --allow-empty -m "This was a bug and not a feature after all..."git push --set-upstream origin fix/not-a-feature# THEN: Click the link to create a PR & merge it
Note: Only required for setting up mono-repo versioning.
- mono-repo-product-name: [string]
- Enables mono-repo mode. The product name to match against.
Eg: 'bob', would match the tags like 'bob_1.2.3'.
Required: if mono-repo-mode: true
Default: '' - mono-repo-product-path: [string]
- The path to the product.
Eg: path/to/bob
Required: if mono-repo-mode: true
Default: '' - force-patch-increment: [bool]
- Forces a PATCH increment if no other increment detected.
(Intended for development purposes only.)
Required: false
Default: false
- new-version: [string]
- The newly detected version.
- previous-version: [string]
- The previous version.
Below is a valid workflow utilizing this action. If you wanted to extend it to do something like update a 'package.json' version, for example, you would simply create a step that runs:npm version $NEW_VERSION
.
name: gitops-autoveron: push: branches: - mainjobs: use-action: name: Verify GitOps AutoVer Action runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run GitOps Automatic Versioning Action id: gitops-autover uses: AlexAtkinson/github-action-gitops-autover@0.3.1 - name: Verify Outputs run: | NEW_VERSION=${{ steps.gitops-autover.outputs.new-version }} echo "new-version: $NEW_VERSION" PREVIOUS_VERSION=${{ steps.gitops-autover.outputs.previous-version }} echo "previous-version: $PREVIOUS_VERSION"
To make use of the mono-repo support, simply add a block for the director you wish to version.
- name: Run GitOps Automatic Versioning Action id: gitops-autover uses: AlexAtkinson/github-action-gitops-autover@0.3.1 with: mono-repo-product-name: bob
This results in outputs like:
major:
patch:
minor:
Q:How did you execute 103 merges?
A: You can use the bump scripts in the scripts directory of this
repo, like: './scripts/bumpPatch.sh 42'. (Does not work with branch protection enabled)
Additionally, this repo uses its own action for versioning, so feel free to investigate that workflow for another example.
name: gitops-autover-exampleon: push: branches: - mainjobs: init: name: Initialize runs-on: ubuntu-latest outputs: REPOSITORY: ${{ steps.init.outputs.REPOSITORY }} PRODUCT: ${{ steps.init.outputs.PRODUCT_NAME }} PRODUCT_NAME_LOWER: ${{ steps.init.outputs.PRODUCT_NAME_LOWER }} NEW_VERSION: ${{ steps.gitops-autover.outputs.new-version }} PREVIOUS_VERSION: ${{ steps.gitops-autover.outputs.previous-version }} steps: - name: Checkout Source uses: actions/checkout@v3 with: lfs: true fetch-depth: 0 - name: Initialize id: init run: | # Detect repo name. REPOSITORY=${PWD##*/} echo "REPOSITORY=$REPOSITORY" >> $GITHUB_OUTPUT # Autodetect product name. Eg: # A repo named cool-corp-awesome-docker will result in # the image being pushed as: awesome-docker:x.x.x [[ $(echo -n "$(cut -d- -f3- <<< ${REPOSITORY})" | wc -c) -gt 0 ]] && PRODUCT_NAME=$(cut -d- -f3- <<< ${REPOSITORY}) [[ $(echo -n "$(cut -d- -f3- <<< ${REPOSITORY})" | wc -c) -eq 0 ]] && PRODUCT_NAME=default echo "PRODUCT_NAME=$PRODUCT_NAME" >> $GITHUB_OUTPUT PRODUCT_NAME_LOWER=${PRODUCT_NAME,,} echo "PRODUCT_NAME_LOWER=$PRODUCT_NAME_LOWER" >> $GITHUB_OUTPUT - name: GitOps Automatic Versioning id: gitops-autover uses: AlexAtkinson/github-action-gitops-autover@0.3.1 build: name: "Build" runs-on: ubuntu-latest needs: [init] steps: - name: "Build" run: | echo "SUCCESSFUL BUILD" > "${{ needs.init.outputs.PRODUCT_NAME_LOWER }}.${{ needs.init.outputs.NEW_VERSION }}.txt" # Then bolt on extras such as slack notify or github release actions as needed.
This action dependsonly on the followingbranch naming scheme being observed.
Branch Name | Increment | Description |
---|---|---|
feature/.* | Minor | Product features. |
enhancement/.* | Minor | Product enhancements. |
fix/.* | Patch | Product fixes |
bugfix/.* | Patch | You should use fix. |
hotfix/.* | Patch | Are you from the past? |
ops/.* | Patch | Enables ops changes to trigger builds. |
For example, the name of the branch for a new awesome feature named Awesome Feature, might be: 'feature/awesome_feature'.
This action ismost suitable for git projects with the following operational design:
- Each merge into main|master is intended to produce an artifact, following the "everything is potentially releasabe" approach.
This action isnot suitable for projects requiring:
- pre-release, beta, etc., type fields. Such projects should depend upon their own language native tooling.
- specific version numbers to be planned and orchestrated ahead of time (usually marketing efforts).
- Exception: Major releases. These can be actioned on demand as outlined below.
- rebase merges. Reminder: this actiondepends on merge commit messages.
- Exception: Patterns like: main < (merge-commit) < staging-branch < (rebase) work-branches
- As long as main|master gets a merge commit message, everyone is happy.
- Exception: Patterns like: main < (merge-commit) < staging-branch < (rebase) work-branches
Versions are returned only in the following format:'MAJOR.MINOR.PATCH'.
MAJOR version increments depend upon manual intervention to trigger as it is not practical to automatically detect either major refactoring oraccepted/planned breaking changes to a product. Human inputinforms the tool of such MAJOR increment qualifying scenarios.
This increment can be accomplished in one of the following ways:
Push a commit message containing: '+semver: [major|breaking]'. For example:
git commit --allow-empty -m "+semver: major" git push
Push the MAJOR tag manually. That this is theless desirable option as it will require the merge of a qualifying branch to iterate the version number, making the first possible version that could be produced 'n.0.1'. Assuming successful build and testing.
git tag 1.0.0 git push --tags
For those interested, here's some pseudo code:
lastMajor = Extract from previous git tag (why option 1 is recommended)lastMinor = Extract from previous git taglastPatch = Extract from previous git tagIF no previous git tag; THEN MAJOR = 0 MINOR = 0 PATCH = 0IF major increment indicator; THEN MAJOR = lastMajor + 1 MINOR = 0 PATCH = 0ELSEIF merged feature/.* or enhancement/.* branches; THEN MAJOR = lastMajor MINOR = lastMinor + count of merged branches PATCH = 0ELSEIF merged bugfix/.* or hotfix/.* branches; THEN MAJOR = lastMajor MINOR = lastMinor PATCH = lastPatch + count of merged branches
If there are no merges of branches conforming to the above naming scheme, this action will fail with the following output:
ERROR: No feature, enhancement, fix, bugfix, hotfix, or ops branches detected!
- When encountering this scenario, and a build is desired, you can simply create a branch with the appropriate naming convention and an empty commit, then merge it. Or use the bump scripts in the 'scripts/' directory of the repo for this action.
Merged branches not conforming to the above naming scheme will simply be ignored.
- HINT: This can be useful when you don't want to increment the version.
- Align this with build 'on:push:branches:' workflow configuration to avoid unnecessary builds.
- HINT: This can be useful when you don't want to increment the version.
The version output does not have a 'v' prefix.
If you would like a 'v' prefix to your versions, add it to your logic when using the output from this action. For example:
echo "The new version is v${{ steps.detect-version.outputs.new-version }}" ^ here
If both 'main' and 'master' branches exist remotely: FAIL
- This will not be changed.
Squash merging must be disabled. This is required to populate the git log with the commit messages issued from the git provider.
PRs are welcome.
- input(s): iteration-branches (map) - inform MINOR and PATCH incrementing branch name patterns.
- DONE: input(s): mono-mode (bool) - version subdirs discretely
- UNDONE-CAN'T DO:
CAN'T DO:DONE:unshallow from last version tag to latest commit to... Seems a limitation of (git at first glance). See theCheckout From Tag action.
About
Automatically determine the semantic version based on merge history.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors2
Uh oh!
There was an error while loading.Please reload this page.