diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 240ded4..860fa1f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -6,7 +6,7 @@ Thank you so much for wanting to contribute to eJMask! Here are a few important 2. Pull requests are great for small fixes for bugs, documentation, etc. 3. Code contributions require updating relevant documentation. -This project takes all contributions through [pull requests](https://help.github.com/articles/using-pull-requests). Code should *not* be pushed directly to `master`. +This project takes all contributions through [pull requests][pull-request-blog]. Code should *not* be pushed directly to `master`. The following guidelines apply to all contributors. @@ -22,7 +22,61 @@ All types of contributions, from minor documentation changes to new capabilities * Submit a pull request to the repository. * Update the `eJMask` GitHub issue with the generated pull request link. -## General Guidelines +### Git Workflow + +1. Go to GitHub and fork the repository [ebay/ejmask][fork-repo]. +2. Clone your fork to your local workspace: + ```commandline + git clone git@github.com:/ejmask.git + ``` +3. Create a new [feature branch][create-branch]. +4. Make your changes, perform a self-review, build, and test. +5. Push your changes to the [remote fork][push-commits]. +6. Raise a [pull request][create-pr]. + +```mermaid +stateDiagram-v2 + state upstream <> + state fork_state <> + state local_state <> + note left of upstream + ebay/ejmask + end note + upstream --> fork_state: fork + note left of fork_state + {user-name}/ejmask + end note + fork_state --> local_state: checkout + note right of local_state + impl/new_feature + end note + state FeatureDev { + local_state --> SelfReview : build test + local_state --> local_state: commit + SelfReview --> SelfReview: lint + SelfReview --> local_state: fix + } + local_state --> fork_state: push + fork_state --> local_state: fetch + fork_state --> Draft: pull_request + state PullRequest { + Draft --> ReadyToReview + Draft --> Draft: Self review + ReadyToReview --> ReadyToReview: Peer review + ReadyToReview --> Approved + } + Approved --> upstream: merge + upstream --> fork_state: pull +``` +> Please keep your branch up to date by [rebasing][rebase-git] upstream changes from the develop branch. + +## Development +### Pre-requisites +- JDK 8 +- Maven 3.6.3 +- python3 (for development scripts) + +### General Guidelines * Only one logical change per commit. * Do not mix whitespace changes with functional code changes. @@ -36,15 +90,17 @@ All types of contributions, from minor documentation changes to new capabilities * The project already has good test coverage, so look at some of the existing tests if you're unsure how to go about it. * Please squash all commits for a change into a single commit (this can be done using `git rebase -i`). -## Commit Message Guidelines - -* Provide a brief description of the change in the first line. -* Insert a single blank line after the first line. -* Provide a detailed description of the change in the following lines, breaking paragraphs where needed. -* The first line should be limited to 50 characters and should not end in a period. -* Subsequent lines should be wrapped at 72 characters. +### Versioning +* We are using [Semantic Versioning](https://semver.org/). +* We are following the format `MAJOR.MINOR.PATCH`. + * `MAJOR` : fundamental changes. + * `MINOR` : incompatible changes. + * `PATCH` : backward-compatible changes & bug fixes. +* Use `version_update.py` to update the version in the `pom.xml` file. +* Use snapshot versions for development & testing +* Update the version to release when you commit. -## Java Guidelines +### Java Guidelines - Please make sure: * Source code is always formatted before commit. @@ -54,3 +110,37 @@ All types of contributions, from minor documentation changes to new capabilities * Trailing whitespace on all lines. * All unused imports. * Empty blocks. + +### Build +```shell +mvn clean install --settings settings.xml --batch-mode +``` + +### Commit Message Guidelines +* +* Provide a brief description of the change in the first line. +* Insert a single blank line after the first line. +* Provide a detailed description of the change in the following lines, breaking paragraphs where needed. +* The first line should be limited to 50 characters and should not end in a period. +* Subsequent lines should be wrapped at 72 characters. + +## Pull Request Guidelines + +- Ensure the pull request has a description of the change. +- Ensure the pull request has a proper title describing the change. + - Prefix the title with: + - `IMPL` for a new change. + - `FIX` for a bug fix. + - `DOC` for a documentation change. + - `DEV` for refactoring. + - For `IMPL` and non-compatible refactoring or bug fixes, increment the version to the next major (e.g., `1.0.0` -> `1.1.0`). + - For all other changes, increment the minor version (e.g., `1.0.0` -> `1.0.1`). + > eg: DEV: Refactored the code to use a new pattern builder + +[create-branch]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-and-deleting-branches-within-your-repository +[create-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork +[clone-repo]: https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository +[fork-repo]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo +[push-commits]: https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository +[pull-request-blog]: https://help.github.com/articles/using-pull-requests +[rebase-git]: https://docs.github.com/en/get-started/using-git/about-git-rebase diff --git a/README.md b/README.md index 15a7ae7..2d3a4e9 100644 --- a/README.md +++ b/README.md @@ -228,19 +228,19 @@ You can download source and binaries from our [release page](https://github.com/ Alternatively you can pull it from the central Maven repositories: ### Using in your maven project. - +> Please check the release version before adding to your project. ```xml com.ebay.ejmask ejmask-bom - 1.1.0 + 2.0.0 ``` ### Using in your Gradle Project. ```groovy -compile group: 'com.ebay.ejmask', name: 'ejmask-bom', version: '1.1.0' +compile group: 'com.ebay.ejmask', name: 'ejmask-bom', version: '2.0.0' ``` ## Roadmap diff --git a/ejmask-api/pom.xml b/ejmask-api/pom.xml index f7e2c95..1f59765 100644 --- a/ejmask-api/pom.xml +++ b/ejmask-api/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-parent - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-api diff --git a/ejmask-bom/pom.xml b/ejmask-bom/pom.xml index d0a94b5..c3b9101 100644 --- a/ejmask-bom/pom.xml +++ b/ejmask-bom/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-parent - 1.2.0-SNAPSHOT + ${revision}${changelist} ../pom.xml diff --git a/ejmask-core/pom.xml b/ejmask-core/pom.xml index f8ac649..7a0738c 100644 --- a/ejmask-core/pom.xml +++ b/ejmask-core/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-parent - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-core diff --git a/ejmask-extensions/pom.xml b/ejmask-extensions/pom.xml index 2fc7d3c..f169c27 100644 --- a/ejmask-extensions/pom.xml +++ b/ejmask-extensions/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-parent - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-extensions diff --git a/ejmask-spring/ejmask-spring-autoconfig/pom.xml b/ejmask-spring/ejmask-spring-autoconfig/pom.xml index 04b16cb..411e52b 100644 --- a/ejmask-spring/ejmask-spring-autoconfig/pom.xml +++ b/ejmask-spring/ejmask-spring-autoconfig/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-spring - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-spring-autoconfig diff --git a/ejmask-spring/ejmask-spring-boot/pom.xml b/ejmask-spring/ejmask-spring-boot/pom.xml index 194d8bf..459941d 100644 --- a/ejmask-spring/ejmask-spring-boot/pom.xml +++ b/ejmask-spring/ejmask-spring-boot/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-spring - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-spring-boot diff --git a/ejmask-spring/ejmask-spring-core/pom.xml b/ejmask-spring/ejmask-spring-core/pom.xml index 373c19e..9224bd5 100644 --- a/ejmask-spring/ejmask-spring-core/pom.xml +++ b/ejmask-spring/ejmask-spring-core/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-spring - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-spring-core diff --git a/ejmask-spring/pom.xml b/ejmask-spring/pom.xml index 24894ed..580c4e5 100644 --- a/ejmask-spring/pom.xml +++ b/ejmask-spring/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-parent - 1.2.0-SNAPSHOT + ${revision}${changelist} ejmask-spring @@ -15,17 +15,4 @@ ejmask-spring-boot ejmask-spring-autoconfig - - - - - - org.springframework.boot - spring-boot-dependencies - 2.7.4 - import - pom - - - diff --git a/pom.xml b/pom.xml index 04a743b..c45c173 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.ebay.ejmask ejmask-parent - 1.2.0-SNAPSHOT + ${revision}${changelist} pom @@ -27,6 +27,8 @@ UTF-8 1.8 1.8 + 1.2.0 + diff --git a/version_update.py b/version_update.py index a6562bc..7e32981 100644 --- a/version_update.py +++ b/version_update.py @@ -1,78 +1,158 @@ -## -## This script is used to update pom version -## -import re -import subprocess +import xml.etree.ElementTree as ET import sys -from xml.etree import ElementTree as ET +import xml.dom.minidom as minidom +import re + +pom_file = 'pom.xml' + +""" +This script updates the version information in a Maven POM file. + +Usage: + python version_update.py + +Options: + - major : (2.8.0 -> 3.0.0) + - minor : (2.8.0 -> 2.9.0-SNAPSHOT) + - patch : (2.8.0 -> 2.8.1-SNAPSHOT) + - release : (2.9.0-SNAPSHOT -> 2.9.0) +""" + +def read_pom_properties(): + """ + Reads the revision and changelist properties from the POM file. + Args: + pom_file (str): Path to the POM file. -## get root pom version -def get_root_pom_version(): - tree = ET.parse('./pom.xml') + Returns: + tuple: A tuple containing the revision and changelist values. + + Example: + revision, changelist = read_pom_properties('pom.xml') + """ + tree = ET.parse(pom_file) root = tree.getroot() - for build in root: - if (build.tag == "{http://maven.apache.org/POM/4.0.0}version"): - return build.text - raise ValueError("Pom must need to have a version tag.") - - -# get the next version -def get_next_version(current_version, version_command): - # cleanup - base_version = current_version.replace("-SNAPSHOT", "").replace("-RELEASE", "").replace("-PATCH", "") - parts = base_version.split('.') - # - if version_command == "next-minor": - # increment the version to next minor SNAPSHOT - parts[-1] = str(int(parts[-1]) + 1) - return '.'.join(parts) - elif version_command == "next-major": - # increment the version to next minor - parts[1] = str(int(parts[1]) + 1) - return '.'.join(parts) + namespace = {'mvn': 'http://maven.apache.org/POM/4.0.0'} + revision = root.find('mvn:properties/mvn:revision', namespace).text + changelist = root.find('mvn:properties/mvn:changelist', namespace).text + return revision, changelist + +def get_version(revision, changelist, version_type): + """ + Generates the new version based on the version type. + + Args: + revision (str): The current revision. + changelist (str): The current changelist. + version_type (str): The type of version update ('major', 'minor', 'patch', 'release'). + + Returns: + tuple: A tuple containing the new revision and changelist values. + + Example: + new_revision, new_changelist = get_version('2.8.0', '-SNAPSHOT', 'minor') + """ + parts = revision.split('.') + major, minor, patch = int(parts[0]), int(parts[1]), int(parts[2]) + if version_type == 'major': + major += 1 + minor = 0 + patch = 0 + changelist = '-SNAPSHOT' + elif version_type == 'minor': + minor += 1 + patch = 0 + changelist = '-SNAPSHOT' + elif version_type == 'patch': + patch += 1 + changelist = '-SNAPSHOT' + elif version_type == 'release' and changelist == '-SNAPSHOT': + changelist = '' + new_revision = f"{major}.{minor}.{patch}" + return new_revision, changelist + +def print_help(): + print("Usage >: python version_update.py \n options: " + "\n - major : (2.8.0 -> 3.0.0-SNAPSHOT)" + "\n - minor : (2.8.0 -> 2.1.0-SNAPSHOT)" + "\n - patch : (2.8.0 -> 2.8.1-SNAPSHOT)" + "\n - release : (2.9.0-SNAPSHOT -> 2.9.0)") + +def update_pom(version_old, revision, changelist): + """ + Updates the POM file with the new version information. + + Args: + version_old (str): The old version string. + revision (str): The new revision. + changelist (str): The new changelist. + pom_file (str): Path to the POM file. + + Example: + update_pom('2.8.0-SNAPSHOT', '2.8.1', '', 'pom.xml') + """ + print(f"updating pom version from {version_old} -> {revision}{changelist}") + if input("Do you want to update the pom version (y/n): ").lower() != 'y': + sys.exit(0) + dom = minidom.parse(pom_file) + properties = dom.getElementsByTagName('properties')[0] + revision_elements = dom.getElementsByTagName('revision') + changelist_elements = dom.getElementsByTagName('changelist') + + if revision_elements and revision_elements[0].firstChild: + revision_elements[0].firstChild.nodeValue = revision else: - # manual version - pattern = r'^\d+\.\d+\.\d+(-SNAPSHOT|-RELEASE)?$' - if not re.match(pattern, version_command): - raise ValueError(f"Invalid version format {version_command}") - return version_command - - -def execute_maven_command(version): - command = f"mvn versions:set -DnewVersion={version} -DgenerateBackupPoms=false" - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = process.communicate() - if process.returncode != 0: - print(f"Error executing command: {stderr.decode()}") + new_revision = dom.createElement('revision') + new_revision.appendChild(dom.createTextNode(revision)) + properties.appendChild(new_revision) + + if changelist_elements and changelist_elements[0].firstChild: + changelist_elements[0].firstChild.nodeValue = changelist else: - print(stdout.decode()) - -def replace_in_specified_module(version, *modules): - for module in modules: - command = f"mvn versions:set -DnewVersion={version} -DgenerateBackupPoms=false -pl {module}" - process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = process.communicate() - if process.returncode != 0: - print(f"Error executing command: {stderr.decode()}") - else: - print(stdout.decode()) + for elem in changelist_elements: + if not elem.firstChild or not elem.firstChild.nodeValue.strip(): + properties.removeChild(elem) + new_changelist = dom.createElement('changelist') + new_changelist.appendChild(dom.createTextNode(changelist)) + properties.appendChild(new_changelist) + + with open(pom_file, 'w') as f: + dom.writexml(f) + +def update_readme(new_version, updated_changelist): + if(updated_changelist == '-SNAPSHOT'): + return + + # Read the content of the README.md file + with open('README.md', 'r') as file: + content = file.read() + + # Define the regex patterns for Maven and Gradle version updates + maven_pattern = r'()(\d+\.\d+\.\d+)()' + gradle_pattern = r"(version: ')(\d+\.\d+\.\d+)(')" + + # Replace the old version with the new version + updated_content = re.sub(maven_pattern, r'\g<1>' + new_version + r'\g<3>', content) + updated_content = re.sub(gradle_pattern, r'\g<1>' + new_version + r'\g<3>', updated_content) + + # Write the updated content back to the README.md file + with open('README.md', 'w') as file: + file.write(updated_content) + + print("Version updated successfully.") if __name__ == "__main__": if len(sys.argv) != 2: - print("Usage >> python version_update.py next | next-minor | next-major ") + print_help() else: - version_new = sys.argv[1] - version_current = get_root_pom_version() - version_next = get_next_version(version_current, version_new) - print(f"Updating the pom version from {version_current} to {version_next}") - print("Press `Y` to continue...") - if input().lower() == 'y': - print("Updating the version...") - execute_maven_command(version_next) - print("Updating the version in specified modules...") - # please disable this line if you don't have any module - replace_in_specified_module(version_next, "gateway-bom") - print("Done...") + revision, changelist = read_pom_properties() + changelist = changelist or '' + version_old = revision + changelist + version_type = sys.argv[1] + if version_type in ['major', 'minor', 'patch', 'release']: + uprated_revision, updated_changelist = get_version(revision, changelist, version_type) + update_pom(version_old, uprated_revision, updated_changelist) + update_readme(uprated_revision, updated_changelist) else: - print("Operation cancelled...") + print_help() \ No newline at end of file