diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml index 4ab7a210..e8a400f4 100644 --- a/.github/workflows/dockerhub.yml +++ b/.github/workflows/dockerhub.yml @@ -60,6 +60,7 @@ jobs: build-args: | APP_ENV=${{ env.VERSION == 'dev' && 'local' || 'production' }} COMPOSER_FLAGS=${{ env.VERSION == 'dev' && '--optimize-autoloader --no-interaction' || '--no-dev --optimize-autoloader --no-interaction' }} + APP_VERSION=${{ env.VERSION }} tags: ${{ env.API_TAGS }} cache-from: type=registry,ref=${{secrets.DOCKER_API_REPO}}:dev cache-to: type=inline @@ -71,6 +72,8 @@ jobs: file: docker/Dockerfile.client platforms: linux/amd64,linux/arm64 push: true + build-args: | + APP_VERSION=${{ env.VERSION }} tags: ${{ env.UI_TAGS }} cache-from: type=registry,ref=${{secrets.DOCKER_UI_REPO}}:dev cache-to: type=inline diff --git a/api/app/Http/Controllers/Content/FeatureFlagsController.php b/api/app/Http/Controllers/Content/FeatureFlagsController.php index 43ff0b57..dd7cae53 100644 --- a/api/app/Http/Controllers/Content/FeatureFlagsController.php +++ b/api/app/Http/Controllers/Content/FeatureFlagsController.php @@ -14,6 +14,7 @@ class FeatureFlagsController extends Controller 'self_hosted' => config('app.self_hosted', true), 'custom_domains' => config('custom-domains.enabled', false), 'ai_features' => !empty(config('services.openai.api_key')), + 'version' => $this->getAppVersion(), 'billing' => [ 'enabled' => !empty(config('cashier.key')) && !empty(config('cashier.secret')), @@ -44,4 +45,17 @@ class FeatureFlagsController extends Controller return response()->json($featureFlags); } + + /** + * Get the application version from Docker environment or fallback + */ + private function getAppVersion(): ?string + { + // Only return version for self-hosted installations + if (!config('app.self_hosted', true)) { + return null; + } + + return config('app.docker_version'); + } } diff --git a/api/config/app.php b/api/config/app.php index e409eb8b..dddc163f 100644 --- a/api/config/app.php +++ b/api/config/app.php @@ -15,6 +15,17 @@ return [ 'name' => env('APP_NAME', 'OpnForm'), + /* + |-------------------------------------------------------------------------- + | Application Version + |-------------------------------------------------------------------------- + | + | This value is the version of your application. Used for display purposes + | and fallback when Docker build version is not available. + | + */ + 'docker_version' => env('APP_VERSION_DOCKER'), + /* |-------------------------------------------------------------------------- | Application Environment diff --git a/client/components/pages/OpenFormFooter.vue b/client/components/pages/OpenFormFooter.vue index fa61bf8f..0a7e881a 100644 --- a/client/components/pages/OpenFormFooter.vue +++ b/client/components/pages/OpenFormFooter.vue @@ -4,6 +4,9 @@

© Copyright {{ currYear }}. All Rights Reserved + +
Version {{ version }} +

@@ -82,22 +85,14 @@
- diff --git a/client/middleware/self-hosted-credentials.js b/client/middleware/self-hosted-credentials.js index be46fbbc..d7d6265b 100644 --- a/client/middleware/self-hosted-credentials.js +++ b/client/middleware/self-hosted-credentials.js @@ -1,11 +1,5 @@ export default defineNuxtRouteMiddleware(async () => { const authStore = useAuthStore() - const featureFlagsStore = useFeatureFlagsStore() - - // Ensure feature flags are loaded - if (!featureFlagsStore.isLoaded) { - await featureFlagsStore.fetchFlags() - } if (useFeatureFlag('self_hosted')) { if (authStore.check && authStore.user?.email === 'admin@opnform.com') { diff --git a/client/plugins/feature-flags.js b/client/plugins/feature-flags.js deleted file mode 100644 index 2c067660..00000000 --- a/client/plugins/feature-flags.js +++ /dev/null @@ -1,10 +0,0 @@ -import { useFeatureFlagsStore } from '~/stores/featureFlags' - -export default defineNuxtPlugin(async () => { - const featureFlagsStore = useFeatureFlagsStore() - - // Load flags if they haven't been loaded yet - if (!featureFlagsStore.isLoaded) { - await featureFlagsStore.fetchFlags() - } -}) \ No newline at end of file diff --git a/client/plugins/featureFlags.js b/client/plugins/featureFlags.js index 35cbca2f..1bcc8b0c 100644 --- a/client/plugins/featureFlags.js +++ b/client/plugins/featureFlags.js @@ -1,9 +1,18 @@ import { useFeatureFlagsStore } from '~/stores/featureFlags' -export default defineNuxtPlugin((nuxtApp) => { - const featureFlagsStore = useFeatureFlagsStore() +export default defineNuxtPlugin(async (nuxtApp) => { + // Get the pinia instance for SSR compatibility + const { $pinia } = nuxtApp - nuxtApp.provide('featureFlag', (key, defaultValue = false) => { - return featureFlagsStore.getFlag(key, defaultValue) - }) + try { + // Pass pinia instance for SSR compatibility + const featureFlagsStore = useFeatureFlagsStore($pinia) + + // Fetch flags during SSR to prevent hydration mismatches + if (!featureFlagsStore.isLoaded) { + await featureFlagsStore.fetchFlags() + } + } catch (error) { + console.error('Feature flags plugin failed:', error) + } }) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index c1ca2438..39194bdf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,11 @@ --- services: api: &api-environment - image: jhumanj/opnform-api:latest + build: + context: . + dockerfile: docker/Dockerfile.api + args: + APP_VERSION: "local-test-1.0.0" container_name: opnform-api volumes: &api-environment-volumes - opnform_storage:/usr/share/nginx/html/storage:rw @@ -62,7 +66,11 @@ services: start_period: 70s # Allow time for first scheduled run and cache write ui: - image: jhumanj/opnform-client:latest + build: + context: . + dockerfile: docker/Dockerfile.client + args: + APP_VERSION: "local-test-1.0.0" container_name: opnform-client env_file: - ./client/.env diff --git a/docker/Dockerfile.api b/docker/Dockerfile.api index a2055666..a3e5b9ec 100644 --- a/docker/Dockerfile.api +++ b/docker/Dockerfile.api @@ -27,6 +27,9 @@ RUN composer install --optimize-autoloader --no-interaction \ # Final stage - smaller runtime image FROM php:8.3-fpm-alpine +# Accept version build argument +ARG APP_VERSION=unknown + # Install runtime dependencies RUN apk add --no-cache \ libzip \ @@ -75,6 +78,9 @@ RUN mkdir -p storage/framework/sessions \ # Copy the entire application from the builder stage COPY --from=builder /app/ ./ +# Set version as environment variable (more reliable than file approach) +ENV APP_VERSION_DOCKER=$APP_VERSION + # Setup entrypoint COPY docker/php-fpm-entrypoint /usr/local/bin/opnform-entrypoint RUN chmod a+x /usr/local/bin/*