Build & release
Releases are tag-driven and built by GitHub Actions. Local builds live in Build from source; this page is how a shipped release actually happens.
Continuous integration
Section titled “Continuous integration”Every push and PR to main runs the CI workflow on macos-15 / Xcode 16.4:
- Validate property lists (
plutil -lint). - Check installer script syntax (
zsh -n). - SwiftLint.
swift build.swift test --filter PDFSmokeTests(fast PDF load/export sanity).swift test(full suite).xcodebuild buildthenxcodebuild test(Xcode-side,CODE_SIGNING_ALLOWED=NO).
Two more workflows guard quality: CodeQL (scheduled Swift analysis) and Dependency Review (fails a PR on moderate-or-higher advisories in dependency changes).
Cutting a release
Section titled “Cutting a release”The Release workflow triggers on a v* or release-v* tag (or manual dispatch):
- Build a universal Apple Silicon + Intel app via
./scripts/install-mac.sh --clean --no-open --package-only --package Orifold.zip. - Package and mount-test the versioned DMG, then verify the exact shipped app’s resource bundle and code signature.
- Generate SHA-256 sidecars and
manifest.json, while keeping stable-nameOrifold.dmgandOrifold.zipassets. - Publish every asset to the tagged GitHub Release, mark it latest, and dispatch a documentation rebuild.
The website serves the universal DMG. The one-line installer and Homebrew cask use Orifold.zip from the same latest release; the in-app updater verifies the published checksum before installation.
Signing & notarization, honestly. Release builds are ad-hoc signed and not notarized by default, so macOS shows an “unidentified developer” prompt on first open — the installer and cask clear the download quarantine to smooth this. If the Developer ID secrets are configured, the same workflow imports the certificate and produces a properly signed (and optionally notarized) build instead.
The Developer ID secrets the workflow looks for
When these repository secrets are present, the release job imports the certificate into a temporary keychain and signs with it:
ORIFOLD_DEVELOPER_ID_CERTIFICATE_BASE64, ORIFOLD_DEVELOPER_ID_CERTIFICATE_PASSWORD, ORIFOLD_SIGNING_IDENTITY, ORIFOLD_APPLE_ID, ORIFOLD_APPLE_TEAM_ID, ORIFOLD_APPLE_APP_SPECIFIC_PASSWORD.
The identical path works locally — set the same variables and run the --package-only and make-dmg.sh commands to produce signed/notarized artifacts on your own machine.
The full release gate
Section titled “The full release gate”Before shipping, the same command list in Testing & the release gate must pass, plus the installed-app workflow audit and a final smoke check of the published artifact.
Where the logs are
Section titled “Where the logs are”.build/install.log— build output from a source build.~/.orifold/prebuilt-install.log— the prebuilt install attempt.- CI: the uploaded
Orifold-xcresultsbundle on the workflow run.