#!/usr/bin/env python3 """Read Workbench's bundled version; record it after a confirmed Workshop upload.""" import argparse import json from pathlib import Path import re import sys ROOT = Path(__file__).resolve().parents[1] VERSION_LINE = 'Latest published Workshop version:' DEFAULT_MANIFEST = (Path.home() / '.local/share/Steam/steamapps/compatdata/1874910/pfx' / 'drive_c/users/steamuser/AppData/Local/Temp/Arma Reforger Workbench' / 'Publishing/2528466DE220D91C/manifest.json') def valid_version(value): return (isinstance(value, str) and re.fullmatch(r'\d+\.\d+\.\d+', value) is not None and all(int(part) <= 32000 for part in value.split('.'))) def bundled_version(manifest, project): guid = re.search(r'\bGUID\s+"([A-Fa-f0-9]{16})"', project) asset = manifest.get('asset', {}) if isinstance(manifest, dict) else {} if (not guid or not isinstance(asset, dict) or not isinstance(asset.get('id'), str) or asset['id'].upper() != guid[1].upper()): raise ValueError('Publishing manifest does not belong to this addon.') version = asset.get('version') # Top-level "version" is the manifest schema, not the mod version. if not valid_version(version): raise ValueError('Publishing manifest has no valid addon version.') return version def update_changelog(text, version): if not valid_version(version): raise ValueError('Invalid Workshop version.') if not text.startswith('# Changelog\n'): raise ValueError('Expected # Changelog at the start of CHANGELOG.md.') line = VERSION_LINE + ' **' + version + '**' existing = list(re.finditer(r'^Latest published Workshop version:.*$', text, re.MULTILINE)) if len(existing) > 1: raise ValueError('Changelog contains multiple Workshop version records.') if existing: match = existing[0] if match.start() > text.find('\n## ') >= 0: raise ValueError('Workshop version record must be above the changelog entries.') return text[:match.start()] + line + text[match.end():] return text.replace('# Changelog\n', '# Changelog\n\n' + line + '\n', 1) def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('--manifest', type=Path, default=DEFAULT_MANIFEST) parser.add_argument('--published', action='store_true', help='Confirm the bundle was successfully uploaded; update CHANGELOG.md') args = parser.parse_args() try: manifest = json.loads(args.manifest.read_text(encoding='utf-8-sig')) version = bundled_version(manifest, (ROOT / 'addons/core/addon.gproj').read_text()) if args.published: path = ROOT / 'CHANGELOG.md' before = path.read_text() after = update_changelog(before, version) if before != after: path.write_text(after) print('Recorded published Workshop version ' + version + ' in CHANGELOG.md.') else: print('Workbench bundle version: ' + version) print('Bundling alone does not confirm publication. Use --published after a successful upload.') except (OSError, ValueError, AttributeError) as error: print('Cannot read/record Workshop version: ' + str(error), file=sys.stderr) return 1 return 0 if __name__ == '__main__': sys.exit(main())