Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions .github/workflows/maven-version-determiner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/python3
import re
import subprocess
import sys


def get_arg(arg_idx) -> str:
return sys.argv[arg_idx]


def get_current_version() -> str:
current_version_cmd = subprocess.run(
"mvn help:evaluate -Dexpression=project.version -q -DforceStdout",
shell=True, capture_output=True, text=True)
return current_version_cmd.stdout


def get_release_version(release_type: str, current_version: str) -> str:
major, minor, patch = determine_new_version(current_version, release_type)
return str(major) + "." + str(minor) + "." + str(patch)


def get_snapshot_version(release_type: str, current_version: str) -> str:
major, minor, patch = determine_new_version(current_version, release_type)
patch += 1
return str(major) + "." + str(minor) + "." + str(patch) + "-SNAPSHOT"


def get_version_tag(release_type: str, current_version: str) -> str:
major, minor, patch = determine_new_version(current_version, release_type)
return "v" + str(major) + "." + str(minor) + "." + str(patch)


def determine_new_version(current_version, release_type):
major, minor, patch, is_prerelease = dissect_version(current_version)

match release_type:
case "MAJOR":
major, minor, patch = get_major_release_version(major)
case "MINOR":
major, minor, patch = get_minor_release_version(major, minor)
case "PATCH":
major, minor, patch = get_patch_release_version(major, minor, patch,
is_prerelease)
case _:
print("Second arg has to be `MAJOR`, `MINOR` or `PATCH`")
sys.exit()

return major, minor, patch


def dissect_version(current_version) -> (int, int, int):
version_regex = get_regex()
regex_match = version_regex.search(current_version)
major: int = int(regex_match.groupdict().get("major"))
minor: int = int(regex_match.groupdict().get("minor"))
patch: int = int(regex_match.groupdict().get("patch"))
is_prerelease: bool = True if regex_match.groupdict().get(
"prerelease") else False
return major, minor, patch, is_prerelease


def get_regex():
# Following REGEX is suggested on semver.org
# https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string
return re.compile(
r'^'
r'(?P<major>0|[1-9]\d*)'
r'\.'
r'(?P<minor>0|[1-9]\d*)'
r'\.'
r'(?P<patch>0|[1-9]\d*)'
r'(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?'
r'(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$')


def get_major_release_version(major):
major += 1
minor = 0
patch = 0
return major, minor, patch


def get_minor_release_version(major, minor):
minor += 1
patch = 0
return major, minor, patch


def get_patch_release_version(major, minor, patch, is_prerelease):
if is_prerelease:
# Leave values as is because current version without `prerelease` is new patch version
return major, minor, patch
return major, minor, patch + 1


if __name__ == "__main__":

version_type = get_arg(1)
release_type = get_arg(2)

current_version = get_current_version()

match version_type:
case "release-version":
new_version = get_release_version(release_type, current_version)
case "version-tag":
new_version = get_version_tag(release_type, current_version)
case "snapshot-version":
new_version = get_snapshot_version(release_type, current_version)
case _:
print(
"First arg has to be `release-version`, `version-tag` or `snapshot-version`.")
sys.exit()

print(new_version)
56 changes: 56 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: prepare-release

on:
workflow_dispatch:
inputs:
release:
description: Type of release
required: true
type: choice
options:
- PATCH
- MINOR
- MAJOR
default: PATCH

jobs:
prepare:
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v4

# SSH connection with keys is necessary to allow `git push`
- name: Ensure correct SSH connection
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

- uses: actions/setup-java@v3
with:
java-version: 11
distribution: corretto
cache: maven

- name: Determine new versions
run: |
echo "release_version=$(./.github/workflows/maven-version-determiner.py release-version $release_type)" >> "$GITHUB_ENV"
echo "snapshot_version=$(./.github/workflows/maven-version-determiner.py snapshot-version $release_type)" >> "$GITHUB_ENV"
echo "version_tag=$(./.github/workflows/maven-version-determiner.py version-tag $release_type)" >> "$GITHUB_ENV"
env:
release_type: ${{ inputs.release }}

- name: Configure Git user
run: |
git config user.email "actions@users.noreply.github.com"
git config user.name "GitHub Actions"

- name: Prepare with Maven release plugin
run: >
mvn
--batch-mode
-Dresume=false
-Drelease-version=$release_version
-Dtag=$version_tag
-DdevelopmentVersion=$snapshot_version
release:prepare
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,20 @@ mvn clean verify

If you are a maintainer, you can release a new version by doing the following:

- Merge the changes that need to be released into the `master` branch
- Checkout on to master locally and pull the latest changes
- Run `mvn release:prepare`, this will generate 2 commits that will bump the version of the github-java-client
- Push these changes to master
- Once the [release pipeline](https://github.com/spotify/github-java-client/actions/workflows/release.yml) has completed, the changes will have been tagged
- [Navigate to the tag](https://github.com/spotify/github-java-client/tags) associated with the changes and generate a manual release
- Once the release is generated, select the "Set as the latest release" checkbox and publish the release
- Trigger the workflow [prepare-release](./.github/workflows/prepare-release.yml) through the
[web UI](https://github.com/spotify/github-java-client/actions/workflows/prepare-release.yml)
- Select whether the new release should be a `major`, `minor` or `patch` release
- Trigger the release preparation on the `master` branch
- Pushes of this workflow will trigger runs of the workflow
[release](https://github.com/spotify/github-java-client/actions/workflows/release.yml)
- Once the
[release pipeline](https://github.com/spotify/github-java-client/actions/workflows/release.yml)
has completed for the release tag, the new release will be available on Maven Central and the
changes can be released on GitHub
- [Navigate to the tag](https://github.com/spotify/github-java-client/tags) associated with the
changes and generate a manual release
- Once the release is generated, select the "Set as the latest release" checkbox and publish the
release

## Notes about maturity

Expand Down