diff options
-rw-r--r-- | CHANGELOG.md | 4 | ||||
-rw-r--r-- | Makefile | 18 | ||||
-rw-r--r-- | pom.xml | 38 | ||||
-rw-r--r-- | src/main/java/org/onap/dcae/inventory/InventoryApplication.java | 52 | ||||
-rw-r--r-- | src/test/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImplTests.java | 8 | ||||
-rw-r--r-- | src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplH2Tests.java | 3 | ||||
-rw-r--r-- | src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplTests.java | 7 | ||||
-rw-r--r-- | src/test/java/org/onap/dcae/inventory/InventoryApplicationTest.java | 7 | ||||
-rw-r--r-- | src/test/java/org/onap/dcae/inventory/exceptions/mappers/DBIExceptionMapperTests.java | 7 | ||||
-rw-r--r-- | tools/config_local.json | 76 | ||||
-rw-r--r-- | version.properties | 4 |
11 files changed, 174 insertions, 50 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bc6986..a69da9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). The version in the brackets represents the version of DCAE inventory and not the ONAP DCAE version. +## [3.5.0] + +* Upgrade java from 8 to 11 + ## [3.4.0] * Add non-root user in Docker image so that the inventory service can be run in non-privileged mode for security reasons DCAEGEN2-1554 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6dd1f67 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +all: build start-service +.PHONY: build + +build: + @echo "##### Build inventory api jar file #####" + mvn clean package + @echo "##### DONE #####" + +start-service: + @echo "##### Start inventory api service #####" + @echo "########################### IMPORTANT ############################################################################################" + @echo "##### Before you start service you must properly configure connection to database in ./tools/congif_local.json! #####" + @echo "##### Now service should up and running pls check: http://localhost:9080/swagger.json or http://localhost:9080/servicehealth #####" + @echo "##################################################################################################################################" + + java -DdevMode=true --add-opens java.base/java.lang=ALL-UNNAMED -jar ./target/inventory-api-3.5.0-SNAPSHOT.jar server ./tools/config_local.json + + @echo "##### DONE #####" @@ -2,6 +2,7 @@ <!-- ================================================================================ Copyright (c) 2017-2020 AT&T Intellectual Property. All rights reserved. +Copyright (c) 2020 Nokia. All rights reserved. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -29,14 +30,15 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <groupId>org.onap.dcaegen2.platform</groupId> <artifactId>inventory-api</artifactId> - <version>3.4.1-SNAPSHOT</version> + <version>3.5.0-SNAPSHOT</version> <name>dcaegen2-platform-inventory-api</name> <!--internal <version>3.0.0</version>--> <properties> - <dropwizard.version>1.1.1</dropwizard.version> + <dropwizard.version>1.3.11</dropwizard.version> <logback.version>1.2.3</logback.version> <swagger-core.version>1.5.8</swagger-core.version> + <guava.version>28.2-jre</guava.version> <ecomp.inceptionYear>2017</ecomp.inceptionYear> <ecomp.organizationName>AT&T Intellectual Property. All rights reserved.</ecomp.organizationName> @@ -46,9 +48,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <snapshots.path>content/repositories/snapshots/</snapshots.path> <releases.path>content/repositories/releases/</releases.path> <site.path>content/sites/site/org/onap/dcae/dcae-inventory/${project.artifactId}/${project.version}/</site.path> - <sonar.coverage.jacoco.xmlReportPaths> - ${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml - </sonar.coverage.jacoco.xmlReportPaths> + <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths> </properties> <pluginRepositories> @@ -201,7 +201,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> - <version>19.0</version> + <version>${guava.version}</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> @@ -209,6 +209,11 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <version>2.22.1</version> </dependency> <dependency> + <groupId>javax.xml.bind</groupId> + <artifactId>jaxb-api</artifactId> + <version>2.3.0</version> + </dependency> + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> @@ -282,10 +287,9 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> - <version>3.5</version> + <version>3.8.0</version> <configuration> - <source>1.8</source> - <target>1.8</target> + <release>11</release> </configuration> </plugin> <plugin> @@ -354,17 +358,23 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>1.0.0</version> + <dependencies> + <dependency> + <groupId>javax.activation</groupId> + <artifactId>activation</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> <configuration> <imageName>${onap.nexus.dockerregistry.daily}/onap/${project.groupId}.${project.artifactId}</imageName> - <baseImage>openjdk:8-jre-alpine</baseImage> + <baseImage>openjdk:11-jre-slim</baseImage> <user>inventory</user> <runs> - <run>addgroup -S inventory</run> - <run>adduser -S -G inventory inventory</run> + <run>useradd -r -U inventory</run> <run>mkdir -p /opt/logs</run> <run>chown -R inventory:inventory /opt</run> </runs> - <entryPoint>["java", "-jar", "/opt/${project.build.finalName}.jar", "server"]</entryPoint> + <entryPoint>["java", "--add-opens", "java.base/java.lang=ALL-UNNAMED", "-jar", "/opt/${project.build.finalName}.jar", "server"]</entryPoint> <resources> <resource> <targetPath>/opt</targetPath> @@ -406,7 +416,7 @@ ECOMP is a trademark and service mark of AT&T Intellectual Property. <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> - <version>2.20.1</version> + <version>2.22.2</version> <dependencies> <dependency> <groupId>org.apache.maven.surefire</groupId> diff --git a/src/main/java/org/onap/dcae/inventory/InventoryApplication.java b/src/main/java/org/onap/dcae/inventory/InventoryApplication.java index 5f0104f..0964f83 100644 --- a/src/main/java/org/onap/dcae/inventory/InventoryApplication.java +++ b/src/main/java/org/onap/dcae/inventory/InventoryApplication.java @@ -3,13 +3,14 @@ * dcae-inventory * ================================================================================ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 Nokia. All rights reserved. * ================================================================================ * 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. @@ -104,8 +105,8 @@ public class InventoryApplication extends Application<InventoryConfiguration> { // You are here because you want to use the default way of configuring inventory - YAML file. // The config file yaml file however has the path to the file that has the cert jks password in the keyStorePassword filed // Update config file's keyStorePassword to have actual password instead of path to the password file - // for junit purposes, it's not possible to do the above with keyStorePassword so return userArgs as we used to do before - if ( "some-junit-yaml.yaml".equals(userArgs[1]) ) { + // for junit purposes, it's not possible to do the above with keyStorePassword so return userArgs as we used to do before + if ( "some-junit-yaml.yaml".equals(userArgs[1]) ) { return userArgs; } debugLogger.debug(String.format("Default configuration file received: %s", userArgs[1])); @@ -131,10 +132,10 @@ public class InventoryApplication extends Application<InventoryConfiguration> { context.reset(); ContextInitializer initializer = new ContextInitializer(context); initializer.autoConfig(); - + metricsLogger.info("Starting DCAE inventory application..."); debugLogger.debug(String.format("Starting DCAE inventory application... args[0]: %s", args[0])); - + } @Override @@ -222,37 +223,42 @@ public class InventoryApplication extends Application<InventoryConfiguration> { environment.jersey().register(new ApiListingResource()); environment.jersey().register(new SwaggerSerializers()); } - - + + private static void createConfigFileFromDefault (String defaultConfigFile) { - + try { - JSONObject dzConfig = new JSONObject ( new JSONTokener ( new FileInputStream ( new File ( defaultConfigFile ) ) ) ); + JSONObject dzConfig = new JSONObject ( new JSONTokener ( new FileInputStream ( new File ( defaultConfigFile ) ) ) ); JSONObject server = dzConfig.getJSONObject("server"); JSONArray applicationConnectors = server.getJSONArray("applicationConnectors"); - String jksPasswdFile = applicationConnectors.getJSONObject(0).getString("keyStorePassword"); - if ( jksPasswdFile != null ) { - applicationConnectors.getJSONObject(0).put("keyStorePassword", getFileContents(jksPasswdFile)); - } - else { - errorLogger.error(String.format("Exiting due to null value for JKS password file: %s", jksPasswdFile)); - System.exit(1); - } + if(isProductionModeActivated()) { + String jksPasswdFile = applicationConnectors.getJSONObject(0).getString("keyStorePassword"); + if (jksPasswdFile != null) { + applicationConnectors.getJSONObject(0).put("keyStorePassword", getFileContents(jksPasswdFile)); + } else { + errorLogger.error(String.format("Exiting due to null value for JKS password file: %s", jksPasswdFile)); + System.exit(1); + } + } FileWriter fileWriter = new FileWriter(configFile); fileWriter.write(dzConfig.toString()); fileWriter.flush(); - fileWriter.close(); + fileWriter.close(); } catch (JSONException | FileNotFoundException e) { - errorLogger.error(String.format("JSONException | FileNotFoundException while processing default config file: %s; execption: %s", + errorLogger.error(String.format("JSONException | FileNotFoundException while processing default config file: %s; execption: %s", defaultConfigFile, e)); System.exit(1); } catch ( Exception e ) { - errorLogger.error(String.format("Exception while processing default config file: %s; execption: %s", + errorLogger.error(String.format("Exception while processing default config file: %s; execption: %s", defaultConfigFile, e)); System.exit(1); } } - + + private static boolean isProductionModeActivated() { + return System.getProperty("devMode","false").equals("false"); + } + public static String getFileContents (String filename) { File f = new File(filename); try { @@ -262,7 +268,7 @@ public class InventoryApplication extends Application<InventoryConfiguration> { errorLogger.error(String.format("FileNotFoundException for filename: %s; execption: %s", filename, e)); System.exit(1); } catch (IOException e) { - errorLogger.error(String.format("IOException for filename: %s; execption: %s", filename, e)); + errorLogger.error(String.format("IOException for filename: %s; execption: %s", filename, e)); System.exit(1); } return null; diff --git a/src/test/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImplTests.java b/src/test/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImplTests.java index bd13abe..5630c40 100644 --- a/src/test/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImplTests.java +++ b/src/test/java/io/swagger/api/impl/DcaeServiceTypesApiServiceImplTests.java @@ -3,14 +3,14 @@ package io.swagger.api.impl;/*- * dcae-inventory * ================================================================================ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. - * Copyright (C) 2020 Nokia Intellectual Property. All rights reserved. + * Copyright (C) 2020 Nokia. All rights reserved. * ================================================================================ * 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. @@ -42,6 +42,7 @@ import org.onap.dcae.inventory.daos.InventoryDAOManager; import org.onap.dcae.inventory.dbthings.models.DCAEServiceObject; import org.onap.dcae.inventory.dbthings.models.DCAEServiceTypeObject; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.slf4j.Logger; @@ -55,6 +56,7 @@ import io.swagger.model.DCAEServiceTypeRequest; * Created by mhwang on 10/27/16. */ @PrepareForTest({InventoryDAOManager.class}) +@PowerMockIgnore("jdk.internal.reflect.*") @RunWith(PowerMockRunner.class) public class DcaeServiceTypesApiServiceImplTests { diff --git a/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplH2Tests.java b/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplH2Tests.java index 32cc664..a431687 100644 --- a/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplH2Tests.java +++ b/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplH2Tests.java @@ -3,6 +3,7 @@ * dcae-inventory * ================================================================================ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2020 Nokia. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +41,7 @@ import org.onap.dcae.inventory.daos.DCAEServicesDAO; import org.onap.dcae.inventory.daos.InventoryDAOManager; import org.onap.dcae.inventory.dbthings.models.DCAEServiceObject; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.skife.jdbi.v2.DBI; @@ -64,6 +66,7 @@ import io.swagger.model.DCAEServiceRequest; * test here was not included in the original class because of conflicting setup operations. */ @PrepareForTest({InventoryDAOManager.class}) +@PowerMockIgnore("jdk.internal.reflect.*") @RunWith(PowerMockRunner.class) public class DcaeServicesApiServiceImplH2Tests { diff --git a/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplTests.java b/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplTests.java index 9599ca5..9c8d688 100644 --- a/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplTests.java +++ b/src/test/java/io/swagger/api/impl/DcaeServicesApiServiceImplTests.java @@ -3,6 +3,7 @@ package io.swagger.api.impl;/*- * dcae-inventory * ================================================================================ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. + * Copyright (c) 2020 Nokia. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +44,7 @@ import org.onap.dcae.inventory.daos.InventoryDAOManager; import org.onap.dcae.inventory.dbthings.models.DCAEServiceComponentObject; import org.onap.dcae.inventory.dbthings.models.DCAEServiceObject; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.slf4j.Logger; @@ -57,6 +59,7 @@ import io.swagger.model.DCAEServiceRequest; * Created by mhwang on 9/25/17. */ @PrepareForTest({InventoryDAOManager.class}) +@PowerMockIgnore("jdk.internal.reflect.*") @RunWith(PowerMockRunner.class) public class DcaeServicesApiServiceImplTests { @@ -88,7 +91,7 @@ public class DcaeServicesApiServiceImplTests { // This block is a trick to make a private method accessible for testing try { - createDCAEService = DcaeServicesApiServiceImpl.class.getDeclaredMethod("createDCAEService", + createDCAEService = DcaeServicesApiServiceImpl.class.getDeclaredMethod("createDCAEService", DCAEServiceObject.class, Collection.class, UriInfo.class); createDCAEService.setAccessible(true); } catch (NoSuchMethodException e) { @@ -137,7 +140,7 @@ public class DcaeServicesApiServiceImplTests { } /* - Commented this unit test because could not get past Nullpointer in the line trying to mock the explicit "bind" + Commented this unit test because could not get past Nullpointer in the line trying to mock the explicit "bind" function call. Mockito does not handle mocking overloaded functions well so it goes into the actual method where an member variable called foreman is null. @Test diff --git a/src/test/java/org/onap/dcae/inventory/InventoryApplicationTest.java b/src/test/java/org/onap/dcae/inventory/InventoryApplicationTest.java index aacbd25..0e5562b 100644 --- a/src/test/java/org/onap/dcae/inventory/InventoryApplicationTest.java +++ b/src/test/java/org/onap/dcae/inventory/InventoryApplicationTest.java @@ -3,6 +3,7 @@ * dcae-inventory * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 Nokia. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,12 +28,11 @@ import io.dropwizard.jetty.setup.ServletEnvironment; import io.dropwizard.setup.Bootstrap; import io.dropwizard.setup.Environment; import org.eclipse.jetty.servlets.CrossOriginFilter; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.junit.runner.manipulation.Filter; import org.onap.dcae.inventory.daos.InventoryDAOManager; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; @@ -41,8 +41,6 @@ import java.util.HashMap; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -51,6 +49,7 @@ import static org.mockito.Mockito.when; * Created by mhwang on 3/14/19. */ @PrepareForTest({InventoryDAOManager.class}) +@PowerMockIgnore("jdk.internal.reflect.*") @RunWith(PowerMockRunner.class) public class InventoryApplicationTest { diff --git a/src/test/java/org/onap/dcae/inventory/exceptions/mappers/DBIExceptionMapperTests.java b/src/test/java/org/onap/dcae/inventory/exceptions/mappers/DBIExceptionMapperTests.java index 21feaba..0597036 100644 --- a/src/test/java/org/onap/dcae/inventory/exceptions/mappers/DBIExceptionMapperTests.java +++ b/src/test/java/org/onap/dcae/inventory/exceptions/mappers/DBIExceptionMapperTests.java @@ -3,13 +3,14 @@ * dcae-inventory * ================================================================================ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 Nokia. All rights reserved. * ================================================================================ * 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. @@ -30,6 +31,7 @@ import org.junit.runner.RunWith; import org.mockito.Mockito; import org.onap.dcae.inventory.daos.InventoryDAOManager; import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.skife.jdbi.v2.exceptions.UnableToCreateStatementException; @@ -42,6 +44,7 @@ import io.swagger.api.ApiResponseMessage; * Created by mhwang on 3/8/17. */ @PrepareForTest({InventoryDAOManager.class}) +@PowerMockIgnore("jdk.internal.reflect.*") @RunWith(PowerMockRunner.class) public class DBIExceptionMapperTests { diff --git a/tools/config_local.json b/tools/config_local.json new file mode 100644 index 0000000..3abe459 --- /dev/null +++ b/tools/config_local.json @@ -0,0 +1,76 @@ +{ + "database": { + "driverClass": "org.postgresql.Driver", + "user": "dcae_inv", + "password": "onapdemodb", + "url": "jdbc:postgresql://10.183.35.177:32185/dcae_inventory", + "properties": { + "charSet": "UTF-8" + }, + "maxWaitForConnection": "1s", + "validationQuery": "/* MyService Health Check */ SELECT 1", + "minSize": 10, + "maxSize": 20, + "initialSize": 10, + "checkConnectionWhileIdle": false, + "evictionInterval": "10s", + "minIdleTime": "1 minute" + }, + "databusControllerConnection": { + "host": "databus-controller-hostname", + "port": 8443, + "mechId": null, + "password": null, + "required": false + }, + "httpClient": { + "minThreads": 1, + "maxThreads": 128, + "gzipEnabled": false, + "gzipEnabledForRequests": false, + "timeout": "5000milliseconds", + "connectionTimeout": "5000milliseconds" + }, + "server": { + "applicationConnectors": [ + { + "type": "http", + "port": 9080 + } + ], + "adminConnectors": [ + { + "type": "http", + "port": 9081 + } + ], + "requestLog": { + "appenders": [ + { + "type": "file", + "currentLogFilename": "logs/request.log", + "threshold": "ALL", + "archive": true, + "archivedLogFilenamePattern": "logs/request.%i.log.gz", + "archivedFileCount": 2, + "maxFileSize": "10MB" + } + ] + } + }, + "logging": { + "level": "INFO", + "appenders": [ + { + "type": "file", + "archive": true, + "timeZone": "UTC", + "currentLogFilename": "logs/audit.log", + "archivedLogFilenamePattern": "logs/audit-%i.log.gz", + "archivedFileCount": 2, + "maxFileSize": "100MB", + "logFormat": "%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00}|%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00}|NULL|UNKNOWN|%thread||inventory||COMPLETE|0|OK||INFO|||||||||||||%-5level:%c: %m%n" + } + ] + } +} diff --git a/version.properties b/version.properties index 5a6199f..7a03c1a 100644 --- a/version.properties +++ b/version.properties @@ -2,8 +2,8 @@ # Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... ) # because they are used in Jenkins, whose plug-in doesn't support major=3 -minor=4 -patch=1 +minor=5 +patch=0 base_version=${major}.${minor}.${patch} # Release must be completed with git revision # in Jenkins |