@@ -1,17 +0,0 @@ -import type { NextApiRequest, NextApiResponse } from 'next' - -export default function handler(req: NextApiRequest, res: NextApiResponse) { - if (req.method !== 'GET') { - return res.status(405).json({ error: 'Method not allowed' }) - } - - const env = Object.entries(process.env) - .filter(([key]) => key.startsWith('NEXT_PUBLIC')) - .sort(([a], [b]) => a.localeCompare(b)) - .reduce>((acc, [key, value]) => { - acc[key] = value ?? '' - return acc - }, {}) - - res.status(200).json(env) -} @@ -87,9 +87,9 @@ function App({ Component, pageProps: { session, ...pageProps } }: AppPropsWithLa useBlockTelegram() const { env, loading: envLoading } = useEnv() - const unleashUrl = env?.NEXT_PUBLIC_UNLEASH_URL || process.env.NEXT_PUBLIC_UNLEASH_URL || '' - const unleashClientKey = env?.NEXT_PUBLIC_UNLEASH_CLIENT_KEY || process.env.NEXT_PUBLIC_UNLEASH_CLIENT_KEY || '' - const unleashAppName = env?.NEXT_PUBLIC_UNLEASH_APP_NAME || process.env.NEXT_PUBLIC_UNLEASH_APP_NAME || '' + const unleashUrl = env?.NEXT_PUBLIC_UNLEASH_URL + const unleashClientKey = env?.NEXT_PUBLIC_UNLEASH_CLIENT_KEY + const unleashAppName = env?.NEXT_PUBLIC_UNLEASH_APP_NAME const unleashClient = React.useMemo(() => { if (envLoading) return null @@ -1,20 +1,9 @@ -import { useEffect, useState } from 'react' +import { useEffect, useMemo } from 'react' import { setEnv as setEnvStore } from '#/shared/lib/env-store' import { PublicEnv } from '../env-types' - -const CACHE_TTL_MS = 5 * 60 * 1000 // 5 минут - -let cache: PublicEnv | null = null -let cacheTimestamp = 0 -let fetchPromise: Promise | null = null - -function isCacheValid(): boolean { - return cache !== null && Date.now() - cacheTimestamp < CACHE_TTL_MS -} - -function getProcessEnvFallback(): PublicEnv { +function getProcessEnv(): PublicEnv { return { NEXT_PUBLIC_MAIN_URL: process.env.NEXT_PUBLIC_MAIN_URL ?? '', NEXT_PUBLIC_API_HOST: process.env.NEXT_PUBLIC_API_HOST ?? '', @@ -28,53 +17,12 @@ function getProcessEnvFallback(): PublicEnv { } } -function fetchEnv(): Promise { - if (isCacheValid()) return Promise.resolve(cache!) - if (fetchPromise) return fetchPromise - - fetchPromise = fetch('/api/env') - .then((r) => r.json()) - .then((data) => { - cache = data - cacheTimestamp = Date.now() - setEnvStore(data) - return data - }) - .finally(() => { - fetchPromise = null - }) - - return fetchPromise -} - -export function useEnv(): { env: PublicEnv | null; loading: boolean; error: Error | null } { - const [env, setEnv] = useState(isCacheValid() ? cache : null) - const [loading, setLoading] = useState(!isCacheValid()) - const [error, setError] = useState(null) +export function useEnv(): { env: PublicEnv; loading: boolean; error: Error | null } { + const env = useMemo(() => getProcessEnv(), []) useEffect(() => { - const load = () => { - if (isCacheValid()) { - setEnv(cache) - setLoading(false) - return - } - - fetchEnv() - .then(setEnv) - .catch(() => { - const fallback = getProcessEnvFallback() - setEnvStore(fallback) - setEnv(fallback) - }) - .finally(() => setLoading(false)) - } - - load() - - const interval = setInterval(load, CACHE_TTL_MS) - return () => clearInterval(interval) - }, []) + setEnvStore(env) + }, [env]) - return { env, loading, error } + return { env, loading: false, error: null } } @@ -9,6 +9,8 @@ default: build: stage: Build + variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA script: - cp $BUILD_ENV .env - docker compose build --push @@ -22,6 +24,7 @@ build: services: - docker:dind variables: + IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA ENVIRONMENT: $CI_ENVIRONMENT_TIER DOCKER_TLS_VERIFY: 1 DOCKER_CERT_PATH: "/certs" @@ -40,7 +43,7 @@ build: script: - sort -u -t '=' -k 1,1 $ENV $BUILD_ENV <(echo "RELEASE=$(echo -n $(date '+%D %X'))") > .env - if [ "$(docker info --format '{{.Swarm.LocalNodeState}}' 2>/dev/null)" = "active" ]; then - docker stack deploy --prune --with-registry-auth -c <(docker compose config | grep -v "^name:") $COMPOSE_PROJECT_NAME; + docker stack deploy --with-registry-auth --prune --resolve-image always -c <(docker compose config | grep -v "^name:") $COMPOSE_PROJECT_NAME; else docker compose up -d; fi @@ -1,6 +1,6 @@ services: app: - image: ${CI_REGISTRY_IMAGE:-air/ui/web}:${CI_COMMIT_SHA:-latest} + image: ${IMAGE_TAG:-air/ui/web:latest} build: context: . dockerfile: Dockerfile