The universal binary CI job was failing at Lipo Universal 2 .app because:
actions/upload-artifact@v3 was uploading the raw uncompressed TargetPrint.app bundle folder.
In Gitea Actions / act runner, upload-artifact and download-artifact strip UNIX execute permission bits (chmod -x, resulting in 0644).
In build-universal, the lipo step tested [ -x "${base}/Contents/MacOS/TargetPrint" ] to decide whether to wrap root Contents into TargetPrint.app. Because -x evaluated to false, the move was skipped and the subsequent test -x immediately exited with code 1.
Even if the move had occurred, the missing execute bit on the binary caused test -x to fail silently.
Fix
Bundle Preservation with ditto:
In build-arch, package TargetPrint.app with ditto -c -k --keepParent into TargetPrint.app.zip before uploading.
Robust Multi-Strategy Extraction in build-universal:
Checks for *.zip and cleanly extracts using ditto -x -k.
Handles fallback to reconstructing TargetPrint.app from root Contents/ if raw contents are ever downloaded (without requiring -x on the check).
Handles any subfolder nesting (e.g. app-x86_64/TargetPrint.app).
Explicitly ensures chmod +x on TargetPrint.app/Contents/MacOS/TargetPrint.
Adds diagnostic logging (ls -l and lipo -info) so CI logs are fully transparent.
Release Asset Upload Condition:
Changed release asset upload check to success() rather than !cancelled().
### Root Cause
The universal binary CI job was failing at `Lipo Universal 2 .app` because:
1. `actions/upload-artifact@v3` was uploading the raw uncompressed `TargetPrint.app` bundle folder.
2. In Gitea Actions / act runner, `upload-artifact` and `download-artifact` strip UNIX execute permission bits (`chmod -x`, resulting in `0644`).
3. In `build-universal`, the lipo step tested `[ -x "${base}/Contents/MacOS/TargetPrint" ]` to decide whether to wrap root `Contents` into `TargetPrint.app`. Because `-x` evaluated to false, the move was skipped and the subsequent `test -x` immediately exited with code 1.
4. Even if the move had occurred, the missing execute bit on the binary caused `test -x` to fail silently.
### Fix
1. **Bundle Preservation with `ditto`**:
- In `build-arch`, package `TargetPrint.app` with `ditto -c -k --keepParent` into `TargetPrint.app.zip` before uploading.
- `ditto` preserves macOS bundle directory structure, file permissions (`+x`), extended attributes, and codesign resources.
2. **Robust Multi-Strategy Extraction in `build-universal`**:
- Checks for `*.zip` and cleanly extracts using `ditto -x -k`.
- Handles fallback to reconstructing `TargetPrint.app` from root `Contents/` if raw contents are ever downloaded (without requiring `-x` on the check).
- Handles any subfolder nesting (e.g. `app-x86_64/TargetPrint.app`).
- Explicitly ensures `chmod +x` on `TargetPrint.app/Contents/MacOS/TargetPrint`.
- Adds diagnostic logging (`ls -l` and `lipo -info`) so CI logs are fully transparent.
3. **Release Asset Upload Condition**:
- Changed release asset upload check to `success()` rather than `!cancelled()`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Root Cause
The universal binary CI job was failing at
Lipo Universal 2 .appbecause:actions/upload-artifact@v3was uploading the raw uncompressedTargetPrint.appbundle folder.upload-artifactanddownload-artifactstrip UNIX execute permission bits (chmod -x, resulting in0644).build-universal, the lipo step tested[ -x "${base}/Contents/MacOS/TargetPrint" ]to decide whether to wrap rootContentsintoTargetPrint.app. Because-xevaluated to false, the move was skipped and the subsequenttest -ximmediately exited with code 1.test -xto fail silently.Fix
ditto:build-arch, packageTargetPrint.appwithditto -c -k --keepParentintoTargetPrint.app.zipbefore uploading.dittopreserves macOS bundle directory structure, file permissions (+x), extended attributes, and codesign resources.build-universal:*.zipand cleanly extracts usingditto -x -k.TargetPrint.appfrom rootContents/if raw contents are ever downloaded (without requiring-xon the check).app-x86_64/TargetPrint.app).chmod +xonTargetPrint.app/Contents/MacOS/TargetPrint.ls -landlipo -info) so CI logs are fully transparent.success()rather than!cancelled().