Release 0.9.3
This commit is contained in:
@@ -4,6 +4,7 @@ WORKDIR /build/frontend
|
|||||||
ARG VITE_API_URL=/api
|
ARG VITE_API_URL=/api
|
||||||
ENV VITE_API_URL=${VITE_API_URL}
|
ENV VITE_API_URL=${VITE_API_URL}
|
||||||
|
|
||||||
|
COPY backend/src/main/resources/application.yml /build/backend/src/main/resources/application.yml
|
||||||
COPY frontend/package*.json ./
|
COPY frontend/package*.json ./
|
||||||
RUN npm ci
|
RUN npm ci
|
||||||
|
|
||||||
@@ -19,7 +20,8 @@ RUN mvn -B -q -DskipTests dependency:go-offline
|
|||||||
|
|
||||||
COPY backend/ ./
|
COPY backend/ ./
|
||||||
COPY --from=frontend-build /build/frontend/dist ./src/main/resources/static
|
COPY --from=frontend-build /build/frontend/dist ./src/main/resources/static
|
||||||
RUN mvn -B -q -DskipTests package
|
RUN mvn -B -q -DskipTests package \
|
||||||
|
&& cp "$(find target -maxdepth 1 -type f -name '*.jar' ! -name '*.original' | head -n 1)" /build/backend/app.jar
|
||||||
|
|
||||||
|
|
||||||
FROM eclipse-temurin:21-jre-alpine AS runtime
|
FROM eclipse-temurin:21-jre-alpine AS runtime
|
||||||
@@ -27,7 +29,7 @@ WORKDIR /app
|
|||||||
|
|
||||||
RUN addgroup -S spring && adduser -S spring -G spring
|
RUN addgroup -S spring && adduser -S spring -G spring
|
||||||
|
|
||||||
COPY --from=backend-build /build/backend/target/muh-backend-0.0.1-SNAPSHOT.jar /app/app.jar
|
COPY --from=backend-build /build/backend/app.jar /app/app.jar
|
||||||
|
|
||||||
USER spring:spring
|
USER spring:spring
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ spring:
|
|||||||
enable: ${MUH_MAIL_STARTTLS:false}
|
enable: ${MUH_MAIL_STARTTLS:false}
|
||||||
|
|
||||||
muh:
|
muh:
|
||||||
|
app:
|
||||||
|
version: 0.9.3
|
||||||
cors:
|
cors:
|
||||||
allowed-origins: ${MUH_ALLOWED_ORIGINS:http://localhost:5173,http://localhost:3000}
|
allowed-origins: ${MUH_ALLOWED_ORIGINS:http://localhost:5173,http://localhost:3000}
|
||||||
security:
|
security:
|
||||||
|
|||||||
99
docker_push.sh
Executable file
99
docker_push.sh
Executable file
@@ -0,0 +1,99 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
readonly SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
readonly REGISTRY_IMAGE="registry.assecutor.org/muh"
|
||||||
|
readonly APP_CONFIG_FILE="${SCRIPT_DIR}/backend/src/main/resources/application.yml"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Verwendung:
|
||||||
|
./docker_push.sh [x.y.z]
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
./docker_push.sh 0.9.13
|
||||||
|
./docker_push.sh
|
||||||
|
|
||||||
|
Voraussetzungen:
|
||||||
|
- Docker Buildx ist installiert
|
||||||
|
- Login zur Registry wurde bereits ausgeführt:
|
||||||
|
docker login registry.assecutor.org
|
||||||
|
|
||||||
|
Ohne Versionsargument wird automatisch die Version aus backend/src/main/resources/application.yml verwendet.
|
||||||
|
Optional kann VITE_API_URL als Umgebungsvariable gesetzt werden.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo "Fehler: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
require_command() {
|
||||||
|
command -v "$1" >/dev/null 2>&1 || fail "'$1' wurde nicht gefunden."
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_app_version() {
|
||||||
|
[[ -f "${APP_CONFIG_FILE}" ]] || fail "'${APP_CONFIG_FILE}' wurde nicht gefunden."
|
||||||
|
|
||||||
|
local version
|
||||||
|
version="$(
|
||||||
|
awk '
|
||||||
|
$0 ~ /^muh:[[:space:]]*$/ {
|
||||||
|
in_muh = 1
|
||||||
|
in_app = 0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
in_muh && $0 ~ /^[^[:space:]]/ {
|
||||||
|
in_muh = 0
|
||||||
|
in_app = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
in_muh && $0 ~ /^[[:space:]][[:space:]]app:[[:space:]]*$/ {
|
||||||
|
in_app = 1
|
||||||
|
next
|
||||||
|
}
|
||||||
|
|
||||||
|
in_app && $0 ~ /^[[:space:]][[:space:]][^[:space:]]/ {
|
||||||
|
in_app = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
in_muh && in_app && match($0, /^[[:space:]][[:space:]][[:space:]][[:space:]]version:[[:space:]]*"?([0-9]+\.[0-9]+\.[0-9]+)"?[[:space:]]*$/, a) {
|
||||||
|
print a[1]
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
' "${APP_CONFIG_FILE}"
|
||||||
|
)"
|
||||||
|
|
||||||
|
[[ -n "${version}" ]] || fail "Version konnte nicht aus ${APP_CONFIG_FILE} ermittelt werden."
|
||||||
|
echo "${version}"
|
||||||
|
}
|
||||||
|
|
||||||
|
VERSION="${1:-$(resolve_app_version)}"
|
||||||
|
|
||||||
|
if [[ "${VERSION}" == "-h" || "${VERSION}" == "--help" ]]; then
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
fail "Versionsnummer muss das Format x.y.z haben."
|
||||||
|
fi
|
||||||
|
|
||||||
|
require_command docker
|
||||||
|
docker buildx version >/dev/null 2>&1 || fail "Docker Buildx ist nicht verfügbar."
|
||||||
|
|
||||||
|
cd "${SCRIPT_DIR}"
|
||||||
|
|
||||||
|
echo "Verwende Release-Version ${VERSION}."
|
||||||
|
echo "Pushe Image ${REGISTRY_IMAGE}:${VERSION} ..."
|
||||||
|
docker buildx build \
|
||||||
|
--platform linux/amd64 \
|
||||||
|
--build-arg "VITE_API_URL=${VITE_API_URL:-/api}" \
|
||||||
|
-t "${REGISTRY_IMAGE}:${VERSION}" \
|
||||||
|
--push \
|
||||||
|
.
|
||||||
|
|
||||||
|
echo "Fertig: ${REGISTRY_IMAGE}:${VERSION}"
|
||||||
2
frontend/src/globals.d.ts
vendored
2
frontend/src/globals.d.ts
vendored
@@ -1 +1,3 @@
|
|||||||
|
declare const __APP_VERSION__: string;
|
||||||
|
|
||||||
interface Worker {}
|
interface Worker {}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
|
import { NavLink, Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||||
import { useSession } from "../lib/session";
|
import { useSession } from "../lib/session";
|
||||||
import { APP_VERSION } from "../lib/version";
|
|
||||||
|
|
||||||
const PAGE_TITLES: Record<string, string> = {
|
const PAGE_TITLES: Record<string, string> = {
|
||||||
"/home": "Startseite",
|
"/home": "Startseite",
|
||||||
@@ -43,7 +42,7 @@ export default function AppShell() {
|
|||||||
<aside className="sidebar">
|
<aside className="sidebar">
|
||||||
<div className="sidebar__brand">
|
<div className="sidebar__brand">
|
||||||
<div className="sidebar__logo">
|
<div className="sidebar__logo">
|
||||||
MUH <span className="sidebar__version">({APP_VERSION})</span>
|
MUH <span className="sidebar__version">({__APP_VERSION__})</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
/**
|
|
||||||
* Application Version
|
|
||||||
*
|
|
||||||
* Semantic Versioning: MAJOR.MINOR.PATCH
|
|
||||||
* - MAJOR: Incompatible API changes
|
|
||||||
* - MINOR: New functionality (backward compatible)
|
|
||||||
* - PATCH: Bug fixes (backward compatible)
|
|
||||||
*/
|
|
||||||
export const APP_VERSION = "0.9.2";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build date - set at build time
|
|
||||||
*/
|
|
||||||
export const BUILD_DATE = new Date().toISOString().split('T')[0];
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,7 +1,44 @@
|
|||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
|
const CONFIG_DIR = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const APPLICATION_CONFIG_PATH = path.resolve(CONFIG_DIR, "../backend/src/main/resources/application.yml");
|
||||||
|
function resolveAppVersion() {
|
||||||
|
const lines = fs.readFileSync(APPLICATION_CONFIG_PATH, "utf8").split(/\r?\n/);
|
||||||
|
let inMuhSection = false;
|
||||||
|
let inAppSection = false;
|
||||||
|
for (const line of lines) {
|
||||||
|
const trimmedLine = line.trim();
|
||||||
|
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const indentation = line.length - line.trimStart().length;
|
||||||
|
if (indentation === 0) {
|
||||||
|
inMuhSection = trimmedLine === "muh:";
|
||||||
|
inAppSection = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inMuhSection && indentation === 2) {
|
||||||
|
inAppSection = trimmedLine === "app:";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inMuhSection && inAppSection && indentation === 4 && trimmedLine.startsWith("version:")) {
|
||||||
|
const version = trimmedLine.slice("version:".length).trim().replace(/^['"]|['"]$/g, "");
|
||||||
|
if (/^\d+\.\d+\.\d+$/.test(version)) {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
throw new Error(`Ungueltige Versionsnummer in ${APPLICATION_CONFIG_PATH}: ${version}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`muh.app.version konnte nicht aus ${APPLICATION_CONFIG_PATH} ermittelt werden.`);
|
||||||
|
}
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
define: {
|
||||||
|
__APP_VERSION__: JSON.stringify(resolveAppVersion()),
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
|
|||||||
@@ -1,8 +1,53 @@
|
|||||||
|
import fs from "node:fs";
|
||||||
|
import path from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
import { defineConfig } from "vite";
|
import { defineConfig } from "vite";
|
||||||
import react from "@vitejs/plugin-react";
|
import react from "@vitejs/plugin-react";
|
||||||
|
|
||||||
|
const CONFIG_DIR = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const APPLICATION_CONFIG_PATH = path.resolve(CONFIG_DIR, "../backend/src/main/resources/application.yml");
|
||||||
|
|
||||||
|
function resolveAppVersion(): string {
|
||||||
|
const lines = fs.readFileSync(APPLICATION_CONFIG_PATH, "utf8").split(/\r?\n/);
|
||||||
|
let inMuhSection = false;
|
||||||
|
let inAppSection = false;
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
const trimmedLine = line.trim();
|
||||||
|
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const indentation = line.length - line.trimStart().length;
|
||||||
|
|
||||||
|
if (indentation === 0) {
|
||||||
|
inMuhSection = trimmedLine === "muh:";
|
||||||
|
inAppSection = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inMuhSection && indentation === 2) {
|
||||||
|
inAppSection = trimmedLine === "app:";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inMuhSection && inAppSection && indentation === 4 && trimmedLine.startsWith("version:")) {
|
||||||
|
const version = trimmedLine.slice("version:".length).trim().replace(/^['"]|['"]$/g, "");
|
||||||
|
if (/^\d+\.\d+\.\d+$/.test(version)) {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
throw new Error(`Ungueltige Versionsnummer in ${APPLICATION_CONFIG_PATH}: ${version}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(`muh.app.version konnte nicht aus ${APPLICATION_CONFIG_PATH} ermittelt werden.`);
|
||||||
|
}
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
|
define: {
|
||||||
|
__APP_VERSION__: JSON.stringify(resolveAppVersion()),
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
host: "0.0.0.0",
|
host: "0.0.0.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user