Repository navigation
Building and Releasing
build.sh is the whole build system. It compiles the Swift package, assembles
the app bundle, writes the LaunchDaemon plists and install scripts, and produces
a pkg, a zip and a dmg. The Makefile is a thin set of shortcuts over it.
- macOS with Xcode. CI builds on macOS 26 with Xcode 26; the packaging step
compiles the Icon Composer bundle
Resources/ReportMate.iconwithactooland fails the build if noAssets.carcomes out, so an older SDK that cannot compile it will not produce a pkg. - Swift 6 toolchain (
swift-tools-version: 6.0). - Homebrew bash 5.
build.shstarts with#!/opt/homebrew/bin/bash; system bash 3.2 will not run it.
brew install bash
./build.sh
Common variants:
./build.sh --clean --version 2026.10.07.2024
./build.sh --skip-pkg --skip-zip --skip-dmg
| Flag | Effect |
|---|---|
--version <v> |
Version to stamp. Defaults to YYYY.MM.DD.HHMM
|
--debug / --release
|
Build configuration; release is the default |
--clean |
Remove build artifacts first |
--skip-build |
Skip the Swift compile |
--skip-pkg, --skip-zip, --skip-dmg
|
Skip that output |
--sign |
Code sign the binaries and app bundle with ReportMate.entitlements
|
--distribution |
Implies --sign; signs with ReportMate-Distribution.entitlements and productsigns the pkg |
--notarize |
Implies --distribution; submits the pkg to notarytool, waits, staples and validates |
--api-url <url> |
Bake a default ApiUrl into the postinstall, written only if the key is absent |
--install |
Install the built package locally |
--create-tag |
Create and push a v<version> git tag |
--create-release |
Create a v<version> GitHub release with every ReportMate-<version>.* artifact (needs gh) |
--verbose |
Verbose output |
--help |
Usage |
| Target | Runs |
|---|---|
make build |
Debug build, no packaging |
make release |
Release build, no packaging |
make test |
swift test |
make package |
Full build with packaging |
make sign |
Package and sign |
make notarize |
Package, sign and notarize (also the default target) |
make install |
Release build, then copy the bare CLI from .build/release to /usr/local/reportmate. No daemons or app bundle |
make clean |
swift package clean and remove build/ and .build/
|
make dev-setup |
Install osquery via Homebrew if missing |
make format / make lint
|
swift-format / SwiftLint, if installed |
Versions are YYYY.MM.DD.HHMM. build.sh generates Sources/Core/AppVersion.swift
with the version compiled in, and restores the "YYYY.MM.DD.HHMM" placeholder
on exit, so the file is generated, never hand-edited, and the working tree stays
clean.
It also writes Sources/Generated/ModuleVersions.swift, giving each module the
date of the last commit that touched its processor and model files (falling back
to the build time), and restores a placeholder on exit. That is why the build
needs full git history (fetch-depth: 0 in CI).
In the app bundle, CFBundleShortVersionString is the date part
(2026.10.07) and CFBundleVersion is every digit run together
(202610072024), so the build number always increases from one build to the
next. Installer compares CFBundleVersion, and an HHMM-only number would go
backwards on a later day at an earlier time.
Credentials come from a .env beside build.sh, which is not committed.
.env.example is a template for all of these except
NOTARIZATION_KEYCHAIN_PROFILE, which build.sh also reads:
| Variable | Purpose |
|---|---|
TEAM_ID |
Apple Developer Team ID |
SIGNING_IDENTITY_APP |
Identity for the binaries and app bundle |
SIGNING_IDENTITY_INSTALLER |
Identity for productsign
|
SIGNING_TIMESTAMP |
Add --timestamp; default true |
SIGNING_KEYCHAIN |
Non-default keychain path |
NOTARIZATION_KEYCHAIN_PROFILE |
Stored notarytool profile — preferred |
NOTARIZATION_APPLE_ID, NOTARIZATION_PASSWORD
|
Legacy Apple ID + app-specific password |
There are no defaults for any of these; the repo is public and ships no signing material.
Prefer the keychain profile. An app-specific password kept in a file is revoked
whenever the Apple ID's password changes, and notarytool reports that as a bare
HTTP 401 … not allowed for primary authentication with no hint that the
credential is simply dead.
xcrun notarytool store-credentials "notarization_credentials" --apple-id you@example.com --team-id XXXXXXXXXX --password xxxx-xxxx-xxxx-xxxx
The bundled macadmins extension is re-signed with --options runtime when
signing is on: the upstream binary ships without a hardened runtime, and
notarization rejects the package otherwise.
Everything lands in release/.
| Artifact | Notes |
|---|---|
ReportMate-<version>.pkg |
pkgbuild with identifier com.github.reportmate, the preinstall/postinstall scripts, and a component plist that blocks bundle relocation. This is the supported install path |
ReportMate-<version>.zip |
The bare CLI binary |
ReportMate-<version>.dmg |
The bare CLI plus an Install.sh that copies it to /usr/local/reportmate. It installs no daemons, app or helper |
The installer scripts are generated by build.sh itself. If a
packages/client/Scripts directory exists it is used instead; the repository
does not ship one.
.github/workflows/ci.yml runs on pushes and PRs to main that touch
Sources/, Tests/, Package.swift, build.sh or the workflow itself. On a
macos-26 runner with Xcode 26 it installs Homebrew bash, runs
./build.sh --skip-pkg --skip-zip --skip-dmg, compiles the app icon with
actool to catch an SDK that cannot build Assets.car, and runs swift test.
It does not package or sign.
.github/workflows/release.yml runs on v* tags, on YYYY.MM.DD.HHMM tags, and
on manual dispatch with an optional version. On macos-26 with Xcode 26 it
builds with --skip-zip --skip-dmg, checks the pkg name matches
ReportMate-YYYY.MM.DD.HHMM.pkg, writes a SHA-256 sidecar, and publishes both as
a GitHub release titled ReportMate <version> with generated notes. A manual run
creates the tag at the built commit. Releases are tagged as bare
YYYY.MM.DD.HHMM versions; the latest is 2026.10.07.2024.
The released pkg is unsigned and unnotarized. No Apple Developer ID material is held in this repository. Sign and notarize the artifact with your own identities before deploying it, exactly as the release notes describe:
codesign --force --options runtime --timestamp --sign "Developer ID Application: <Org> (<TeamID>)" "/Applications/Utilities/Managed Reports Runner.app"
productsign --timestamp --sign "Developer ID Installer: <Org> (<TeamID>)" ReportMate-<version>.pkg ReportMate-<version>-signed.pkg
xcrun notarytool submit ReportMate-<version>-signed.pkg --apple-id <apple-id> --team-id <TeamID> --password <app-specific-password> --wait
xcrun stapler staple ReportMate-<version>-signed.pkg
MIT licensed. — reportmate.app