feat(packaging): dynamically resolve installer version info from build context
CI Test Suite / Run Component Tests & Pipeline Verification (push) Successful in 1m31s
Release Binaries & Packages / Build & Release Standalone Binaries (Linux & Windows Cross-Compilation) (push) Successful in 3m50s

This commit is contained in:
2026-09-30 18:18:53 +02:00
parent 959f2977f0
commit 41d7d66a56
6 changed files with 177 additions and 16 deletions
+11 -3
View File
@@ -1,7 +1,15 @@
#ifFileExists("version.iss")
#include "version.iss"
#endif
#ifndef AppVersion
#define AppVersion "0.3.5.1"
#endif
[Setup]
AppId={{9C4A6F1D-8975-476E-8512-4217DE029A88}}
AppName=LOGAR Client
AppVersion=0.3.5.1
AppVersion={#AppVersion}
AppPublisher=LOGAR
AppPublisherURL=https://logar.eibl.tech
AppSupportURL=https://logar.eibl.tech
@@ -19,9 +27,9 @@ WizardImageFile=assets\wizard_sidebar.bmp
WizardSmallImageFile=assets\wizard_small.bmp
VersionInfoCompany=LOGAR
VersionInfoDescription=LOGAR Windows Edge Log Forwarder Setup
VersionInfoVersion=0.3.5.1
VersionInfoVersion={#AppVersion}
VersionInfoProductName=LOGAR Client
VersionInfoProductVersion=0.3.5.1
VersionInfoProductVersion={#AppVersion}
[Files]
Source: "..\dist\Win_Client.exe"; DestDir: "{app}"; Flags: ignoreversion
+14 -3
View File
@@ -9,13 +9,24 @@ RequestExecutionLevel admin
BrandingText "LOGAR Centralized Log Aggregator && Forwarder"
VIProductVersion "0.3.5.1"
!ifFileExists "version.nsh"
!include "version.nsh"
!endif
!ifndef APP_VERSION
!define APP_VERSION "0.0.0.0"
!endif
!ifndef DISPLAY_VERSION
!define DISPLAY_VERSION "${APP_VERSION}"
!endif
VIProductVersion "${APP_VERSION}"
VIAddVersionKey "ProductName" "LOGAR Client"
VIAddVersionKey "CompanyName" "LOGAR"
VIAddVersionKey "LegalCopyright" "© 2026 LOGAR"
VIAddVersionKey "FileDescription" "LOGAR Windows Edge Log Forwarder Setup"
VIAddVersionKey "FileVersion" "0.3.5.1"
VIAddVersionKey "ProductVersion" "0.3.5.1"
VIAddVersionKey "FileVersion" "${APP_VERSION}"
VIAddVersionKey "ProductVersion" "${DISPLAY_VERSION}"
# --- Visual Graphics & Branding ---
!define MUI_ICON "assets/logo.ico"
+11 -3
View File
@@ -1,7 +1,15 @@
#ifFileExists("version.iss")
#include "version.iss"
#endif
#ifndef AppVersion
#define AppVersion "0.3.5.1"
#endif
[Setup]
AppId={{4F3D675E-1E4E-43B6-8C84-B47DE290BE4A}}
AppName=LOGAR Server
AppVersion=0.3.5.1
AppVersion={#AppVersion}
AppPublisher=LOGAR
AppPublisherURL=https://logar.eibl.tech
AppSupportURL=https://logar.eibl.tech
@@ -19,9 +27,9 @@ WizardImageFile=assets\wizard_sidebar.bmp
WizardSmallImageFile=assets\wizard_small.bmp
VersionInfoCompany=LOGAR
VersionInfoDescription=LOGAR Cloud Hub & TCP Ingestion Server Setup
VersionInfoVersion=0.3.5.1
VersionInfoVersion={#AppVersion}
VersionInfoProductName=LOGAR Server
VersionInfoProductVersion=0.3.5.1
VersionInfoProductVersion={#AppVersion}
[Files]
Source: "..\dist\Server.exe"; DestDir: "{app}"; Flags: ignoreversion
+14 -3
View File
@@ -8,13 +8,24 @@ RequestExecutionLevel admin
BrandingText "LOGAR Centralized Log Aggregator && Ingestion Hub"
VIProductVersion "0.3.5.1"
!ifFileExists "version.nsh"
!include "version.nsh"
!endif
!ifndef APP_VERSION
!define APP_VERSION "0.0.0.0"
!endif
!ifndef DISPLAY_VERSION
!define DISPLAY_VERSION "${APP_VERSION}"
!endif
VIProductVersion "${APP_VERSION}"
VIAddVersionKey "ProductName" "LOGAR Server"
VIAddVersionKey "CompanyName" "LOGAR"
VIAddVersionKey "LegalCopyright" "© 2026 LOGAR"
VIAddVersionKey "FileDescription" "LOGAR Cloud Hub & TCP Ingestion Server Setup"
VIAddVersionKey "FileVersion" "0.3.5.1"
VIAddVersionKey "ProductVersion" "0.3.5.1"
VIAddVersionKey "FileVersion" "${APP_VERSION}"
VIAddVersionKey "ProductVersion" "${DISPLAY_VERSION}"
# --- Visual Graphics & Branding ---
!define MUI_ICON "assets/logo.ico"
+123 -4
View File
@@ -290,6 +290,115 @@ def ensure_libpython():
pass
import re
def get_context_version():
"""
Extracts the current release version from the build context:
1. Environment variables (APP_VERSION, LOGAR_VERSION, GITEA_REF_NAME, GITHUB_REF_NAME, GITHUB_REF)
2. Git tag via `git describe --tags --exact-match` or `git describe --tags`
3. RELEASE_NOTES.md top header
4. README.md version badge
Returns tuple: (display_version, four_part_version)
e.g. ('0.3.5.1', '0.3.5.1') or ('0.3.5', '0.3.5.0')
"""
raw_version = ""
# 1. Environment variables
for env_var in ["APP_VERSION", "LOGAR_VERSION", "GITEA_REF_NAME", "GITHUB_REF_NAME", "GITHUB_REF"]:
val = os.environ.get(env_var, "").strip()
if val:
if val.startswith("refs/tags/"):
val = val[len("refs/tags/"):]
if val.startswith("v") and len(val) > 1 and val[1].isdigit():
val = val[1:]
if any(c.isdigit() for c in val):
raw_version = val
break
# 2. Git command
if not raw_version:
try:
res = subprocess.run(["git", "describe", "--tags", "--exact-match"], cwd=ROOT_DIR, capture_output=True, text=True, check=False)
if res.returncode == 0 and res.stdout.strip():
tag = res.stdout.strip()
if tag.startswith("v") and len(tag) > 1 and tag[1].isdigit():
tag = tag[1:]
raw_version = tag
except Exception:
pass
if not raw_version:
try:
res = subprocess.run(["git", "describe", "--tags"], cwd=ROOT_DIR, capture_output=True, text=True, check=False)
if res.returncode == 0 and res.stdout.strip():
tag = res.stdout.strip().split("-")[0]
if tag.startswith("v") and len(tag) > 1 and tag[1].isdigit():
tag = tag[1:]
raw_version = tag
except Exception:
pass
# 3. RELEASE_NOTES.md
if not raw_version:
rel_notes = os.path.join(ROOT_DIR, "RELEASE_NOTES.md")
if os.path.exists(rel_notes):
try:
with open(rel_notes, "r", encoding="utf-8") as f:
content = f.read()
m = re.search(r"##\s*\[v?([0-9.]+)\]", content)
if m:
raw_version = m.group(1).strip()
except Exception:
pass
# 4. README.md
if not raw_version:
readme = os.path.join(ROOT_DIR, "README.md")
if os.path.exists(readme):
try:
with open(readme, "r", encoding="utf-8") as f:
content = f.read()
m = re.search(r"version-v?([0-9.]+)-blue", content)
if m:
raw_version = m.group(1).strip()
except Exception:
pass
# Fallback
if not raw_version:
raw_version = "0.3.5.1"
# Clean display version (strip non-standard characters, keep digits and dots)
m_clean = re.search(r"([0-9]+(?:\.[0-9]+)*)", raw_version)
display_version = m_clean.group(1) if m_clean else raw_version
# Format 4-part numeric version for NSIS VIProductVersion (X.X.X.X)
parts = display_version.split(".")
while len(parts) < 4:
parts.append("0")
four_part_version = ".".join(parts[:4])
return display_version, four_part_version
def write_version_headers(display_version, four_part_version):
"""Writes dynamic version header files for NSIS and Inno Setup compilers."""
compilation_dir = os.path.join(ROOT_DIR, "compilation")
os.makedirs(compilation_dir, exist_ok=True)
nsh_file = os.path.join(compilation_dir, "version.nsh")
with open(nsh_file, "w", encoding="utf-8") as f:
f.write(f'; Auto-generated version header from build context\n!define APP_VERSION "{four_part_version}"\n!define DISPLAY_VERSION "{display_version}"\n')
iss_file = os.path.join(compilation_dir, "version.iss")
with open(iss_file, "w", encoding="utf-8") as f:
f.write(f'; Auto-generated version header from build context\n#define AppVersion "{display_version}"\n')
print(f"[+] Dynamic context version resolved: {display_version} (NSIS VIProductVersion: {four_part_version})")
def compile_nsis_installers():
"""Compiles NSIS installers if makensis is available (native Linux/Windows)."""
makensis_bin = ensure_makensis()
@@ -297,13 +406,20 @@ def compile_nsis_installers():
print("[!] Note: NSIS compiler (makensis) not found in PATH or standard directories.")
return False
makensis_cmd = [makensis_bin]
display_ver, vi_ver = get_context_version()
write_version_headers(display_ver, vi_ver)
compilation_dir = os.path.join(ROOT_DIR, "compilation")
makensis_cmd = [
makensis_bin,
f"-DAPP_VERSION={vi_ver}",
f"-DDISPLAY_VERSION={display_ver}"
]
success = True
for nsi in ["installer_client.nsi", "installer_server.nsi"]:
nsi_path = os.path.join(compilation_dir, nsi)
if os.path.exists(nsi_path):
print(f"[*] Compiling NSIS script: {nsi} via {makensis_cmd[0]}...")
print(f"[*] Compiling NSIS script: {nsi} (v{display_ver}) via {makensis_cmd[0]}...")
try:
subprocess.run(makensis_cmd + [nsi_path], cwd=compilation_dir, check=True)
print(f"[+] Successfully compiled NSIS installer for {nsi}")
@@ -338,12 +454,15 @@ def compile_inno_setup_installers():
print("[!] Note: Inno Setup compiler (iscc / innosetup) not available on host. Skipping installer .exe creation.")
return False
display_ver, vi_ver = get_context_version()
write_version_headers(display_ver, vi_ver)
for iss in ["installer_client.iss", "installer_server.iss"]:
iss_path = os.path.join(ROOT_DIR, "compilation", iss)
if os.path.exists(iss_path):
print(f"[*] Compiling Inno Setup script: {iss}...")
print(f"[*] Compiling Inno Setup script: {iss} (v{display_ver})...")
try:
subprocess.run(iscc_cmd + [iss_path], check=True)
subprocess.run(iscc_cmd + [f"/DAppVersion={display_ver}", iss_path], check=True)
print(f"[+] Successfully compiled {iss}")
except Exception as e:
print(f"[!] Warning: Failed to compile {iss} with {iscc_cmd}: {e}")