scripts: make-manifest.py drops launcher exe from files list #6

Open
opened 2026-04-15 11:46:56 +02:00 by jann · 0 comments
Member

make-manifest.py currently stores the launcher file only under the top-level launcher field of the manifest and excludes it from the files array.

The launcher-side orchestrator (jann/metin-launcher UpdateOrchestrator) only iterates manifest.files when downloading blobs — it never consults the launcher field for a download action. Result: the launcher exe (e.g. Metin2.exe) is never fetched, the install dir is left without the client binary, and GameProcess.Launch logs game executable not found.

Hit this during today's m2pack-full release: had to post-process every signed manifest by reinjecting the launcher entry into files before publish.

Reproduction

  1. python3 scripts/make-manifest.py --source /path/to/client --launcher Metin2.exe --out manifest.json
  2. jq '.files | map(select(.path == "Metin2.exe")) | length' manifest.json0
  3. Orchestrator downloads everything except Metin2.exe.

Fix options

  • Append the launcher FileEntry to files in walk_client before returning (and keep the launcher field for spawn-time metadata).
  • Or have the launcher-side orchestrator additionally download manifest.launcher on a hash mismatch.

The first option is simpler and keeps the orchestrator contract ("files lists every blob") honest. Opening as a blocker for the next clean-pipeline release.

Workaround currently in use: the release wrapper patches the JSON with a second python pass that sorts the launcher entry into files and re-signs with sign-manifest.py.

`make-manifest.py` currently stores the launcher file only under the top-level `launcher` field of the manifest and excludes it from the `files` array. The launcher-side orchestrator (jann/metin-launcher `UpdateOrchestrator`) only iterates `manifest.files` when downloading blobs — it never consults the `launcher` field for a download action. Result: the launcher exe (e.g. `Metin2.exe`) is never fetched, the install dir is left without the client binary, and `GameProcess.Launch` logs `game executable not found`. Hit this during today's m2pack-full release: had to post-process every signed manifest by reinjecting the launcher entry into files before publish. ## Reproduction 1. `python3 scripts/make-manifest.py --source /path/to/client --launcher Metin2.exe --out manifest.json` 2. `jq '.files | map(select(.path == "Metin2.exe")) | length' manifest.json` → `0` 3. Orchestrator downloads everything except Metin2.exe. ## Fix options - Append the launcher FileEntry to `files` in `walk_client` before returning (and keep the `launcher` field for spawn-time metadata). - Or have the launcher-side orchestrator additionally download `manifest.launcher` on a hash mismatch. The first option is simpler and keeps the orchestrator contract ("files lists every blob") honest. Opening as a blocker for the next clean-pipeline release. Workaround currently in use: the release wrapper patches the JSON with a second python pass that sorts the launcher entry into files and re-signs with `sign-manifest.py`.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: metin-server/m2dev-client#6