Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Version Handling in Build & Backend #1043

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Ignore .idea files except basic run configurations
# Ignore .idea files except important common settings and run configurations
/.idea
!/.idea/codeStyleSettings.xml
!/.idea/encodings.xml
Expand All @@ -7,7 +7,7 @@
!/.idea/codeStyles
!/.idea/runConfigurations
!/.idea/inspectionProfiles

!/.idea/gradle.xml

classes/
bin/
Expand Down
24 changes: 24 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 4 additions & 36 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,39 +1,7 @@
/**
* Used Version of Scenarioo Java Library for reading scenarioo docu data
*/
ext.scenariooApiVersion = '2.1.1'

/**
* Internal scenarioo format version of produced aggregation data (internal server format version).
*
* On import this version is stored for each build, if the format of a build does not correspond to this format, the
* build is automatically reimported again (all aggregation data recalculated in new format).
*
* First part of the version corresponds to library version that is supported, second part of the version depends on
* internal aggregation format. the second part should be increased whenever something important is changed in the
* internal format or the way that the aggregator is caluclating internal data on builds.
*/
ext.scenariooAggregatedDataFormatVersion = '2.1.0'

/**
* Name of the release branch of this scenarioo version, which is used for links to the versioned documentation.
*/
ext.documentationVersion = '5.0'

/*
* Gets the version name from the latest Git tag
* From: http://ryanharter.com/blog/2013/07/30/automatic-versioning-with-git-and-gradle/
*/
def getVersionName = { ->
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = stdout
}
return stdout.toString().trim()
}
apply from: "version.gradle"

ext.versionWithGitCommit = getVersionName();
apply plugin: 'idea'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this?

idea.module.inheritOutputDirs = true

buildscript {
repositories {
Expand All @@ -52,7 +20,7 @@ allprojects {
apply plugin: 'io.spring.dependency-management'

group = 'org.scenarioo'
version = getVersionName()
version = scenariooViewerVersion

wrapper {
gradleVersion = '6.7.1'
Expand Down
34 changes: 13 additions & 21 deletions scenarioo-server/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -96,55 +96,47 @@ dependencies {
}


task createVersionPropertiesFile {
doLast {
def aggregatedDataFormatVersion = project.scenariooAggregatedDataFormatVersion
def apiVersion = project.scenariooApiVersion
def documentationVersion = project.documentationVersion

File versionFile = new File(sourceSets.main.output.classesDirs.getSingleFile().absolutePath + '/version.properties');
versionFile.write('version=' + versionWithGitCommit + '\n' +
'build-date=' + new Date() + '\n' +
'apiVersion=' + apiVersion + '\n' +
'aggregatedDataFormatVersion=' + aggregatedDataFormatVersion + '\n' +
'documentationVersion=' + documentationVersion + '\n')
/**
* Replace properties in important resource files
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think java doc style should only be used on methods. I would use a /* single comment */ style here.

*/
processResources {
filesMatching(['version.properties', 'banner.txt']) {
expand(project.properties)
}
}

bootJar {
from('../scenarioo-client/dist') {
into('static')
}
archiveFileName = 'scenarioo-viewer-' + versionWithGitCommit + '.jar'
archiveFileName = 'scenarioo-viewer-' + archiveVersion.get() + '.jar'
}

bootJar.doLast {
copy {
from('build/libs/')
into('build/libs/')
include('scenarioo-viewer-' + version + '.jar')
rename('scenarioo-viewer-' + version + '.jar', 'scenarioo-latest.jar')
include('scenarioo-viewer-' + archiveVersion.get() + '.jar')
rename('scenarioo-viewer-' + archiveVersion.get() + '.jar', 'scenarioo-latest.jar')
}
}

bootWar {
from('../scenarioo-client/dist') {
into('WEB-INF/classes/static')
}
archiveFileName = 'scenarioo-viewer-' + versionWithGitCommit + '.war'
archiveFileName = 'scenarioo-viewer-' + archiveVersion.get() + '.war'
}

bootWar.doLast {
copy {
from('build/libs/')
into('build/libs/')
include('scenarioo-viewer-' + versionWithGitCommit + '.war')
rename('scenarioo-viewer-' + versionWithGitCommit + '.war', 'scenarioo-latest.war')
include('scenarioo-viewer-' + archiveVersion.get() + '.war')
rename('scenarioo-viewer-' + archiveVersion.get() + '.war', 'scenarioo-latest.war')
}
}

assemble.dependsOn createVersionPropertiesFile
war.dependsOn createVersionPropertiesFile
bootWar.dependsOn ":scenarioo-client:build"
war.dependsOn ":scenarioo-client:build"

Expand All @@ -160,7 +152,7 @@ publishing {

groupId 'org.scenarioo'
artifactId 'scenarioo-viewer'
version versionWithGitCommit
version scenariooViewerVersion
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the same as archiveVersion, correct?


pom {
name = 'Scenarioo Viewer'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,33 +16,37 @@ public enum ApplicationVersionHolder {

private ApplicationVersion applicationVersion;

/**
* Use this to simply initialize in spring boot app from resource files in class path
*/
public void initializeFromClassContext() {

final Properties properties = new Properties();
final InputStream inputStream = ApplicationVersionHolder.class.getResourceAsStream("/version.properties");
if (inputStream == null) {
LOGGER.warn("version.properties not found, no real version information available.");
ApplicationVersionHolder.INSTANCE.initialize("unknown", "unknown", "unknown", "unknown", "develop");
return;
}
ApplicationVersionHolder.INSTANCE.initializeFromVersionPropertiesInputStream(inputStream);
}

try {
properties.load(inputStream);
ApplicationVersionHolder.INSTANCE.initializeFromProperties(properties);
} catch (final Exception e) {
LOGGER.warn("version.properties not found, no real version information available.", e);
/**
* Use this to initialize from any input stream (e.g. from servlet context resource in a different web server scenario, like a tomcat war deployment)
*/
public void initializeFromVersionPropertiesInputStream(InputStream inputStream) {
if (inputStream == null) {
LOGGER.warn("version.properties not found, no real version information available. Continue with unknown version.");
ApplicationVersionHolder.INSTANCE.initialize("unknown", "unknown", "unknown", "unknown", "develop");
} else {
try {
final Properties properties = new Properties();
properties.load(inputStream);
ApplicationVersionHolder.INSTANCE.initializeFromProperties(properties);
} catch (final Exception e) {
LOGGER.warn("Could not load version.properties - no real version information available.", e);
ApplicationVersionHolder.INSTANCE.initialize("unknown", "unknown", "unknown", "unknown", "develop");
}
}

LOGGER.info("Version info loaded from version.properties:");
LOGGER.info(" Version: " + ApplicationVersionHolder.INSTANCE.getApplicationVersion().getVersion());
LOGGER.info(" Build date: " + ApplicationVersionHolder.INSTANCE.getApplicationVersion().getBuildDate());
}

public void initialize(final String version, final String buildDate, final String apiVersion,
final String aggregatedDataFormatVersion, String documentationVersion) {
applicationVersion = new ApplicationVersion(version, buildDate, apiVersion,
aggregatedDataFormatVersion, documentationVersion);
}

public void initializeFromProperties(final Properties versionProperties) {
private void initializeFromProperties(final Properties versionProperties) {
String version = versionProperties.getProperty("version");
String buildDate = versionProperties.getProperty("build-date");
String apiVersion = versionProperties.getProperty("apiVersion");
Expand All @@ -51,6 +55,12 @@ public void initializeFromProperties(final Properties versionProperties) {
initialize(version, buildDate, apiVersion, aggregatedDataFormatVersion, documentationVersion);
}

private void initialize(final String version, final String buildDate, final String apiVersion,
final String aggregatedDataFormatVersion, String documentationVersion) {
applicationVersion = new ApplicationVersion(version, buildDate, apiVersion,
aggregatedDataFormatVersion, documentationVersion);
}

public ApplicationVersion getApplicationVersion() {
return applicationVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,25 +84,14 @@ private void loadConfiguration(final ServletContext servletContext) {
}

private void initializeApplicationVersion(final ServletContext servletContext) {
final Properties properties = new Properties();

final InputStream inputStream = servletContext.getResourceAsStream("/WEB-INF/classes/version.properties");
if (inputStream == null) {
LOGGER.warn(" version.properties not found, no version information available");
ApplicationVersionHolder.INSTANCE.initialize("unknown", "unknown", "unknown", "unknown", "develop");
return;
}

try {
properties.load(inputStream);
ApplicationVersionHolder.INSTANCE.initializeFromProperties(properties);
} catch (final Exception e) {
ApplicationVersionHolder.INSTANCE.initialize("unknown", "unknown", "unknown", "unknown", "develop");
LOGGER.warn(" version.properties not found, no version information available", e);
// just try using class context, which should work for spring boot app.
ApplicationVersionHolder.INSTANCE.initializeFromClassContext();
} else {
// load from input stream from servlet context otherwise (needed for some war deployment scenarios in a web server as a WAR)
ApplicationVersionHolder.INSTANCE.initializeFromVersionPropertiesInputStream(inputStream);
}

LOGGER.info(" Version: " + ApplicationVersionHolder.INSTANCE.getApplicationVersion().getVersion());
LOGGER.info(" Build date: " + ApplicationVersionHolder.INSTANCE.getApplicationVersion().getBuildDate());
}

private void initializeContextPath(ServletContext servletContext) {
Expand Down
8 changes: 6 additions & 2 deletions scenarioo-server/src/main/resources/banner.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
sy- :ho .yy:` `:y+ /hs- .+s. /h: yy /ho- .+hho oh. /h: /ho- `- .+ho :hs:` ./hs`
`/shyyhs/ :oyyyhyo: `/syyyhy+- /h: yy `/shyyhs+:ho oh. /h: `/shyyhs+. `/syhyhyo-


:: Spring Boot :: ${spring-boot.formatted-version}
:: Scenarioo Version :: ${project.scenariooViewerVersion}
:: Scenarioo Release Build Date :: ${project.buildDate}
:: Scenarioo Documentation Version :: ${project.documentationVersion}
:: Scenarioo Data Format Version :: ${project.scenariooApiVersion}
:: Scenarioo Internal Format Version :: ${project.scenariooAggregatedDataFormatVersion}
:: Spring Boot Version :: \${spring-boot.formatted-version}
5 changes: 5 additions & 0 deletions scenarioo-server/src/main/resources/version.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version=${project.scenariooViewerVersion}
build-date=${project.buildDate}
apiVersion=${project.scenariooApiVersion}
aggregatedDataFormatVersion=${project.scenariooAggregatedDataFormatVersion}
documentationVersion=${project.documentationVersion}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.scenarioo.dao.version;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.*;

public class ApplicationVersionHolderTest {

@Test
public void initializeFromClassContext_loadsVersionProperlyFromVersionPropertiesFile() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JUnit 5 does not require the public keyword

ApplicationVersionHolder.INSTANCE.initializeFromClassContext();
assertThat(ApplicationVersionHolder.INSTANCE.getApplicationVersion().getVersion()).isNotBlank();
assertThat(ApplicationVersionHolder.INSTANCE.getApplicationVersion().getVersion()).isNotEqualToIgnoringCase("unknown");
assertThat(ApplicationVersionHolder.INSTANCE.getApplicationVersion().getVersion()).describedAs("Version loaded from version.properties is not expected to contain unresolved property expression - Hint: use gradle to build to have proper resolved version.properties").doesNotContain("${");
}

}
49 changes: 49 additions & 0 deletions version.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Version of the scenarioo viewer web application.
* This version is taken from git version information via `git describe`
* which is a nice version number in case of a properly tagged release version
* or otherwise a version number including the git commit hash for any non-release versions (like developer snapshot releases).
*/
ext.scenariooViewerVersion = getVersionFromGit()

/**
* Used Version of Scenarioo Java Library for reading scenarioo docu data
*/
ext.scenariooApiVersion = '2.1.1'

/**
* Internal scenarioo format version of produced aggregation data (internal server format version).
*
* On import this version is stored for each build, if the format of a build does not correspond to this format, the
* build is automatically reimported again (all aggregation data recalculated in new format).
*
* First part of the version corresponds to library version that is supported, second part of the version depends on
* internal aggregation format. the second part should be increased whenever something important is changed in the
* internal format or the way that the aggregator is caluclating internal data on builds.
*/
ext.scenariooAggregatedDataFormatVersion = '2.1.0'

/**
* Name of the release branch of this scenarioo version, which is used for links to the versioned documentation.
*/
ext.documentationVersion = '5.0'

/**
* Build date for version properties file
*/
ext.buildDate = new Date()

/**
* Gets the version name from the latest Git tag
* From: http://ryanharter.com/blog/2013/07/30/automatic-versioning-with-git-and-gradle/
*/
def getVersionFromGit() {
def stdout = new ByteArrayOutputStream()
exec {
commandLine 'git', 'describe', '--tags'
standardOutput = stdout
}
def version = stdout.toString().trim()
println "Version from git: ${version}"
return version
}