From e1a62df40d2c297076121a26761a17b20ca0daa8 Mon Sep 17 00:00:00 2001 From: M_Kececi Date: Tue, 3 Mar 2026 11:06:01 +0300 Subject: [PATCH] Merge remote-tracking branch 'origin/master' --- deploy/deploy.sh | 119 ++++++++++++++++- ...ig.js.temporary.compiled.1772520846397.mjs | 125 ------------------ 2 files changed, 118 insertions(+), 126 deletions(-) delete mode 100644 ui/quasar.config.js.temporary.compiled.1772520846397.mjs diff --git a/deploy/deploy.sh b/deploy/deploy.sh index 0201526..65d033f 100644 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -19,6 +19,8 @@ RUNTIME_PRESERVE_FILES=( "svc/mail.env" "svc/fonts" "svc/public" + "deploy/deploy.sh" + "scripts/deploy.sh" ) log_step() { @@ -98,6 +100,109 @@ purge_nginx_ui_cache() { rm -rf /var/cache/nginx/* || true } +purge_cdn_html_cache() { + # Optional Cloudflare purge. Skip safely if not configured. + local zone_id="${CF_ZONE_ID:-}" + local api_token="${CF_API_TOKEN:-}" + local site_url="${SITE_URL:-https://ss.baggi.com.tr}" + local purge_urls="${CDN_PURGE_URLS:-$site_url/,$site_url/index.html}" + + if [[ -z "$zone_id" || -z "$api_token" ]]; then + echo "CDN purge skipped: CF_ZONE_ID / CF_API_TOKEN not set." + return 0 + fi + + IFS=',' read -r -a url_array <<< "$purge_urls" + if [[ ${#url_array[@]} -eq 0 ]]; then + echo "CDN purge skipped: no URLs configured." + return 0 + fi + + local files_json="" + local sep="" + local url="" + for raw in "${url_array[@]}"; do + url="$(echo "$raw" | xargs)" + [[ -n "$url" ]] || continue + files_json="${files_json}${sep}\"${url}\"" + sep="," + done + + if [[ -z "$files_json" ]]; then + echo "CDN purge skipped: URL list resolved to empty." + return 0 + fi + + local payload + payload="{\"files\":[${files_json}]}" + + local response + response="$(curl -sS -X POST "https://api.cloudflare.com/client/v4/zones/${zone_id}/purge_cache" \ + -H "Authorization: Bearer ${api_token}" \ + -H "Content-Type: application/json" \ + --data "$payload" || true)" + + if echo "$response" | grep -q '"success":true'; then + echo "CDN HTML purge completed." + return 0 + fi + + echo "WARN: CDN purge may have failed. Response: $response" + return 0 +} + +extract_app_js_name() { + local source="$1" + echo "$source" | grep -oE 'app\.[a-f0-9]+\.js' | head -n1 || true +} + +verify_live_ui_hash() { + local site_url="${SITE_URL:-https://ss.baggi.com.tr}" + local fail_on_mismatch="${FAIL_ON_UI_HASH_MISMATCH:-false}" + local local_index="$APP_DIR/ui/dist/spa/index.html" + + if [[ ! -f "$local_index" ]]; then + echo "WARN: local index not found for hash verify: $local_index" + return 0 + fi + + local local_app + local_app="$(extract_app_js_name "$(cat "$local_index")")" + if [[ -z "$local_app" ]]; then + echo "WARN: local app hash parse failed." + return 0 + fi + + local live_html + live_html="$(curl -sS \ + -H "Cache-Control: no-cache" \ + -H "Pragma: no-cache" \ + "${site_url}/" || true)" + if [[ -z "$live_html" ]]; then + echo "WARN: live index fetch failed for ${site_url}/" + return 0 + fi + + local live_app + live_app="$(extract_app_js_name "$live_html")" + if [[ -z "$live_app" ]]; then + echo "WARN: live app hash parse failed." + return 0 + fi + + if [[ "$local_app" == "$live_app" ]]; then + echo "UI HASH OK: ${local_app}" + return 0 + fi + + echo "WARN: UI hash mismatch local=${local_app} live=${live_app}" + if [[ "$fail_on_mismatch" == "true" ]]; then + echo "ERROR: FAIL_ON_UI_HASH_MISMATCH=true and UI hash mismatch detected." + return 1 + fi + return 0 +} + ensure_ui_readable_by_nginx() { local ui_index="$APP_DIR/ui/dist/spa/index.html" @@ -141,7 +246,11 @@ restart_services() { fi if systemctl cat nginx >/dev/null 2>&1; then - systemctl restart nginx + if ! nginx -t; then + echo "ERROR: nginx config test failed" + return 1 + fi + systemctl reload nginx if ! systemctl is-active --quiet nginx; then echo "ERROR: nginx service failed to start" return 1 @@ -177,6 +286,8 @@ run_deploy() { -e svc/mail.env \ -e svc/fonts \ -e svc/public \ + -e deploy/deploy.sh \ + -e scripts/deploy.sh \ -e svc/bssapp restore_runtime_files echo "DEPLOY COMMIT: $(git rev-parse --short HEAD)" @@ -207,6 +318,12 @@ run_deploy() { log_step "PURGE NGINX CACHE" purge_nginx_ui_cache + log_step "PURGE CDN HTML CACHE (OPTIONAL)" + purge_cdn_html_cache + + log_step "VERIFY LIVE UI HASH" + verify_live_ui_hash + echo "[DEPLOY FINISHED] $(date '+%F %T')" } diff --git a/ui/quasar.config.js.temporary.compiled.1772520846397.mjs b/ui/quasar.config.js.temporary.compiled.1772520846397.mjs deleted file mode 100644 index 4a501bd..0000000 --- a/ui/quasar.config.js.temporary.compiled.1772520846397.mjs +++ /dev/null @@ -1,125 +0,0 @@ -/* eslint-disable */ -/** - * THIS FILE IS GENERATED AUTOMATICALLY. - * 1. DO NOT edit this file directly as it won't do anything. - * 2. EDIT the original quasar.config file INSTEAD. - * 3. DO NOT git commit this file. It should be ignored. - * - * This file is still here because there was an error in - * the original quasar.config file and this allows you to - * investigate the Node.js stack error. - * - * After you fix the original file, this file will be - * deleted automatically. - **/ - - -// quasar.config.js -import { defineConfig } from "@quasar/app-webpack/wrappers"; -var quasar_config_default = defineConfig(() => { - const apiBaseUrl = (process.env.VITE_API_BASE_URL || "/api").trim(); - return { - /* ===================================================== - APP INFO - ===================================================== */ - productName: "Baggi BSS", - productDescription: "Baggi Tekstil Business Support System", - /* ===================================================== - BOOT FILES - ===================================================== */ - boot: ["dayjs"], - /* ===================================================== - GLOBAL CSS - ===================================================== */ - css: ["app.css"], - /* ===================================================== - ICONS / FONTS - ===================================================== */ - extras: [ - "roboto-font", - "material-icons" - ], - /* ===================================================== - BUILD (PRODUCTION) - ===================================================== */ - build: { - vueRouterMode: "hash", - env: { - VITE_API_BASE_URL: apiBaseUrl - }, - esbuildTarget: { - browser: ["es2022", "firefox115", "chrome115", "safari14"], - node: "node20" - }, - // Cache & performance - gzip: true, - preloadChunks: true - }, - /* ===================================================== - DEV SERVER (LOCAL) - ===================================================== */ - devServer: { - server: { type: "http" }, - port: 9e3, - open: true, - // DEV proxy (CORS'suz) - proxy: [ - { - context: ["/api"], - target: "http://localhost:8080", - changeOrigin: true, - secure: false - } - ] - }, - /* ===================================================== - QUASAR FRAMEWORK - ===================================================== */ - framework: { - config: { - notify: { - position: "top", - timeout: 2500 - } - }, - lang: "tr", - plugins: [ - "Loading", - "Dialog", - "Notify" - ] - }, - animations: [], - /* ===================================================== - SSR / PWA (DISABLED) - ===================================================== */ - ssr: { - prodPort: 3e3, - middlewares: ["render"], - pwa: false - }, - pwa: { - workboxMode: "GenerateSW" - }, - /* ===================================================== - MOBILE / DESKTOP - ===================================================== */ - capacitor: { - hideSplashscreen: true - }, - electron: { - preloadScripts: ["electron-preload"], - inspectPort: 5858, - bundler: "packager", - builder: { - appId: "baggisowtfaresystem" - } - }, - bex: { - extraScripts: [] - } - }; -}); -export { - quasar_config_default as default -};