feat: prerelease workflow with major version support and version propagation

- Add docker-dev.yml: prerelease CI for dev branch with minor/major bump
  inputs; auto-continues in-flight major line via existing pre tags;
  publishes floating major-pre Docker tag (e.g. 2-pre)
- Rewrite docker.yml version-bump: tag-based versioning, manual bump
  inputs (auto/patch/minor/major), major guarded by confirm_major=MAJOR,
  auto-finalizes in-flight prereleases; publishes floating major tag (e.g. 2)
- Inject APP_VERSION build-arg through Dockerfile so the running container
  knows its real version instead of reading package.json
- Server reads APP_VERSION env in authService/adminService; exposes
  is_prerelease in app config and update-check response; prerelease builds
  compare against GitHub prerelease releases rather than latest stable
- Client stores isPrerelease from config; navbar shows amber version badge
  on prerelease builds (left of dark-mode toggle); GitHubPanel filters out
  prerelease releases unless the running build is itself a prerelease
This commit is contained in:
jubnl
2026-04-12 16:24:20 +02:00
parent 3ad1bef134
commit 981b667fbb
10 changed files with 278 additions and 39 deletions
+3 -2
View File
@@ -88,16 +88,17 @@ function RootRedirect() {
}
export default function App() {
const { loadUser, isAuthenticated, demoMode, setDemoMode, setDevMode, setHasMapsKey, setServerTimezone, setAppRequireMfa, setTripRemindersEnabled } = useAuthStore()
const { loadUser, isAuthenticated, demoMode, setDemoMode, setDevMode, setIsPrerelease, setHasMapsKey, setServerTimezone, setAppRequireMfa, setTripRemindersEnabled } = useAuthStore()
const { loadSettings } = useSettingsStore()
useEffect(() => {
if (!location.pathname.startsWith('/shared/') && !location.pathname.startsWith('/public/') && !location.pathname.startsWith('/login')) {
loadUser()
}
authApi.getAppConfig().then(async (config: { demo_mode?: boolean; dev_mode?: boolean; has_maps_key?: boolean; version?: string; timezone?: string; require_mfa?: boolean; trip_reminders_enabled?: boolean; permissions?: Record<string, PermissionLevel> }) => {
authApi.getAppConfig().then(async (config: { demo_mode?: boolean; dev_mode?: boolean; is_prerelease?: boolean; has_maps_key?: boolean; version?: string; timezone?: string; require_mfa?: boolean; trip_reminders_enabled?: boolean; permissions?: Record<string, PermissionLevel> }) => {
if (config?.demo_mode) setDemoMode(true)
if (config?.dev_mode) setDevMode(true)
if (config?.is_prerelease !== undefined) setIsPrerelease(config.is_prerelease)
if (config?.has_maps_key !== undefined) setHasMapsKey(config.has_maps_key)
if (config?.timezone) setServerTimezone(config.timezone)
if (config?.require_mfa !== undefined) setAppRequireMfa(!!config.require_mfa)