generated from SAP/repository-template
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3cac67b
commit 4a1603a
Showing
3 changed files
with
317 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
name: "Prepare Release" | ||
|
||
on: | ||
workflow_dispatch: | ||
inputs: | ||
branch: | ||
description: "The Branch to Release From" | ||
required: false | ||
default: "main" | ||
release-version: | ||
description: "The Version to Release" | ||
required: false | ||
|
||
jobs: | ||
bump-version: | ||
name: "Bump Version" | ||
outputs: | ||
current-version: ${{ steps.determine-versions.outputs.CURRENT_SNAPSHOT }} | ||
release-version: ${{ steps.determine-versions.outputs.RELEASE_VERSION }} | ||
new-version: ${{ steps.determine-versions.outputs.NEW_SNAPSHOT }} | ||
release-branch: ${{ steps.prepare-release.outputs.BRANCH_NAME }} | ||
release-commit: ${{ steps.prepare-release.outputs.RELEASE_COMMIT_ID }} | ||
release-tag: ${{ steps.prepare-release.outputs.TAG_NAME }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: "Checkout Repository" | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.event.inputs.branch }} | ||
|
||
- name: "Determine Versions" | ||
id: determine-versions | ||
run: python .pipeline/scripts/get-release-versions.py | ||
env: | ||
INPUT_VERSION: ${{ github.event.inputs.release-version }} | ||
|
||
- run: "echo Release Version: ${{ steps.determine-versions.outputs.RELEASE_VERSION }}" | ||
- run: "echo Current Version: ${{ steps.determine-versions.outputs.CURRENT_SNAPSHOT }}" | ||
- run: "echo New Version: ${{ steps.determine-versions.outputs.NEW_SNAPSHOT }}" | ||
|
||
- name: "Set Release Version to ${{ steps.determine-versions.outputs.RELEASE_VERSION }}" | ||
id: prepare-release | ||
run: | | ||
# NOTE: If you change this pattern here, also adjust perform_release.yml: | ||
BRANCH_NAME=RELEASE-${{ steps.determine-versions.outputs.RELEASE_VERSION }} | ||
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT | ||
git switch --create $BRANCH_NAME | ||
python .pipeline/scripts/set-release-versions.py --version ${{ steps.determine-versions.outputs.RELEASE_VERSION }} | ||
git add . | ||
git commit -m "Update to version ${{ steps.determine-versions.outputs.RELEASE_VERSION }}" | ||
# We need to get the commit id, and push the branch so the release tag will point at the right commit afterwards | ||
RELEASE_COMMIT_ID=$(git log -1 --pretty=format:"%H") | ||
echo "RELEASE_COMMIT_ID=$RELEASE_COMMIT_ID" >> $GITHUB_OUTPUT | ||
TAG_NAME=rel/${{ steps.determine-versions.outputs.RELEASE_VERSION }} | ||
git tag $TAG_NAME $RELEASE_COMMIT_ID | ||
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_OUTPUT | ||
git push origin $BRANCH_NAME | ||
git push origin $TAG_NAME | ||
create-release: | ||
name: "Create GitHub Release" | ||
needs: [ bump-version, run-ci ] | ||
outputs: | ||
release-name: ${{ steps.create-release.outputs.RELEASE_NAME }} | ||
release-url: ${{ steps.create-release.outputs.RELEASE_URL }} | ||
permissions: | ||
contents: write # needed to create a new release | ||
actions: read # needed to download the artifacts from the CI workflow | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: "Checkout repository" | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ needs.bump-version.outputs.release-branch }} | ||
|
||
- name: "Setup java" | ||
uses: actions/setup-java@v4 | ||
with: | ||
distribution: "temurin" | ||
java-version: ${{ env.JAVA_VERSION }} | ||
cache: 'maven' | ||
|
||
- name: "Build SDK" | ||
run: | | ||
MVN_ARGS="${{ env.MVN_MULTI_THREADED_ARGS }} clean install -DskipTests -DskipFormatting" | ||
mvn $MVN_ARGS | ||
- name: "Create Release" | ||
id: create-release | ||
run: | | ||
tar -caf apidocs-${{ needs.bump-version.outputs.release-version }}.tar.gz -C .targets/target/reports/apidocs/ . | ||
tar -caf release-${{ needs.bump-version.outputs.release-version }}.tar.gz -C .release-artifacts/ . | ||
RELEASE_NAME="rel/${{ needs.bump-version.outputs.release-version }}" | ||
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_OUTPUT | ||
RELEASE_URL=$(gh release create "$RELEASE_NAME" \ | ||
--target ${{ needs.bump-version.outputs.release-commit }} \ | ||
--title "Release ${{ needs.bump-version.outputs.release-version }}" \ | ||
--draft --generate-notes \ | ||
apidocs-${{ needs.bump-version.outputs.release-version }}.tar.gz \ | ||
release-${{ needs.bump-version.outputs.release-version }}.tar.gz) | ||
echo "RELEASE_URL=$RELEASE_URL" >> $GITHUB_OUTPUT | ||
env: | ||
GH_TOKEN: ${{ github.token }} | ||
|
||
create-code-pr: | ||
name: "Create Code PR" | ||
needs: [ bump-version, run-ci, create-release, create-docs-pr, create-release-notes-pr ] | ||
outputs: | ||
pr-url: ${{ steps.create-code-pr.outputs.PR_URL }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: "Checkout Repository" | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ needs.bump-version.outputs.release-branch }} | ||
|
||
- name: "Set New Version" | ||
run: | | ||
python .pipeline/scripts/set-release-versions.py --version ${{ needs.bump-version.outputs.new-version }} | ||
git add . | ||
git commit -m "Update to version ${{ needs.bump-version.outputs.new-version }}" | ||
git push | ||
- name: "Create Code PR" | ||
run: | | ||
COMMIT_URL=${{ github.event.repository.html_url }}/commit/${{ needs.bump-version.outputs.release-commit }} | ||
PR_URL=$(gh pr create --title "Release ${{ needs.bump-version.outputs.release-version }}" --body "## TODOs | ||
- [ ] Review the changes in [the release commit]($COMMIT_URL) | ||
- [ ] Update the Release notes | ||
- [ ] Review the [Draft Release](${{ needs.create-release.outputs.release-url }}) | ||
- [ ] Review **and approve** this PR | ||
- [ ] Trigger the [Perform Release Workflow](${{ github.event.repository.html_url }}/actions/workflows/perform-release.yml) | ||
- [ ] Once the `Perform Release` workflow is through, head over to the [OSS Repository](https://oss.sonatype.org/#stagingRepositories) and log in with the credentials in the Team Password Safe. There should be a staged release. Check whether everything looks good and, if so, publish the release.") | ||
echo "PR_URL=$PR_URL" >> $GITHUB_OUTPUT | ||
env: | ||
# GH_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }} | ||
|
||
handle-failure: | ||
runs-on: ubuntu-latest | ||
needs: [ bump-version, run-ci, create-release, create-docs-pr, create-release-notes-pr, create-code-pr ] | ||
permissions: | ||
contents: write # needed to delete the GitHub release | ||
if: ${{ failure() }} | ||
steps: | ||
- name: "Checkout Repository" | ||
uses: actions/checkout@v4 | ||
with: | ||
ref: ${{ github.event.inputs.branch }} | ||
|
||
- name: "Delete Release" | ||
if: ${{ needs.create-release.outputs.release-url != '' }} | ||
run: gh release delete --repo "${{ github.repository }}" ${{ needs.create-release.outputs.release-name }} --yes | ||
env: | ||
GH_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }} | ||
continue-on-error: true | ||
|
||
- name: "Delete Release Branch" | ||
if: ${{ needs.bump-version.outputs.release-branch != '' }} | ||
run: git push --delete origin ${{ needs.bump-version.outputs.release-branch }} | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }} | ||
continue-on-error: true | ||
|
||
- name: "Delete Release Tag" | ||
if: ${{ needs.bump-version.outputs.release-tag != '' }} | ||
run: git push --delete origin ${{ needs.bump-version.outputs.release-tag }} | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.BOT_SDK_JS_FOR_DOCS_REPO_PR }} | ||
continue-on-error: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import os | ||
import re | ||
import json | ||
import subprocess | ||
import unittest | ||
|
||
def determine_versions(current_snapshot, input_version): | ||
|
||
milestone_version_regex = r'^\d+\.\d+\.\d+-M\d+$' | ||
|
||
if not input_version: | ||
input_version = re.sub(r'-SNAPSHOT', '', current_snapshot) | ||
elif re.match(milestone_version_regex, input_version): | ||
return {'input_version': input_version, 'current_snapshot': current_snapshot, 'new_snapshot_version': current_snapshot} | ||
|
||
version_parts = [int(x) for x in input_version.split('.')] | ||
new_snapshot_version = f"{version_parts[0]}.{version_parts[1] + 1}.0-SNAPSHOT" | ||
|
||
return {'input_version': input_version, 'current_snapshot': current_snapshot, 'new_snapshot_version': new_snapshot_version} | ||
|
||
class TestDetermineVersions(unittest.TestCase): | ||
|
||
def test_no_input_provided(self): | ||
self.assertEqual(determine_versions('1.2.3-SNAPSHOT', None), | ||
{'input_version': '1.2.3', 'current_snapshot': '1.2.3-SNAPSHOT','new_snapshot_version': '1.3.0-SNAPSHOT'}) | ||
|
||
def test_input_provided(self): | ||
self.assertEqual(determine_versions('1.2.3-SNAPSHOT', '2.1.0'), | ||
{'input_version': '2.1.0', 'current_snapshot': '1.2.3-SNAPSHOT','new_snapshot_version': '2.2.0-SNAPSHOT'}) | ||
|
||
def test_input_milestone_provided(self): | ||
self.assertEqual(determine_versions('1.2.3-SNAPSHOT', '1.2.3-M2'), | ||
{'input_version': '1.2.3-M2', 'current_snapshot': '1.2.3-SNAPSHOT','new_snapshot_version': '1.2.3-SNAPSHOT'}) | ||
|
||
def write_versions_github_output(): | ||
with open("latest.json", "r") as file: | ||
current_snapshot = json.load(file)["version"] | ||
|
||
input_version = os.environ.get("INPUT_VERSION") | ||
|
||
calculated_versions = determine_versions(current_snapshot, input_version) | ||
|
||
github_output = os.environ.get("GITHUB_OUTPUT") | ||
with open(github_output, "a") as f: | ||
f.write(f"RELEASE_VERSION={calculated_versions['input_version']}\n") | ||
f.write(f"CURRENT_SNAPSHOT={calculated_versions['current_snapshot']}\n") | ||
f.write(f"NEW_SNAPSHOT={calculated_versions['new_snapshot_version']}\n") | ||
|
||
if __name__ == '__main__': | ||
write_versions_github_output() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import argparse | ||
import os | ||
import re | ||
import sys | ||
from xml.etree import ElementTree | ||
|
||
class _CommentedTreeBuilder(ElementTree.TreeBuilder): | ||
def __init__(self, *args, **kwargs): | ||
super(_CommentedTreeBuilder, self).__init__(*args, **kwargs) | ||
|
||
def comment(self, data): | ||
self.start(ElementTree.Comment, {}) | ||
self.data(data) | ||
self.end(ElementTree.Comment) | ||
|
||
def _update_readme(sdk_version): | ||
_update_file("README.md", r'(maven_central-)(.+)(-blue\.svg)', r'\g<1>%s\g<3>' % sdk_version) | ||
_update_file("README.md", r'(a:sdk-core%20AND%20v:)(.+\))', r'\g<1>%s)' % sdk_version) | ||
|
||
def _update_pom_files(sdk_version): | ||
_update_version_tags(sdk_version) | ||
|
||
with open("latest.json", "w") as f: | ||
f.write('{\n "version": "%s"\n}\n' % sdk_version) | ||
|
||
|
||
def _update_version_tags(sdk_version): | ||
for root, dirs, files in os.walk(os.getcwd()): | ||
for file in files: | ||
if file == "pom.xml": | ||
_update_file(os.path.join(root, file), r'(<sdk\.version>)(.*?)(</sdk\.version>)', r'\g<1>%s\g<3>' % sdk_version) | ||
|
||
|
||
def _update_version_tag(pom_file, sdk_version): | ||
ElementTree.register_namespace("", "http://maven.apache.org/POM/4.0.0") | ||
|
||
parser = ElementTree.XMLParser(target=_CommentedTreeBuilder()) | ||
|
||
try: | ||
tree = ElementTree.parse(pom_file, parser=parser) | ||
root = tree.getroot() | ||
child_to_parent = {c: p for p in root.iter() for c in p} | ||
except: | ||
print(f"ERROR: Failed to parse POM file {pom_file}.") | ||
raise | ||
|
||
namespaces = {'xmlns': 'http://maven.apache.org/POM/4.0.0'} | ||
|
||
version_tags = root.findall(".//xmlns:version", namespaces=namespaces) | ||
project_version_tags = list(filter(lambda x: child_to_parent[x].tag.endswith("project"), version_tags)) | ||
|
||
if len(project_version_tags) == 1: | ||
project_version_tags[0].text = sdk_version | ||
|
||
parent_tags = root.findall(".//xmlns:parent", namespaces=namespaces) | ||
|
||
if len(parent_tags) == 1: | ||
parent_tags[0].find("xmlns:version", namespaces=namespaces).text = sdk_version | ||
|
||
# not sure why, but tree.write() (as used in other functions) produces a differently formatted XML declaration... | ||
# that's why we the file is written in this kind of hacky manner | ||
with open(pom_file, "w") as f: | ||
f.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + ElementTree.tostring(root).decode() + "\n") | ||
|
||
def _update_file(file_name, search_str, replace_str): | ||
with open(file_name) as f: | ||
result = f.read() | ||
result = re.sub(search_str, replace_str, result) | ||
|
||
with open(file_name, "w") as f: | ||
f.write(result) | ||
|
||
def set_sdk_version(full_version): | ||
_update_pom_files(full_version) | ||
if "SNAPSHOT" not in full_version: | ||
_update_readme(full_version) | ||
|
||
if __name__ == '__main__': | ||
try: | ||
parser = argparse.ArgumentParser(description='SAP Cloud SDK - Versioning script.') | ||
|
||
parser.add_argument('--version', | ||
metavar='VERSION', | ||
help='The version to be set.', required=True) | ||
args = parser.parse_args() | ||
|
||
set_sdk_version(args.version) | ||
|
||
except KeyboardInterrupt: | ||
sys.exit(1) |