diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index fce433f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: java -jdk: - - openjdk9 - - openjdk11 - -after_success: - - mvn clean verify jacoco:report coveralls:report diff --git a/Jenkinsfile b/Jenkinsfile index 95f69d7..3563d1b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,18 +2,35 @@ pipeline { agent { docker { image 'maven:3.6-jdk-11' - args '-v $HOME/.m2:/root/.m2 -u 0:0' + args '-v /home/jenkins/.m2:/var/maven/.m2 -v /home/jenkins/.gnupg:/.gnupg -e MAVEN_CONFIG=/var/maven/.m2 -e MAVEN_OPTS=-Duser.home=/var/maven' } } + environment { + COVERALLS_REPO_TOKEN = credentials('coveralls_repo_token_semantic_version') + GPG_SECRET = credentials('gpg_password') + } stages { stage('Build') { steps { - sh 'mvn clean install' + sh 'mvn -B clean verify' + } + } + stage('Coverage') { + steps { + sh 'mvn -B jacoco:report jacoco:report-integration coveralls:report -DrepoToken=$COVERALLS_REPO_TOKEN' } } stage('javadoc') { steps { - sh 'mvn javadoc:javadoc' + sh 'mvn -B javadoc:javadoc' + } + } + stage('Deploy SNAPSHOT') { + when { + branch 'dev' + } + steps { + sh 'mvn -B -Prelease -DskipTests -Dgpg.passphrase=${GPG_SECRET} deploy' } } } diff --git a/JenkinsfileRelease b/JenkinsfileRelease index 7a5abba..70f8291 100644 --- a/JenkinsfileRelease +++ b/JenkinsfileRelease @@ -8,22 +8,50 @@ pipeline { environment { GPG_SECRET = credentials('gpg_password') GITHUB = credentials('Github-Username-Pw') + GITHUB_RELEASE_TOKEN = credentials('github_registry_release') + GIT_ASKPASS='./.git-askpass' } stages { - stage ('Set Git Information') { - steps { - sh 'git config user.email "simon.taddiken@gmail.com"' - sh 'git config user.name "Simon Taddiken"' + stage ('Ensure dev branch') { + when { + expression { + return env.BRANCH_NAME != 'dev'; } + } + steps { + error("Releasing is only possible from dev branch") + } + } + stage ('Set Git Information') { + steps { + sh 'echo \'echo \$GITHUB_PSW\' > ./.git-askpass' + sh 'chmod +x ./.git-askpass' + sh 'git config url."https://api@github.com/".insteadOf "https://github.com/"' + sh 'git config url."https://ssh@github.com/".insteadOf "ssh://git@github.com/"' + sh 'git config url."https://git@github.com/".insteadOf "git@github.com:"' + sh 'git config user.email "build@taddiken.online"' + sh 'git config user.name "Jenkins"' + } + } + stage('Create release branch') { + steps { + sh 'mvn -B -Prelease gitflow:release-start' + } + } + stage('Verify release') { + steps { + sh 'mvn -B -Prelease -Dgpg.passphrase=${GPG_SECRET} verify' + } } - stage('Prepare') { + stage('Perform release') { steps { - sh 'mvn -B release:prepare -Dpassword=${GITHUB_PSW} -Dusername=${GITHUB_USR}' + sh "mvn -B gitflow:release-finish -DargLine=\"-Prelease -B -Dgpg.passphrase=${GPG_SECRET} -DskipTests\"" } } - stage('Perform') { + stage('Create GitHub release') { steps { - sh 'mvn -B release:perform -Darguments="-Dgpg.passphrase=${GPG_SECRET} -Dpassword=${GITHUB_PSW} -Dusername=${GITHUB_USR}"' + sh 'git checkout master' + sh "mvn -B github-release:github-release -Dgithub.release-token=${GITHUB_RELEASE_TOKEN}" } } } diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md new file mode 100644 index 0000000..861b781 --- /dev/null +++ b/RELEASE_NOTES.md @@ -0,0 +1 @@ +* #5: System locale might lead to illegal identifiers during lower/upper casing (Thx [@portlek](https://github.com/portlek)) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 270c7d8..d7539a6 100644 --- a/pom.xml +++ b/pom.xml @@ -1,15 +1,15 @@ - + 4.0.0 de.skuzzle skuzzle-parent - 2.0.11 - ../skuzzle-parent/pom.xml + 3.0.1 semantic-version - 2.1.1-SNAPSHOT + 2.1.1 jar semantic-version @@ -24,16 +24,14 @@ - 3.1.1 - semantic-version semantic-version - 5.5.2 - 1.5.2 + 5.7.2 2.10.0.pr1 - 3.0.0-M4 - 3.0.0-M4 + 2.8.5 + 0.9.0 + 3.1.0 false false @@ -41,17 +39,28 @@ true - scm:git:https://github.com/skuzzle/${github.name}.git HEAD + + + + org.junit + junit-bom + ${junit.version} + pom + import + + + + com.google.code.gson gson - 2.8.5 + ${gson.version} test @@ -69,43 +78,29 @@ com.github.zafarkhaja java-semver - 0.9.0 + ${java-semver.version} test com.vdurmont semver4j - 2.0.1 + ${semver4j.version} test org.junit.jupiter junit-jupiter - ${junit.jupiter.version} test org.junit.jupiter junit-jupiter-api - ${junit.jupiter.version} - test - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - org.junit.platform - junit-platform-launcher - ${junit.platform.version} test - org.junit.platform - junit-platform-commons - ${junit.platform.version} + org.junit-pioneer + junit-pioneer + 1.4.2 test @@ -119,10 +114,37 @@ 8 + + com.amashchenko.maven.plugin + gitflow-maven-plugin + + deploy + true + true + true + + master + dev + + + + + com.ragedunicorn.tools.maven + github-release-maven-plugin + 1.0.2 + + skuzzle + ${github.name} + ${github.release-token} + v${project.version} + Semantic Version ${project.version} + master + RELEASE_NOTES.md + + org.apache.maven.plugins maven-compiler-plugin - 3.8.1 default-compile diff --git a/src/it/java/de/skuzzle/semantic/IsPreReleasePerformanceIT.java b/src/it/java/de/skuzzle/semantic/IsPreReleasePerformanceIT.java index 08d4c1a..8a4bb5b 100644 --- a/src/it/java/de/skuzzle/semantic/IsPreReleasePerformanceIT.java +++ b/src/it/java/de/skuzzle/semantic/IsPreReleasePerformanceIT.java @@ -8,7 +8,7 @@ public class IsPreReleasePerformanceIT extends VersionPerformanceTestBase { @Test public void testIsNoPreReleaseWithRegex() throws Exception { - performTest("Is no pre-release with regex", RUN, new Runnable() { + performTest("Is no pre-release with regex", RUNS, new Runnable() { @Override public void run() { @@ -19,7 +19,7 @@ public void run() { @Test public void testIsNoPreRelease() throws Exception { - performTest("Is no pre-release without regex", RUN, new Runnable() { + performTest("Is no pre-release without regex", RUNS, new Runnable() { @Override public void run() { diff --git a/src/it/java/de/skuzzle/semantic/ParsingPerformanceIT.java b/src/it/java/de/skuzzle/semantic/ParsingPerformanceIT.java index b9a355d..a16a4ea 100644 --- a/src/it/java/de/skuzzle/semantic/ParsingPerformanceIT.java +++ b/src/it/java/de/skuzzle/semantic/ParsingPerformanceIT.java @@ -10,21 +10,21 @@ public class ParsingPerformanceIT extends VersionPerformanceTestBase { @Test public void testNoRegex() throws Exception { - performTest("Without regex", RUN, () -> Version.parseVersion(TEST_STRING)); + performTest("Without regex", RUNS, () -> Version.parseVersion(TEST_STRING)); } @Test public void testWithRegex() throws Exception { - performTest("With regex", RUN, () -> VersionRegEx.parseVersion(TEST_STRING)); + performTest("With regex", RUNS, () -> VersionRegEx.parseVersion(TEST_STRING)); } @Test public void testJSemver() throws Exception { - performTest("jsemver", RUN, () -> com.github.zafarkhaja.semver.Version.valueOf(TEST_STRING)); + performTest("jsemver", RUNS, () -> com.github.zafarkhaja.semver.Version.valueOf(TEST_STRING)); } @Test public void testsemver4j() throws Exception { - performTest("semver4j", RUN, () -> new Semver(TEST_STRING)); + performTest("semver4j", RUNS, () -> new Semver(TEST_STRING)); } } diff --git a/src/it/java/de/skuzzle/semantic/SortingPerformanceIT.java b/src/it/java/de/skuzzle/semantic/SortingPerformanceIT.java index 4c08bb8..87df478 100644 --- a/src/it/java/de/skuzzle/semantic/SortingPerformanceIT.java +++ b/src/it/java/de/skuzzle/semantic/SortingPerformanceIT.java @@ -1,6 +1,10 @@ package de.skuzzle.semantic; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -9,77 +13,73 @@ public class SortingPerformanceIT extends VersionPerformanceTestBase { - private String[] sortMe; + private static final Random SHUFFLE_RANDOM = new Random(0); + + private List sortMe; @BeforeEach public void setup() { - this.sortMe = new String[] { - "1.0.0-alpha.beta", - "1.0.0-alpha", - "1.0.0-alpha.1", - "1.0.0-beta.11", - "1.0.0-beta", - "1.0.0-rc.1", - "1.0.0", - "1.0.0-beta.2", - "2.1.1", - "2.1.0", - "1.0.0-alpha.beta", - "2.0.0", - "1.0.0-alpha", - "1.0.0-rc.1", - "1.0.0-alpha.1", - "1.0.0-beta", - "1.0.0-beta.11", - "1.0.0", - "1.0.0-beta.2", - "2.1.0", - "2.0.0", - "2.1.1", - }; + final List mutable = new ArrayList<>( + List.of( + "1.0.0-alpha.beta", + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-beta.11", + "1.0.0-beta", + "1.0.0-rc.1", + "1.0.0", + "1.0.0-beta.2", + "2.1.1", + "2.1.0", + "1.0.0-alpha.beta", + "2.0.0", + "1.0.0-alpha", + "1.0.0-rc.1", + "1.0.0-alpha.1", + "1.0.0-beta", + "1.0.0-beta.11", + "1.0.0", + "1.0.0-beta.2", + "2.1.0", + "2.0.0", + "2.1.1")); + Collections.shuffle(mutable, SHUFFLE_RANDOM); + sortMe = Collections.unmodifiableList(mutable); } @Test public void testOldVersion() throws Exception { - performTest("Old Impl", RUN, () -> { - return Arrays.stream(this.sortMe) - .map(VersionRegEx::parseVersion) - .toArray(length -> new VersionRegEx[length]); - }, unsorted -> { - Arrays.sort(unsorted); - }); + performTest("Regex Impl", RUNS, + () -> sortMe.stream() + .map(VersionRegEx::parseVersion) + .toArray(VersionRegEx[]::new), + Arrays::sort); } @Test public void testCurrentVersion() throws Exception { - performTest("Current Impl", RUN, () -> { - return Arrays.stream(this.sortMe) - .map(Version::parseVersion) - .toArray(length -> new Version[length]); - }, unsorted -> { - Arrays.sort(unsorted); - }); + performTest("Current Impl", RUNS, + () -> sortMe.stream() + .map(Version::parseVersion) + .toArray(Version[]::new), + Arrays::sort); } @Test public void testJSemver() throws Exception { - performTest("JSemver", RUN, () -> { - return Arrays.stream(this.sortMe) - .map(com.github.zafarkhaja.semver.Version::valueOf) - .toArray(l -> new com.github.zafarkhaja.semver.Version[l]); - }, unsorted -> { - Arrays.sort(unsorted); - }); + performTest("JSemver", RUNS, + () -> sortMe.stream() + .map(com.github.zafarkhaja.semver.Version::valueOf) + .toArray(com.github.zafarkhaja.semver.Version[]::new), + Arrays::sort); } @Test public void testSemver4j() throws Exception { - performTest("JSemver", RUN, () -> { - return Arrays.stream(this.sortMe) - .map(Semver::new) - .toArray(length -> new Semver[length]); - }, unsorted -> { - Arrays.sort(unsorted); - }); + performTest("JSemver", RUNS, + () -> sortMe.stream() + .map(Semver::new) + .toArray(Semver[]::new), + Arrays::sort); } } diff --git a/src/it/java/de/skuzzle/semantic/VersionPerformanceTestBase.java b/src/it/java/de/skuzzle/semantic/VersionPerformanceTestBase.java index 21395ee..d86a9f7 100644 --- a/src/it/java/de/skuzzle/semantic/VersionPerformanceTestBase.java +++ b/src/it/java/de/skuzzle/semantic/VersionPerformanceTestBase.java @@ -9,7 +9,7 @@ class VersionPerformanceTestBase { private static final int WARM_UP = 11000; - protected static final int RUN = 100000; + protected static final int RUNS = 100000; private void warmUp(Runnable subject) { for (int i = 0; i < WARM_UP; ++i) { diff --git a/src/main/java/de/skuzzle/semantic/Version.java b/src/main/java/de/skuzzle/semantic/Version.java index a810b08..274a95f 100644 --- a/src/main/java/de/skuzzle/semantic/Version.java +++ b/src/main/java/de/skuzzle/semantic/Version.java @@ -29,6 +29,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; +import java.util.Locale; /** * This class is an implementation of the full semantic version 2.0.0 @@ -45,7 +46,6 @@ * methods taking an array or other kind of modifiable objects as input, will first make a * copy before using it as internal state. * - * *

* Note that unless stated otherwise, none of the public methods of this class accept * null values. Most methods will throw an {@link IllegalArgumentException} @@ -53,7 +53,6 @@ * {@link Comparable} contract, the comparison methods will throw a * {@link NullPointerException} instead. * - * * @author Simon Taddiken */ public final class Version implements Comparable, Serializable { @@ -517,7 +516,6 @@ private static int parseIDPart(char[] stream, String full, int start, throw unexpectedChar(full, c); } break; - } } @@ -531,7 +529,7 @@ private static VersionFormatException illegalLeadingChar(String v, int c, } private static VersionFormatException unexpectedChar(String v, int c) { - if (c == -1) { + if (c == EOS) { return new VersionFormatException(String.format( "Incomplete version part in %s", v)); } @@ -1751,7 +1749,7 @@ public int compareToWithBuildMetaData(Version other) { /** * Returns a new Version where all identifiers are converted to upper case letters. * - * @return A new version with upper case identifiers. + * @return A new version with lower case identifiers. * @since 1.1.0 */ public Version toUpperCase() { @@ -1776,7 +1774,7 @@ private static String[] copyCase(String[] source, boolean toUpper) { final String[] result = new String[source.length]; for (int i = 0; i < source.length; i++) { final String string = source[i]; - result[i] = toUpper ? string.toUpperCase() : string.toLowerCase(); + result[i] = toUpper ? string.toUpperCase(Locale.ROOT) : string.toLowerCase(Locale.ROOT); } return result; } diff --git a/src/test/java/de/skuzzle/semantic/VersionTest.java b/src/test/java/de/skuzzle/semantic/VersionTest.java index 0eebf7f..06f456c 100644 --- a/src/test/java/de/skuzzle/semantic/VersionTest.java +++ b/src/test/java/de/skuzzle/semantic/VersionTest.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.DefaultLocale; import de.skuzzle.semantic.Version.VersionFormatException; @@ -1225,4 +1226,26 @@ void testIsStableWithBuildMetaData() throws Exception { assertTrue(Version.create(1, 3, 4).withBuildMetaData("foo").isStable()); } + // This would have produced an illegal identifier when using toLowerCase with default + // locale + // https://github.com/skuzzle/semantic-version/pull/5 + @Test + @DefaultLocale("tr-TR") + void testToLowerCaseWithTurkishLocale() throws Exception { + final Version lowerCase = Version.create(1, 3, 4).withPreRelease("I") + .toLowerCase(); + Version.create(1, 3, 4, lowerCase.getPreRelease()); + } + + // This would have produced an illegal identifier when using toLowerCase with default + // locale + // https://github.com/skuzzle/semantic-version/pull/5 + @Test + @DefaultLocale("tr-TR") + void testToUpperCaseWithTurkishLocale() throws Exception { + final Version lowerCase = Version.create(1, 3, 4) + .withPreRelease("i") + .toUpperCase(); + Version.create(1, 3, 4, lowerCase.getPreRelease()); + } }