Merge pull request 'feature/dynamic-version' (#12) from feature/dynamic-version into main
Reviewed-on: https://git.walzen665.de/Walzen665/sharepulse/pulls/12
This commit is contained in:
commit
b8b0242240
@ -1,4 +1,4 @@
|
|||||||
name: SharePulse Build
|
name: SharePulse build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -42,11 +42,29 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: jar-artifact
|
name: jar-artifact
|
||||||
path: build/libs/*.jar
|
path: build/libs/*.jar
|
||||||
|
|
||||||
build-docker-image:
|
build-docker-image:
|
||||||
needs: build-jar
|
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
|
needs: build-jar
|
||||||
steps:
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Extract tag name
|
||||||
|
run: |
|
||||||
|
git fetch --tags
|
||||||
|
GIT_TAG=$(git tag --points-at HEAD)
|
||||||
|
if [[ "$GIT_TAG" == v* ]]; then
|
||||||
|
VERSION=${GIT_TAG#v}
|
||||||
|
echo "Version tag found. Initializing docker image build for version: $VERSION"
|
||||||
|
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
||||||
|
else
|
||||||
|
echo "No version tag found. Skipping subsequent steps. (Version tag format: vX.X.X)"
|
||||||
|
echo "SKIP_SUBSEQUENT_STEPS=true" >> $GITHUB_ENV
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Initialize Docker runtime
|
- name: Initialize Docker runtime
|
||||||
|
if: env.SKIP_SUBSEQUENT_STEPS != 'true'
|
||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install ca-certificates curl gnupg lsb-release -y
|
apt-get install ca-certificates curl gnupg lsb-release -y
|
||||||
@ -60,23 +78,27 @@ jobs:
|
|||||||
apt-get update
|
apt-get update
|
||||||
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin -y
|
apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin -y
|
||||||
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download Artifact
|
- name: Download Artifact
|
||||||
|
if: env.SKIP_SUBSEQUENT_STEPS != 'true'
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: jar-artifact
|
name: jar-artifact
|
||||||
path: build/libs
|
path: build/libs
|
||||||
|
|
||||||
- name: Build Docker Image
|
- name: Build Docker Image
|
||||||
run: docker build . -t walzen665/sharepulse:latest
|
if: env.SKIP_SUBSEQUENT_STEPS != 'true'
|
||||||
|
run: docker build . -t walzen665/sharepulse:$VERSION
|
||||||
|
|
||||||
- name: Tag Docker image
|
- name: Tag Docker image
|
||||||
run: docker tag walzen665/sharepulse:latest git.walzen665.de/walzen665/sharepulse:latest
|
if: env.SKIP_SUBSEQUENT_STEPS != 'true'
|
||||||
|
run: docker tag walzen665/sharepulse:latest git.walzen665.de/walzen665/sharepulse:$VERSION
|
||||||
|
|
||||||
- name: Log in to Gitea Docker Registry
|
- name: Log in to Gitea Docker Registry
|
||||||
|
if: env.SKIP_SUBSEQUENT_STEPS != 'true'
|
||||||
run: echo ${{ secrets.GITEAREGISTRYTOKEN }} | docker login -u ${{ secrets.GITEAREGISTRYUSERNAME }} --password-stdin https://git.walzen665.de
|
run: echo ${{ secrets.GITEAREGISTRYTOKEN }} | docker login -u ${{ secrets.GITEAREGISTRYUSERNAME }} --password-stdin https://git.walzen665.de
|
||||||
|
|
||||||
- name: Push Docker Image to Gitea
|
- name: Push Docker Image to Gitea
|
||||||
run: docker push git.walzen665.de/walzen665/sharepulse:latest
|
if: env.SKIP_SUBSEQUENT_STEPS != 'true'
|
||||||
|
run: docker push git.walzen665.de/walzen665/sharepulse:$VERSION
|
||||||
|
|
||||||
|
|
||||||
|
45
README.md
45
README.md
@ -13,3 +13,48 @@ Requirements:
|
|||||||
1. Update `spring.profiles.active` in `application.properties` to `development`
|
1. Update `spring.profiles.active` in `application.properties` to `development`
|
||||||
2. Start external Backend and Database
|
2. Start external Backend and Database
|
||||||
3. Run `./gradlew bootRun ` in the root directory
|
3. Run `./gradlew bootRun ` in the root directory
|
||||||
|
|
||||||
|
# Running SharePulse using Docker
|
||||||
|
```yml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
sharepulse:
|
||||||
|
image: git.walzen665.de/walzen665/sharepulse:latest
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
environment:
|
||||||
|
# All Configurable parameters with default values
|
||||||
|
# Can be deleted if default values are used
|
||||||
|
RETHINKDB_HOST: rethinkdb
|
||||||
|
RETHINKDB_PORT: 28015
|
||||||
|
RETHINKDB_DATABASE: sharepulse
|
||||||
|
SHAREPULSE_FILEPASSWORD_LENGTH: "6"
|
||||||
|
SHAREPULSE_FILEID_LENGTH: "6"
|
||||||
|
SHAREPULSE_TEMP_FILESTORE_PATH: "/temp-filestore"
|
||||||
|
SHAREPULSE_AUTO_RESET_ON_STARTUP: "true"
|
||||||
|
MAX_FILE_SIZE: "1GB"
|
||||||
|
MAX_REQUEST_SIZE: "1GB"
|
||||||
|
depends_on:
|
||||||
|
- rethinkdb
|
||||||
|
networks:
|
||||||
|
- sharepulse-net
|
||||||
|
|
||||||
|
rethinkdb:
|
||||||
|
image: rethinkdb:latest
|
||||||
|
volumes:
|
||||||
|
- rethinkdb_data:/data
|
||||||
|
ports:
|
||||||
|
- "28015:28015"
|
||||||
|
# - "8080:8080" Webinterface of rethinkdb (optional and only accessible from localhost)
|
||||||
|
networks:
|
||||||
|
- sharepulse-net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
sharepulse-net:
|
||||||
|
external: false
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
rethinkdb_data:
|
||||||
|
|
||||||
|
```
|
@ -40,6 +40,9 @@ dependencies {
|
|||||||
|
|
||||||
bootJar {
|
bootJar {
|
||||||
manifest {
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Application-Version': project.version
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,11 +15,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-4 hover:scale-125 transition-transform duration-100">
|
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-4 hover:scale-125 transition-transform duration-100">
|
||||||
<h3 class="font-semibold text-gray-800 sm:col-span-2 md:text-right">Version:</h3>
|
<h3 class="font-semibold text-gray-800 sm:col-span-2 md:text-right">Version:</h3>
|
||||||
<p class="text-gray-800 sm:col-span-2 sm:text-left">1.0.0</p>
|
<p class="text-gray-800 sm:col-span-2 sm:text-left">
|
||||||
|
<span class="loading loading-spinner loading-md" *ngIf="!version"></span>
|
||||||
|
<span *ngIf="version">{{ version }}</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-4 hover:scale-125 transition-transform duration-100">
|
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-4 hover:scale-125 transition-transform duration-100">
|
||||||
<h3 class="font-semibold text-gray-800 sm:col-span-2 md:text-right">API-Status:</h3>
|
<h3 class="font-semibold text-gray-800 sm:col-span-2 md:text-right">API-Status:</h3>
|
||||||
<p class="sm:col-span-2 sm:text-left text-green-600">online</p>
|
<span class="loading loading-spinner loading-md" *ngIf="!version"></span>
|
||||||
|
<p class="sm:col-span-2 sm:text-left text-green-600" *ngIf="version">online</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-4 hover:scale-125 transition-transform duration-100">
|
<div class="grid grid-cols-1 sm:grid-cols-4 items-center gap-4 hover:scale-125 transition-transform duration-100">
|
||||||
<h3 class=" font-semibold text-gray-800 sm:col-span-2 md:text-right">Libraries:</h3>
|
<h3 class=" font-semibold text-gray-800 sm:col-span-2 md:text-right">Libraries:</h3>
|
||||||
|
@ -1,19 +1,26 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import {RouterLink} from "@angular/router";
|
import {RouterLink} from "@angular/router";
|
||||||
import {LegalService} from "../../service/legalService";
|
import {LegalService} from "../../service/legalService";
|
||||||
|
import axios from "axios";
|
||||||
|
import {DevelopmentStore} from "../../store/DevelopmentStore";
|
||||||
|
import {NgIf} from "@angular/common";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-credits',
|
selector: 'app-credits',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
RouterLink
|
RouterLink,
|
||||||
|
NgIf
|
||||||
],
|
],
|
||||||
templateUrl: './credits.component.html',
|
templateUrl: './credits.component.html',
|
||||||
styleUrl: './credits.component.scss'
|
styleUrl: './credits.component.scss'
|
||||||
})
|
})
|
||||||
export class CreditsComponent {
|
export class CreditsComponent {
|
||||||
|
|
||||||
constructor(private legalService: LegalService) {
|
version: string = '';
|
||||||
|
|
||||||
|
constructor(private legalService: LegalService, private developmentStore: DevelopmentStore) {
|
||||||
|
this.getVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
openPrivacyPolicyModal() {
|
openPrivacyPolicyModal() {
|
||||||
@ -23,4 +30,14 @@ export class CreditsComponent {
|
|||||||
openTermsOfUseModal() {
|
openTermsOfUseModal() {
|
||||||
this.legalService.openTermsOfUse();
|
this.legalService.openTermsOfUse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getVersion() {
|
||||||
|
axios.get(this.developmentStore.getBaseUrl() + 'api/v1/version')
|
||||||
|
.then((response) => {
|
||||||
|
this.version = response.data;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,9 +101,6 @@ export class DownloadComponent {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: this.developmentStore.getBaseUrl() + 'api/v1/speed-test',
|
url: this.developmentStore.getBaseUrl() + 'api/v1/speed-test',
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
headers: {
|
|
||||||
'Access-Control-Allow-Origin': '*', // Allow CORS
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const end = new Date().getTime(); // End timer
|
const end = new Date().getTime(); // End timer
|
||||||
@ -124,9 +121,6 @@ export class DownloadComponent {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: this.developmentStore.getBaseUrl() + 'api/v1/download-info?fileId=' + this.fileId,
|
url: this.developmentStore.getBaseUrl() + 'api/v1/download-info?fileId=' + this.fileId,
|
||||||
responseType: 'json',
|
responseType: 'json',
|
||||||
headers: {
|
|
||||||
'Access-Control-Allow-Origin': '*', // Allow CORS
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.downloadInfo = response.data;
|
this.downloadInfo = response.data;
|
||||||
@ -146,9 +140,6 @@ export class DownloadComponent {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
url: this.developmentStore.getBaseUrl() + 'api/v1/download?fileId=' + this.fileId + '&password=' + this.filePassword,
|
url: this.developmentStore.getBaseUrl() + 'api/v1/download?fileId=' + this.fileId + '&password=' + this.filePassword,
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
headers: {
|
|
||||||
'Access-Control-Allow-Origin': '*', // Allow CORS
|
|
||||||
},
|
|
||||||
onDownloadProgress: (progressEvent) => {
|
onDownloadProgress: (progressEvent) => {
|
||||||
const endTime = new Date().getTime();
|
const endTime = new Date().getTime();
|
||||||
const duration = (endTime - startTime) / 1000;
|
const duration = (endTime - startTime) / 1000;
|
||||||
|
@ -85,7 +85,6 @@ export class UploadComponent {
|
|||||||
const config = {
|
const config = {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
'Access-Control-Allow-Origin': '*', // Allow CORS
|
|
||||||
},
|
},
|
||||||
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
|
onUploadProgress: (progressEvent: AxiosProgressEvent) => {
|
||||||
if (progressEvent.total) {
|
if (progressEvent.total) {
|
||||||
@ -156,7 +155,6 @@ export class UploadComponent {
|
|||||||
data: uint8View,
|
data: uint8View,
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/octet-stream',
|
'Content-Type': 'application/octet-stream',
|
||||||
'Access-Control-Allow-Origin': '*', // Allow CORS
|
|
||||||
},
|
},
|
||||||
onUploadProgress: function(progressEvent) {
|
onUploadProgress: function(progressEvent) {
|
||||||
// Optional: handle progress events for feedback
|
// Optional: handle progress events for feedback
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package de.w665.sharepulse.rest;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.servlet.error.ErrorController;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used to redirect the user to the home page if an endpoint is not found.
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
public class ErrorRestController implements ErrorController {
|
||||||
|
@RequestMapping("/error")
|
||||||
|
public String handleError() {
|
||||||
|
return "<script>" +
|
||||||
|
"console.log('Page not found. Redirecting to /home...');" +
|
||||||
|
"window.location.href = window.location.origin + '/home';" +
|
||||||
|
"</script>";
|
||||||
|
}
|
||||||
|
}
|
37
src/main/java/de/w665/sharepulse/rest/mappings/Version.java
Normal file
37
src/main/java/de/w665/sharepulse/rest/mappings/Version.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package de.w665.sharepulse.rest.mappings;
|
||||||
|
|
||||||
|
import com.rethinkdb.net.Response;
|
||||||
|
import de.w665.sharepulse.rest.ApiRestController;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class Version extends ApiRestController {
|
||||||
|
|
||||||
|
private final ResourceLoader resourceLoader;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public Version(ResourceLoader resourceLoader) {
|
||||||
|
this.resourceLoader = resourceLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/version")
|
||||||
|
public ResponseEntity<Object> getVersion() throws Exception {
|
||||||
|
Resource resource = resourceLoader.getResource("classpath:META-INF/MANIFEST.MF");
|
||||||
|
Manifest manifest = new Manifest(resource.getInputStream());
|
||||||
|
Attributes attr = manifest.getMainAttributes();
|
||||||
|
String version = attr.getValue("Application-Version");
|
||||||
|
String response = version != null ? version : "Version is only available in production builds";
|
||||||
|
return new ResponseEntity<>(response, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user