Skip to content

Commit 4d0f82b

Browse files
committed
Improved versioning across all builds
1 parent 30b1775 commit 4d0f82b

File tree

6 files changed

+118
-42
lines changed

6 files changed

+118
-42
lines changed
Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,82 @@
11
import sys
22
import re
3+
import argparse
34

4-
def update_version_info(version_str, file_path='file_version_info.txt'):
5+
def update_version_info(version_str, build_number=None, file_path='file_version_info.txt'):
56
"""
67
Updates the file_version_info.txt with the given version.
7-
Handles versions with suffixes like '2025.12.0-beta' or '2025.12.0-dev'.
8+
Handles versions with suffixes like '2025.12.0-beta' or '2026.1.5.dev0+hash'.
89
"""
9-
# Strip suffix for numeric tuple (e.g., "2025.12.0-beta" -> "2025.12.0")
10-
base_version = re.sub(r'-.*$', '', version_str)
10+
print(f"Processing version: {version_str} (Build Number: {build_number})")
1111

12+
# 1. Extract the BASE numeric part (Major.Minor.Patch)
13+
# We want only the MAJOR.MINOR.PATCH part for the fixed file info tuples.
14+
match = re.search(r'([0-9]+\.[0-9]+\.[0-9]+)', version_str)
15+
if not match:
16+
print(f"Error: Could not find a valid numeric version in '{version_str}'")
17+
sys.exit(1)
18+
19+
base_version = match.group(1)
1220
parts = base_version.split('.')
13-
while len(parts) < 4:
21+
22+
# Ensure we have at least 3 parts
23+
while len(parts) < 3:
1424
parts.append('0')
1525

16-
# Ensure all parts are numeric
17-
numeric_parts = []
18-
for p in parts[:4]:
19-
try:
20-
numeric_parts.append(str(int(p)))
21-
except ValueError:
22-
numeric_parts.append('0')
26+
# 2. Add/Override the 4th component (Build/Revision)
27+
if build_number is not None:
28+
parts.append(str(build_number))
29+
else:
30+
# Default to 0 if not provided
31+
parts.append('0')
32+
33+
# Limit to 4 components for Windows VersionInfo
34+
numeric_parts = parts[:4]
35+
36+
# 3. Generate the formats needed for file_version_info.txt
2337

2438
# tuple format: (2025, 12, 0, 0)
2539
tuple_str = f"({', '.join(numeric_parts)})"
26-
# string format: '2025.12.0.0' for file version (numeric only)
40+
41+
# string format: '2025.12.0.0' for FileVersion (must be numeric only)
2742
full_version_str = '.'.join(numeric_parts)
28-
# Display version includes suffix for ProductVersion string
29-
display_version_str = version_str if '-' in version_str else full_version_str
3043

31-
with open(file_path, 'r', encoding='utf-8') as f:
32-
content = f.read()
44+
# display_version_str is for ProductVersion (can include suffixes)
45+
display_version_str = version_str
46+
47+
# 4. Read and Update the File
48+
try:
49+
with open(file_path, 'r', encoding='utf-8') as f:
50+
content = f.read()
51+
except FileNotFoundError:
52+
print(f"Error: {file_path} not found.")
53+
sys.exit(1)
3354

3455
# Update filevers and prodvers tuples (must be numeric)
35-
content = re.sub(r'filevers=\(\d+, \d+, \d+, \d+\)', f'filevers={tuple_str}', content)
36-
content = re.sub(r'prodvers=\(\d+, \d+, \d+, \d+\)', f'prodvers={tuple_str}', content)
56+
# Use smart regex to match variation in whitespace
57+
content = re.sub(r'filevers\s*=\s*\([^)]+\)', f'filevers={tuple_str}', content)
58+
content = re.sub(r'prodvers\s*=\s*\([^)]+\)', f'prodvers={tuple_str}', content)
3759

38-
# Update StringStructs
39-
# Update StringStructs
40-
# FileVersion should be numeric only
60+
# Update StringStructs (FileVersion and ProductVersion)
61+
# FileVersion should be numeric only for Windows stability
4162
content = re.sub(r"StringStruct\(u?'FileVersion', u?'[^']+'\)", f"StringStruct(u'FileVersion', u'{full_version_str}')", content)
4263
# ProductVersion can include suffix for display
4364
content = re.sub(r"StringStruct\(u?'ProductVersion', u?'[^']+'\)", f"StringStruct(u'ProductVersion', u'{display_version_str}')", content)
4465

4566
with open(file_path, 'w', encoding='utf-8') as f:
4667
f.write(content)
4768

48-
print(f"Updated {file_path} to version {display_version_str} (numeric: {full_version_str})")
69+
print(f"Successfully updated {file_path}:")
70+
print(f" - FileVersion (Numeric): {full_version_str}")
71+
print(f" - ProductVersion (Display): {display_version_str}")
72+
print(f" - Tuple (FFI): {tuple_str}")
4973

5074
if __name__ == "__main__":
51-
if len(sys.argv) < 2:
52-
print("Usage: python update_version_info.py <version>")
53-
sys.exit(1)
75+
parser = argparse.ArgumentParser(description="Update version information in file_version_info.txt")
76+
parser.add_argument("version", help="Full version string (e.g., 2026.1.5.dev0+hash)")
77+
parser.add_argument("--build", type=int, help="Optional build number (4th component override)", default=None)
78+
parser.add_argument("--file", help="Path to version info file", default="file_version_info.txt")
79+
80+
args = parser.parse_args()
5481

55-
update_version_info(sys.argv[1])
82+
update_version_info(args.version, build_number=args.build, file_path=args.file)

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ jobs:
7272
sed -i "s/__version__ = \".*\"/__version__ = \"$VERSION\"/" src/switchcraft/__init__.py
7373
7474
# Update file_version_info.txt
75-
python .github/scripts/update_version_info.py "$VERSION"
75+
python .github/scripts/update_version_info.py "$VERSION" --build ${{ github.run_number }}
7676
7777
# Update Addon Manifests
7878
sed -i "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" src/switchcraft_advanced/manifest.json
@@ -203,7 +203,7 @@ jobs:
203203
# Update version files
204204
sed -i "s/version = \".*\"/version = \"$DEV_VERSION\"/" pyproject.toml
205205
sed -i "s/__version__ = \".*\"/__version__ = \"$DEV_VERSION\"/" src/switchcraft/__init__.py
206-
python .github/scripts/update_version_info.py "$DEV_VERSION"
206+
python .github/scripts/update_version_info.py "$DEV_VERSION" --build ${{ github.run_number }}
207207
208208
# Update .iss files (Inno Setup installer scripts)
209209
# Extract numeric version only (remove .dev0, +build, etc.) for VersionInfoVersion

file_version_info.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ VSVersionInfo(
66
ffi=FixedFileInfo(
77
# filevers and prodvers should be always a tuple with four items: (1, 2, 3, 4)
88
# Set not needed items to zero 0.
9-
filevers=(2026, 1, 0, 0),
10-
prodvers=(2026, 1, 0, 0),
9+
filevers=(2026, 1, 5, 0),
10+
prodvers=(2026, 1, 5, 0),
1111
# Contains a bitmask that specifies the valid bits 'flags'r
1212
mask=0x3f,
1313
# Contains a bitmask that specifies the Boolean attributes of the file.
@@ -31,12 +31,12 @@ VSVersionInfo(
3131
'040904B0',
3232
[StringStruct('CompanyName', 'FaserF'),
3333
StringStruct('FileDescription', 'SwitchCraft - Advanced Silent Switch & Packaging Tool'),
34-
StringStruct(u'FileVersion', u'2026.1.0.0'),
34+
StringStruct(u'FileVersion', u'2026.1.5.0'),
3535
StringStruct('InternalName', 'SwitchCraft'),
3636
StringStruct('LegalCopyright', 'Copyright (c) 2026 FaserF'),
3737
StringStruct('OriginalFilename', 'SwitchCraft.exe'),
3838
StringStruct('ProductName', 'SwitchCraft'),
39-
StringStruct(u'ProductVersion', u'2026.1.0.0')])
39+
StringStruct(u'ProductVersion', u'2026.1.5b3.dev0+30b1775')])
4040
]),
4141
VarFileInfo([VarStruct('Translation', [1033, 1200])])
4242
]

scripts/build_release.ps1

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,22 @@ if (-not $IsCI -and (Test-Path (Join-Path $RepoRoot ".git"))) {
254254
}
255255

256256

257+
# --- Update Version Info File (for PyInstaller) ---
258+
Write-Host "`nUpdating file_version_info.txt with localized version..." -ForegroundColor Gray
259+
try {
260+
$UpdateScript = Join-Path $RepoRoot ".github/scripts/update_version_info.py"
261+
if (Test-Path $UpdateScript) {
262+
if ($IsWinBuild) {
263+
python $UpdateScript "$AppVersion" --build $BuildNumber
264+
}
265+
else {
266+
python3 $UpdateScript "$AppVersion" --build $BuildNumber
267+
}
268+
}
269+
} catch {
270+
Write-Warning "Failed to update file_version_info.txt: $_"
271+
}
272+
257273
# Setup Dist dir
258274
$DistDir = Join-Path $RepoRoot "dist"
259275
if (-not (Test-Path $DistDir)) {

src/switchcraft/main.py

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,32 @@ def _ensure_pwa_manifest():
833833
except Exception:
834834
pass
835835

836-
if hasattr(ft, "run"):
837-
ft.run(main)
838-
else:
839-
ft.app(target=main, assets_dir="assets")
836+
try:
837+
if hasattr(ft, "run"):
838+
ft.run(main)
839+
else:
840+
ft.app(target=main, assets_dir="assets")
841+
except Exception as e:
842+
# Fallback for early failures (before main() handles it)
843+
try:
844+
import pyi_splash
845+
if pyi_splash.is_alive():
846+
pyi_splash.close()
847+
except:
848+
pass
849+
850+
if splash_proc:
851+
try:
852+
splash_proc.terminate()
853+
except:
854+
pass
855+
856+
# Write crash dump for early failure
857+
try:
858+
write_crash_dump(sys.exc_info())
859+
except:
860+
pass
861+
862+
# If it's a windowed app with no console, we should try to show a message box
863+
# but for now, just reraise if we have a console or exit
864+
raise e

switchcraft.spec

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,19 +71,27 @@ datas = [
7171
('src/switchcraft/assets', 'assets'),
7272
]
7373

74-
# Collect Flet data files (icons.json, etc.)
75-
from PyInstaller.utils.hooks import collect_data_files
74+
# Collect Flet data files and binaries
75+
from PyInstaller.utils.hooks import collect_all
7676
try:
77-
flet_datas = collect_data_files('flet', include_py_files=False)
77+
flet_datas, flet_binaries, flet_hiddenimports = collect_all('flet')
7878
datas += flet_datas
79+
binaries = flet_binaries
80+
hidden_imports += flet_hiddenimports
81+
82+
fd_datas, fd_binaries, fd_hiddenimports = collect_all('flet_desktop')
83+
datas += fd_datas
84+
binaries += fd_binaries
85+
hidden_imports += fd_hiddenimports
7986
except Exception as e:
80-
print(f"WARNING: Failed to collect Flet data files: {e}")
87+
print(f"WARNING: Failed to collect Flet bundle files: {e}")
88+
binaries = []
8189

8290
# Analysis for Modern (Flet)
8391
a = Analysis(
8492
['src/switchcraft/main.py'],
8593
pathex=[os.path.abspath('src')],
86-
binaries=[],
94+
binaries=binaries,
8795
datas=datas,
8896
hiddenimports=hidden_imports,
8997
hookspath=[],

0 commit comments

Comments
 (0)