Development
swift test # unit tests
./scripts/e2e.sh # end-to-end, with fake tools in a throwaway turnstile home
/usr/bin/python3 scripts/e2e-top-tests.py # daemon-free PTY driver checks
node --test scripts/history-report-tests.mjs # isolated report input and SQLite checks
The history-report helper accepts no arguments for a 30-day report or exactly
./scripts/history-report.sh --days <positive-integer>. Invalid arguments exit
2 before reading history or invoking SQLite. The fixture tests use disposable
databases.
Pressure and restart E2E fixtures keep fake jobs alive until the required state is observed, then release their wait files and check completion.
The top driver checks exercise a fake CLI in a temporary home. Full E2E reports job visibility, pause, kill confirmation, target removal, UI exit, terminal restoration, driver errors, and caller status separately. Failures print the last status snapshot, PTY tail, and job output.
Docs
This site lives in website/:
cd website
npm install
npm start
./scripts/record-demo.sh rerecords static/img/demo.svg, the terminal recording in the README and the intro. It runs two builds against a throwaway turnstile home, so the turnstile lines are real output. Rerun it when that output changes.
Releasing
Bump Turnstile.version in Sources/TurnstileCore/Paths.swift, rename "Unreleased" in CHANGELOG.md to the new version, commit, push, and push a matching tag:
git tag -a v0.5.0 -m "turnstile 0.5.0"
git push origin v0.5.0
The release workflow checks dependency licenses, tests, builds the universal CLI tarball and the notarized Turnstile.app, attests their build provenance, publishes both to a release here and on mcclowes/homebrew-turnstile, with notes from the changelog, and updates the tap's formula and cask. Running the workflow by hand builds, signs, and notarizes without publishing, to check the secrets.
To check a download came from this repo's workflow:
gh attestation verify "$(which turnstile)" --repo mcclowes/turnstile
./scripts/release.sh does the same from a Mac with the Developer ID certificate and the kiln-notary notarytool profile, tagging for you. It stays as a fallback until the workflow has shipped a release.
Release secrets
The workflow needs these Actions secrets:
| Secret | What it holds |
|---|---|
DEVELOPER_ID_P12_BASE64 | The Developer ID Application certificate and its private key, exported from Keychain Access as a .p12, then base64 -i cert.p12 | pbcopy |
DEVELOPER_ID_P12_PASSWORD | The password set when exporting the .p12 |
NOTARY_API_KEY_P8_BASE64 | An App Store Connect API key (Users and Access → Integrations, Developer access), the .p8 base64-encoded |
NOTARY_API_KEY_ID | That key's ID |
NOTARY_API_ISSUER_ID | The issuer ID shown above the keys |
TAP_GITHUB_TOKEN | A fine-grained token for mcclowes/homebrew-turnstile alone, with Contents read and write, to publish its release and push the formula and cask |
Releases on this repo use the workflow's own token.