diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 9bcc43dca7fd..88f53f13418b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -44,6 +44,12 @@ jobs: - name: Checkout codebase uses: actions/checkout@v3 + # Generate deployed-version info (git hash, commit date, build run) into a file + # that the backend exposes as `buildVersion` on the REST root endpoint (issue #813). + # Must run before the Docker build so the file is included in the image. + - name: Add version + run: python scripts/sourceversion.py ${{ github.server_url }}/${{ github.repository }}/actions/runs/ ${{ github.run_id }} > dspace/config/VERSION_D.txt + # https://github.com/docker/setup-buildx-action - name: Setup Docker Buildx uses: docker/setup-buildx-action@v2 diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java index 61f18a5b3c9c..f9d20fcb9b2d 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/RootConverter.java @@ -9,6 +9,11 @@ import static org.dspace.app.util.Util.getSourceVersion; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; + +import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.model.RootRest; import org.dspace.services.ConfigurationService; import org.springframework.beans.factory.annotation.Autowired; @@ -29,6 +34,37 @@ public RootRest convert() { rootRest.setDspaceUI(configurationService.getProperty("dspace.ui.url")); rootRest.setDspaceServer(configurationService.getProperty("dspace.server.url")); rootRest.setDspaceVersion("DSpace " + getSourceVersion()); + rootRest.setBuildVersion(getBuildVersion()); return rootRest; } + + /** + * Read the build version from the `build.version.file.path` property + * + * @return content of the version file + */ + private String getBuildVersion() { + String bVersionFilePath = configurationService.getProperty("build.version.file.path"); + + if (StringUtils.isBlank(bVersionFilePath)) { + return "Unknown"; + } + + StringBuilder buildVersion = new StringBuilder(); + try { + FileReader fileReader = new FileReader(bVersionFilePath); + BufferedReader bufferedReader = new BufferedReader(fileReader); + + String line; + // Read each line from the file until the end of the file is reached + while ((line = bufferedReader.readLine()) != null) { + buildVersion.append(line); + } + + } catch (IOException e) { + // Empty - do not log anything + } + + return buildVersion.toString(); + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java index cef8965601ca..b1eddec47d4b 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/RootRest.java @@ -21,6 +21,7 @@ public class RootRest extends RestAddressableModel { private String dspaceName; private String dspaceServer; private String dspaceVersion; + private String buildVersion; public String getCategory() { return CATEGORY; @@ -67,6 +68,14 @@ public void setDspaceVersion(String dspaceVersion) { this.dspaceVersion = dspaceVersion; } + public String getBuildVersion() { + return buildVersion; + } + + public void setBuildVersion(String buildVersion) { + this.buildVersion = buildVersion; + } + @Override public boolean equals(Object object) { return (object instanceof RootRest && @@ -76,6 +85,7 @@ public boolean equals(Object object) { .append(this.getDspaceUI(), ((RootRest) object).getDspaceUI()) .append(this.getDspaceName(), ((RootRest) object).getDspaceName()) .append(this.getDspaceServer(), ((RootRest) object).getDspaceServer()) + .append(this.getBuildVersion(), ((RootRest) object).getBuildVersion()) .isEquals()); } @@ -88,6 +98,7 @@ public int hashCode() { .append(this.getDspaceName()) .append(this.getDspaceUI()) .append(this.getDspaceServer()) + .append(this.getBuildVersion()) .toHashCode(); } } diff --git a/dspace/config/VERSION_D.txt b/dspace/config/VERSION_D.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/dspace/config/clarin-dspace.cfg b/dspace/config/clarin-dspace.cfg index 7bad095eb855..bcd0c93011e7 100644 --- a/dspace/config/clarin-dspace.cfg +++ b/dspace/config/clarin-dspace.cfg @@ -218,4 +218,8 @@ identifiers.item-status.register-doi = true ##### Dataquest URL - sing in the footer ##### themed.by.url = https://www.dataquest.sk/dspace -themed.by.company.name = dataquest s.r.o. \ No newline at end of file +themed.by.company.name = dataquest s.r.o. + +### The build version is stored in the specific file (issue #813) ### +### Exposed as `buildVersion` on the REST root endpoint (/server/api). ### +build.version.file.path = ${dspace.dir}/config/VERSION_D.txt \ No newline at end of file diff --git a/scripts/sourceversion.py b/scripts/sourceversion.py new file mode 100644 index 000000000000..b838d70708c8 --- /dev/null +++ b/scripts/sourceversion.py @@ -0,0 +1,22 @@ +import subprocess +import sys +from datetime import datetime, timezone + +def get_time_in_timezone(zone: str = "Europe/Bratislava"): + try: + from zoneinfo import ZoneInfo + my_tz = ZoneInfo(zone) + except Exception as e: + my_tz = timezone.utc + return datetime.now(my_tz) + + +if __name__ == '__main__': + ts = get_time_in_timezone() + print(f"This info was generated on: {ts.strftime('%Y-%m-%d %H:%M:%S %Z%z')}") + + cmd = 'git log -1 --pretty=format:"Git hash: %H Date of commit: %ai"' + subprocess.check_call(cmd, shell=True) + + link = sys.argv[1] + sys.argv[2] + print(' Build run: ' + link + ' ')