diff --git a/versions-maven-plugin/pom.xml b/versions-maven-plugin/pom.xml index c7a9dee648..872b61c92f 100644 --- a/versions-maven-plugin/pom.xml +++ b/versions-maven-plugin/pom.xml @@ -169,6 +169,14 @@ javax.inject + + + + org.eclipse.jgit + org.eclipse.jgit + 5.13.3.202401111512-r + + commons-codec diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/invoker.properties new file mode 100644 index 0000000000..852932e8a7 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/invoker.properties @@ -0,0 +1,2 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm +invoker.buildResult = failure diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/pom.xml new file mode 100644 index 0000000000..78bc48a827 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-0-commits-0-tags + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/setup.groovy new file mode 100644 index 0000000000..b03e421918 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/setup.groovy @@ -0,0 +1,11 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/verify.groovy new file mode 100644 index 0000000000..e342730544 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-0-commits-0-tags/verify.groovy @@ -0,0 +1,12 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /Caused by: org.apache.maven.plugin.MojoExecutionException: SCM repo has no head\/commits\./ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "SCM repo should have no head/commits" diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/invoker.properties new file mode 100644 index 0000000000..b86b79ee0e --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/invoker.properties @@ -0,0 +1 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/pom.xml new file mode 100644 index 0000000000..4f6aef7e24 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-1-commit-0-tags + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/setup.groovy new file mode 100644 index 0000000000..4053e7dd39 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/setup.groovy @@ -0,0 +1,16 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') +exec('git config user.email "you@example.com"') +exec('git config user.name "Your Name"') + +exec('git add test.txt') +exec('git commit -m initial-commit') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/verify.groovy new file mode 100644 index 0000000000..3c42ac51e6 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-1-commit-0-tags/verify.groovy @@ -0,0 +1,19 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /\[INFO\] Property 'revision' set to: (.+)/ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "Version information not found in log file" + +// Extract the version from the matched group +def actualVersion = matcher[0][1] + +def expectedVersion = '0.0.1-1-SNAPSHOT' + +assert actualVersion == expectedVersion : "Expected version '${expectedVersion}', but found '${actualVersion}'" diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/invoker.properties new file mode 100644 index 0000000000..03ed4f49ed --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/invoker.properties @@ -0,0 +1 @@ +invoker.goals=-X ${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/pom.xml new file mode 100644 index 0000000000..edb2c32957 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-4-commits-1-vtag + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/setup.groovy new file mode 100644 index 0000000000..d529d2ab13 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/setup.groovy @@ -0,0 +1,30 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') +exec('git config user.email "you@example.com"') +exec('git config user.name "Your Name"') + +exec('git add test.txt') +exec('git commit -m initial-commit') +exec('git tag 1.1.1') +exec('git tag') + +testFile << 'content2' +exec('git add test.txt') +exec('git commit -m commit_no2') + +testFile << 'content3' +exec('git add test.txt') +exec('git commit -m commit_no3') + +testFile << 'content4' +exec('git add test.txt') +exec('git commit -m commit_no4') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/verify.groovy new file mode 100644 index 0000000000..3ddc76fc89 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-4-commits-1-vtag/verify.groovy @@ -0,0 +1,19 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /\[INFO\] Property 'revision' set to: (.+)/ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "Version information not found in log file" + +// Extract the version from the matched group +def actualVersion = matcher[0][1] + +def expectedVersion = '1.1.2-4-SNAPSHOT' + +assert actualVersion == expectedVersion : "Expected version '${expectedVersion}', but found '${actualVersion}'" diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/invoker.properties new file mode 100644 index 0000000000..b86b79ee0e --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/invoker.properties @@ -0,0 +1 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/pom.xml new file mode 100644 index 0000000000..f5de5973f3 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-latest-commit + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/setup.groovy new file mode 100644 index 0000000000..a8873ec840 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/setup.groovy @@ -0,0 +1,17 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') +exec('git config user.email "you@example.com"') +exec('git config user.name "Your Name"') + +exec('git add test.txt') +exec('git commit -m initial-commit') +exec('git tag v1.1.1') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/verify.groovy new file mode 100644 index 0000000000..86e3aa9330 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-latest-commit/verify.groovy @@ -0,0 +1,19 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /\[INFO\] Property 'revision' set to: (.+)/ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "Version information not found in log file" + +// Extract the version from the matched group +def actualVersion = matcher[0][1] + +def expectedVersion = '1.1.1' + +assert actualVersion == expectedVersion : "Expected version '${expectedVersion}', but found '${actualVersion}'" diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/invoker.properties new file mode 100644 index 0000000000..0218ef30cc --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/invoker.properties @@ -0,0 +1 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm -DappendSnapshot=false diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/pom.xml new file mode 100644 index 0000000000..7acc0f9586 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-param-append-snapshot + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/setup.groovy new file mode 100644 index 0000000000..4053e7dd39 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/setup.groovy @@ -0,0 +1,16 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') +exec('git config user.email "you@example.com"') +exec('git config user.name "Your Name"') + +exec('git add test.txt') +exec('git commit -m initial-commit') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/verify.groovy new file mode 100644 index 0000000000..522dee4138 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-append-snapshot/verify.groovy @@ -0,0 +1,19 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /\[INFO\] Property 'revision' set to: (.+)/ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "Version information not found in log file" + +// Extract the version from the matched group +def actualVersion = matcher[0][1] + +def expectedVersion = '0.0.1-1' + +assert actualVersion == expectedVersion : "Expected version '${expectedVersion}', but found '${actualVersion}'" diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/invoker.properties new file mode 100644 index 0000000000..dd8cc8fc1c --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/invoker.properties @@ -0,0 +1 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm -DuseVersion=9.9.9-9 diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/pom.xml new file mode 100644 index 0000000000..08131ac356 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-param-use-versions + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/setup.groovy new file mode 100644 index 0000000000..4053e7dd39 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/setup.groovy @@ -0,0 +1,16 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') +exec('git config user.email "you@example.com"') +exec('git config user.name "Your Name"') + +exec('git add test.txt') +exec('git commit -m initial-commit') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/verify.groovy new file mode 100644 index 0000000000..4c2fe68a20 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-param-use-versions/verify.groovy @@ -0,0 +1,19 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /\[INFO\] Property 'revision' set to: (.+)/ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "Version information not found in log file" + +// Extract the version from the matched group +def actualVersion = matcher[0][1] + +def expectedVersion = '9.9.9-9' + +assert actualVersion == expectedVersion : "Expected version '${expectedVersion}', but found '${actualVersion}'" diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/invoker.properties b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/invoker.properties new file mode 100644 index 0000000000..ca4ce2b72e --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/invoker.properties @@ -0,0 +1 @@ +invoker.goals=${project.groupId}:${project.artifactId}:${project.version}:use-dynamic-version-from-scm -DpropertyName=version_from_scm diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/pom.xml b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/pom.xml new file mode 100644 index 0000000000..593dcc5ae8 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + localhost + it-dynamic-versioning-scm-tag-env-use-version + ${revision} + pom + ranges-update-report + http://localhost/ + diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/selector.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/selector.groovy new file mode 100644 index 0000000000..74f82d0070 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/selector.groovy @@ -0,0 +1,10 @@ +try { + // smoke test if we have a needed tools + def gitVersion = "git --version".execute() + gitVersion.consumeProcessOutput(System.out, System.out) + gitVersion.waitFor() + return gitVersion.exitValue() == 0 +} catch (Exception e) { + // some error occurs - we skip a test + return false +} diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/setup.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/setup.groovy new file mode 100644 index 0000000000..4053e7dd39 --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/setup.groovy @@ -0,0 +1,16 @@ +void exec(String command) { + def proc = command.execute(null, basedir) + proc.consumeProcessOutput(System.out, System.out) + proc.waitFor() + assert proc.exitValue() == 0 : "Command '${command}' returned status: ${proc.exitValue()}" +} + +def testFile = new File(basedir, 'test.txt') +testFile << 'content' + +exec('git init') +exec('git config user.email "you@example.com"') +exec('git config user.name "Your Name"') + +exec('git add test.txt') +exec('git commit -m initial-commit') diff --git a/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/verify.groovy b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/verify.groovy new file mode 100644 index 0000000000..603724bd4a --- /dev/null +++ b/versions-maven-plugin/src/it/it-dynamic-versioning-scm-tag-property-name/verify.groovy @@ -0,0 +1,19 @@ +// check that property was set + +def mavenLogFile = new File(basedir, 'build.log') +assert mavenLogFile.exists() : "Maven log file does not exist" + +// Read the log file +def logContent = mavenLogFile.text + +// Define a pattern to match the version output +def versionPattern = /\[INFO\] Property 'version_from_scm' set to: (.+)/ +def matcher = (logContent =~ versionPattern) +assert matcher.find() : "Version information not found in log file" + +// Extract the version from the matched group +def actualVersion = matcher[0][1] + +def expectedVersion = '0.0.1-1-SNAPSHOT' + +assert actualVersion == expectedVersion : "Expected version '${expectedVersion}', but found '${actualVersion}'" diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DynamicVersioningSCMPlugin.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DynamicVersioningSCMPlugin.java new file mode 100644 index 0000000000..bde84f1de7 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/DynamicVersioningSCMPlugin.java @@ -0,0 +1,240 @@ +package org.codehaus.mojo.versions; + +/* + * Copyright MojoHaus and Contributors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.File; +import java.io.IOException; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.maven.artifact.versioning.ComparableVersion; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.storage.file.FileRepositoryBuilder; + +/** + * Maven plugin that uses SCM/VCS to enable dynamic versioning based on your + * version control system. Goal will set the version in a property. + * + * @author Jimisola Laursen + * @since 2.17.0 + */ +@Mojo(name = "use-dynamic-version-from-scm", defaultPhase = LifecyclePhase.INITIALIZE) +public class DynamicVersioningSCMPlugin extends AbstractMojo { + + /** + * The Maven Project Object + * + * @since 2.17.0 + */ + @Parameter(defaultValue = "${project}", readonly = true, required = true) + private MavenProject project; + + /** + * The name of the property that will contain the resolved version. + * + * @since 2.17.0 + */ + @Parameter(property = "propertyName", defaultValue = "revision") + protected String propertyName; + + /** + * Whether the SNAPSHOT qualifier shall be apppended or not. + * + * @since 2.17.0 + */ + @Parameter(property = "appendSnapshot", defaultValue = "true") + protected boolean appendSnapshot; + + /** + * Use this version instead of resolving from SCM tag information. + * + * @since 2.17.0 + */ + @Parameter(property = "useVersion") + protected String useVersion; + + /** + * The default version used when SCM repository has no commit or no version + * tag. + * + * @since 2.17.0 + */ + @Parameter(property = "defaultVersion", defaultValue = "0.0.1") + protected String defaultVersion; + + // standard semantic versioning with an optional 'v' prefix + protected static final Pattern TAG_VERSION_PATTERN = Pattern.compile("refs/tags/(?:v)?((\\d+\\.\\d+\\.\\d+)(.*))"); + + public void execute() throws MojoExecutionException { + // limit JGits excessive logging + Logger.getLogger("org.eclipse.jgit").setLevel(Level.INFO); + + VersionInformation vi; + + Optional mayBeVersion = Optional.ofNullable(useVersion); + + if (mayBeVersion.isPresent()) { + vi = new VersionInformation(mayBeVersion.get()); + } else { + vi = getVersionFromSCM(); + } + + project.getProperties().setProperty(propertyName, vi.toString()); + getLog().info("Property '" + propertyName + "' set to: " + + project.getProperties().getProperty(propertyName)); + } + + /** + * Returns the resolved version based on SCM tag information for use with Maven + * CI. + * + * @throws org.apache.maven.plugin.MojoExecutionException Something wrong with + * the + * plugin itself + */ + protected VersionInformation getVersionFromSCM() throws MojoExecutionException { + // check for repository + try (Repository repository = new FileRepositoryBuilder() + .setGitDir(new File(".git")) + .readEnvironment() // scan environment GIT_* variables + .findGitDir() // scan up the file system tree + .build(); ) { + + if (repository.getDirectory() == null) { + throw new MojoExecutionException("Directory is not an SCM repository."); + } + + // check for latest commit + RevCommit latestCommit = getLatestCommit(repository); + + return getVersionFromCommit(repository, latestCommit); + } catch (IOException e) { + throw new MojoExecutionException("Error reading Git information.", e); + } + } + + protected RevCommit getLatestCommit(Repository repository) throws MojoExecutionException { + try (RevWalk revWalk = new RevWalk(repository)) { + ObjectId head = repository.resolve("HEAD"); + + if (head == null) { + throw new MojoExecutionException("SCM repo has no head/commits."); + } + + return revWalk.parseCommit(head); + } catch (IOException e) { + throw new MojoExecutionException("SCM repo most likely has no commits.", e); + } + } + + protected VersionInformation getVersionFromCommit(Repository repository, RevCommit latestCommit) + throws MojoExecutionException { + + try (Git git = Git.wrap(repository)) { + + List versionTags = getVersionedTagsForCommit(git, latestCommit); + + Optional ovi = findHighestVersion(versionTags); + + // latest commit has version tag(s), we use the highest one + if (ovi.isPresent()) { + return ovi.get(); + } + + Iterable commits = git.log().call(); + int count = 0; + for (RevCommit commit : commits) { + count++; + + versionTags = getVersionedTagsForCommit(git, commit); + + ovi = findHighestVersion(versionTags); + + if (ovi.isPresent()) { + VersionInformation vi = ovi.get(); + + vi.setPatch(vi.getPatch() + 1); + vi.setBuildNumber(count); + + return addSnapshotQualifier(vi); + } + } + + // no version tags in repository + return addSnapshotQualifier(new VersionInformation(defaultVersion + "-" + count)); + + } catch (GitAPIException e) { + throw new MojoExecutionException("Error reading Git information.", e); + } + } + + protected Optional findHighestVersion(List versionTags) { + Optional highestVersionString = versionTags.stream().max(this.new VersionComparator()); + + return highestVersionString.map(VersionInformation::new); + } + + protected List getVersionedTagsForCommit(Git git, RevCommit commit) throws GitAPIException { + // get tags directly associated with the commit + return git.tagList().call().stream() + .filter(tag -> tag.getObjectId().equals(commit.getId())) + .map(Ref::getName) + .filter(tagName -> { + Matcher matcher = TAG_VERSION_PATTERN.matcher(tagName); + return matcher.matches() && matcher.groupCount() > 0; + }) + .map(tagName -> { + Matcher matcher = TAG_VERSION_PATTERN.matcher(tagName); + matcher.matches(); + return matcher.group(1); + }) + .collect(Collectors.toList()); + } + + protected VersionInformation addSnapshotQualifier(VersionInformation vi) { + if (appendSnapshot) { + vi.setQualifier("SNAPSHOT"); + } + + return vi; + } + + protected class VersionComparator implements Comparator { + + @Override + public int compare(String version1, String version2) { + return new ComparableVersion(version1).compareTo(new ComparableVersion(version2)); + } + } +} diff --git a/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/VersionInformation.java b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/VersionInformation.java new file mode 100644 index 0000000000..1cfbe492d5 --- /dev/null +++ b/versions-maven-plugin/src/main/java/org/codehaus/mojo/versions/VersionInformation.java @@ -0,0 +1,176 @@ +package org.codehaus.mojo.versions; + +/* + * The MIT License + * + * Copyright (c) 2016, 2017 Karl Heinz Marbaise + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is furnished to do + * so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * This class will parse the version based on the given pattern in + * {@code org.codehaus.mojo.buildhelper.ParseVersionMojo}. + * + * @author Karl Heinz Marbaise + * khmarbaise@apache.org + * + */ +public class VersionInformation { + + private static final String MAJOR_MINOR_PATCH_PATTERN = "^((\\d+)(\\.(\\d+)(\\.(\\d+))?)?)"; + + private static final Pattern MAJOR_MINOR_PATCH = Pattern.compile(MAJOR_MINOR_PATCH_PATTERN); + + private static final Pattern DIGITS = Pattern.compile(MAJOR_MINOR_PATCH_PATTERN + "(.*)$"); + + private static final Pattern BUILD_NUMBER = Pattern.compile("(((\\-)(\\d+)(.*))?)|(\\.(.*))|(\\-(.*))|(.*)$"); + + private int major; + + private int minor; + + private int patch; + + private long buildNumber; + + private String qualifier; + + private void parseBuildNumber(String buildNumberPart) { + Matcher matcher = BUILD_NUMBER.matcher(buildNumberPart); + if (matcher.matches()) { + String buildNumber = matcher.group(4); + String qualifier = matcher.group(5); + + if (buildNumber != null) { + setBuildNumber(Long.parseLong(buildNumber)); + } + + if (matcher.group(7) != null) { + qualifier = matcher.group(7); + } + // Starting with "-" + if (matcher.group(9) != null) { + qualifier = matcher.group(9); + } + if (qualifier != null) { + if (qualifier.trim().length() == 0) { + setQualifier(null); + } else { + setQualifier(qualifier); + } + } else { + setQualifier(null); + } + } + } + + private void parseMajorMinorPatchVersion(String version) { + Matcher matcher = MAJOR_MINOR_PATCH.matcher(version); + if (matcher.matches()) { + String majorString = matcher.group(2); + String minorString = matcher.group(4); + String patchString = matcher.group(6); + + if (majorString != null) { + setMajor(Integer.parseInt(majorString)); + } + if (minorString != null) { + setMinor(Integer.parseInt(minorString)); + } + if (patchString != null) { + setPatch(Integer.parseInt(patchString)); + } + } + } + + public VersionInformation(String version) { + Matcher matcherDigits = DIGITS.matcher(version); + if (matcherDigits.matches()) { + parseMajorMinorPatchVersion(matcherDigits.group(1)); + parseBuildNumber(matcherDigits.group(7)); + } else { + setQualifier(version); + } + } + + public int getMajor() { + return major; + } + + public void setMajor(int major) { + this.major = major; + } + + public int getMinor() { + return minor; + } + + public void setMinor(int minor) { + this.minor = minor; + } + + public int getPatch() { + return patch; + } + + public void setPatch(int patch) { + this.patch = patch; + } + + public long getBuildNumber() { + return buildNumber; + } + + public void setBuildNumber(long buildNumber) { + this.buildNumber = buildNumber; + } + + public String getQualifier() { + return qualifier; + } + + public void setQualifier(String qualifier) { + this.qualifier = qualifier; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(this.getMajor()); + sb.append("." + this.getMinor()); + sb.append("." + this.getPatch()); + + if (this.getQualifier() != null || this.getBuildNumber() != 0) { + + if (this.getBuildNumber() != 0) { + sb.append("-"); + sb.append(this.getBuildNumber()); + } + if (this.getQualifier() != null) { + sb.append("-"); + sb.append(this.getQualifier()); + } + } + + return sb.toString(); + } +} diff --git a/versions-maven-plugin/src/site/markdown/examples/use-dynamic-version-from-scm.md b/versions-maven-plugin/src/site/markdown/examples/use-dynamic-version-from-scm.md new file mode 100644 index 0000000000..895db7ebeb --- /dev/null +++ b/versions-maven-plugin/src/site/markdown/examples/use-dynamic-version-from-scm.md @@ -0,0 +1,32 @@ +title: Using use-dynamic-version-from-scm goal +author: Jimisola Laursen +date: 2024-06-22 + + + +The `use-dynamic-version-from-scm` goal will use scm/vcs (currently, only git) tags to determine the version for the current build and set that in a property (default: `revision`). It is intended to be used with [Maven CI Friendly Versions](https://maven.apache.org/maven-ci-friendly.html). The goal follows [Versions Maven Plugin - Version number rules](https://www.mojohaus.org/versions/versions-maven-plugin/version-rules.html). + +* The version tag can be with or without "v" prefix, i.e. "v1.2.3" or "1.2.3". +* The `-SNAPSHOT` qualifier suffix is optional (appended per default). +* If the parameter `useVersion` is set then that version will be used irrespective of commits/tags (is typically used for testing). +* The goal will determine the version for the current build as follows: + * latest commit has valid version tag: use the highest version tag for that commit (e.g. 1.2.3 -> 1.2.3) + * latest version has _no_ valid version tag: use the highest version tag for the most recent non-latest commit, increase incremental (patch) version with 1 and use the number of commits to that commit (commit count) as build number and `-SNAPSHOT qualifer appended (e.g. 1.2.3 -> 1.2.4-12-SNAPSHOT) + * no commit with valid version tag: use 0.0.1 (configurable) and use the number of commits to that commit (commit count) as build number and `-SNAPSHOT qualifer appended (e.g. 1.2.3 -> 1.2.4-12-SNAPSHOT) (e.g. 0.0.1-10-SNAPSHOT) + * repository has no commits: build fails with exception `Caused by: org.apache.maven.plugin.MojoExecutionException: SCM repo has no head/commits.` + diff --git a/versions-maven-plugin/src/site/markdown/index.md b/versions-maven-plugin/src/site/markdown/index.md index a0f773e6b4..48c386d5ed 100644 --- a/versions-maven-plugin/src/site/markdown/index.md +++ b/versions-maven-plugin/src/site/markdown/index.md @@ -73,6 +73,7 @@ have been a newer version and replaces them with the latest version. built-in "Poor Man's SCM". * [versions:revert](./revert-mojo.html) restores the `pom.xml` files from the `pom.xml.versionsBackup` files. Forms one half of the built-in "Poor Man's SCM". +* [versions:use-dynamic-version-from-scm](./use-dynamic-version-from-scm-mojo.html) uses SCM/VCS tags to enable dynamic versioning and sets the version in a property. ## Reporting goals overview @@ -135,3 +136,4 @@ you can take a look into the following examples: * [Replacing -SNAPSHOT versions with their corresponding releases](./examples/use-releases.html) * [Changing the project version](./examples/set.html) * [Recording version changes](./examples/recording-changes.html) +* [Using use-dynamic-version-from-scm goal](./examples/use-dynamic-version-from-scm.html)