-
-
Notifications
You must be signed in to change notification settings - Fork 129
feat(cli): precompiled, signed & notarized macOS keychain helper packages #2458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 14 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
b357ed9
docs: design spec for precompiled macOS keychain helper packages
WcaleNieWolny 0a81ee7
docs: harden helper spec — strip env override from release, verify bi…
WcaleNieWolny b2bf229
docs: remove swiftc fallback from helper spec — verified binary or ha…
WcaleNieWolny 640abfc
docs: implementation plan for precompiled keychain helper
WcaleNieWolny e36c1eb
docs: generic helper binary + subcommand, anti-footgun gate, SECURITY…
WcaleNieWolny 67f6829
docs: record future native-UI/.app path + pin stable signing identifi…
WcaleNieWolny 758cb9a
docs: switch helper release to deliberate workflow_dispatch (button),…
WcaleNieWolny f894a8c
feat(cli-helper): precompiled macOS keychain helper packages
WcaleNieWolny ee6f104
feat(cli): run precompiled helper with signature verification, drop s…
WcaleNieWolny cbfa23c
ci: workflow_dispatch helper publish + release strip assertion
WcaleNieWolny 36bb529
docs: fix plan architecture line to workflow_dispatch (was stale 'tag…
WcaleNieWolny 8ec2181
fix: drop stale compile-helper test + address review nits
claude 41ecf9c
feat(cli-helper): ship helper as hidden Capgo.app bundle
WcaleNieWolny 5630bf2
chore: address CodeRabbit review
WcaleNieWolny b3c8485
ci(helper): drop GITHUB_TOKEN to contents: read (release uses PAT)
WcaleNieWolny 5f96c4c
ci(helper): also trigger on cli-helper-* tag (testable from a branch)
WcaleNieWolny 57aa9ff
ci(helper): publish under the 'rc' dist-tag (keep new packages off 'l…
WcaleNieWolny c0c0c41
ci(helper): hardcode public team id UVTJ336J2D (not a secret)
WcaleNieWolny 0d15569
ci(helper): decode base64 APPLE_KEY_CONTENT before notarytool (fixes …
WcaleNieWolny 6030554
Merge remote-tracking branch 'origin/main' into feat/precompiled-keyc…
WcaleNieWolny 4a1bd15
ci(helper): run precompiled-helper signature tests in the macOS TUI w…
WcaleNieWolny 56842c3
test(helper): bump private suite to drift-fixed main (drops compiling…
WcaleNieWolny d19ec57
test(helper): pin private suite to the capgo-main-calibrated branch
WcaleNieWolny 5f2d277
fix(helper): harden signing path per hostile review
WcaleNieWolny 97795f7
ci(helper): fix gate smoke tests for stdin passphrase interface
WcaleNieWolny a692637
ci(helper): publish stable versions to npm 'latest', prereleases to 'rc'
WcaleNieWolny cd6c6e4
feat(cli): declare keychain helper packages as optionalDependencies
WcaleNieWolny File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,133 @@ | ||
| name: Build and publish CLI keychain helper | ||
|
|
||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "Helper version to publish, e.g. 1.0.0 (no 'cli-helper-' prefix)" | ||
| required: true | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| publish_cli_helper: | ||
| runs-on: macos-latest | ||
| name: Build, sign, notarize, publish keychain helper | ||
| timeout-minutes: 45 | ||
| permissions: | ||
| contents: write | ||
| id-token: write | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v6 | ||
| with: | ||
| persist-credentials: false | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v6 | ||
| with: | ||
| node-version: 24.x | ||
| registry-url: https://registry.npmjs.org | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - name: Validate + capture version | ||
| id: version | ||
| run: | | ||
| v="${{ github.event.inputs.version }}" | ||
| if ! echo "$v" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$'; then | ||
| echo "::error::version '$v' is not semver (e.g. 1.0.0)"; exit 1 | ||
| fi | ||
| echo "version=$v" >> "$GITHUB_OUTPUT" | ||
| - name: Build helper bundles | ||
| run: bash cli-helper/scripts/build.sh "${{ steps.version.outputs.version }}" | ||
| - name: Import Developer ID certificate into throwaway keychain | ||
| env: | ||
| DEVELOPER_ID_CERT_BASE64: ${{ secrets.DEVELOPER_ID_CERT_BASE64 }} | ||
| DEVELOPER_ID_CERT_PASSWORD: ${{ secrets.DEVELOPER_ID_CERT_PASSWORD }} | ||
| run: | | ||
| KEYCHAIN_PATH="$RUNNER_TEMP/build.keychain-db" | ||
| KEYCHAIN_PWD="$(uuidgen)" | ||
| security create-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_PATH" | ||
| security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" | ||
| security unlock-keychain -p "$KEYCHAIN_PWD" "$KEYCHAIN_PATH" | ||
| echo "$DEVELOPER_ID_CERT_BASE64" | base64 -d > "$RUNNER_TEMP/cert.p12" | ||
| security import "$RUNNER_TEMP/cert.p12" -k "$KEYCHAIN_PATH" \ | ||
| -P "$DEVELOPER_ID_CERT_PASSWORD" -T /usr/bin/codesign | ||
| rm "$RUNNER_TEMP/cert.p12" | ||
| security set-key-partition-list -S apple-tool:,apple:,codesign: \ | ||
| -s -k "$KEYCHAIN_PWD" "$KEYCHAIN_PATH" | ||
| security list-keychains -d user -s "$KEYCHAIN_PATH" login.keychain | ||
| IDENTITY=$(security find-identity -v -p codesigning "$KEYCHAIN_PATH" \ | ||
| | awk -F'"' '/Developer ID Application/ {print $2; exit}') | ||
| if [ -z "$IDENTITY" ]; then | ||
| echo "::error::No Developer ID Application identity found in imported cert" | ||
| exit 1 | ||
| fi | ||
| echo "DEVELOPER_ID_IDENTITY=$IDENTITY" >> "$GITHUB_ENV" | ||
| - name: Write App Store Connect API key | ||
| env: | ||
| APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }} | ||
| run: | | ||
| printf '%s' "$APPLE_KEY_CONTENT" > "$RUNNER_TEMP/AuthKey.p8" | ||
| echo "APPLE_KEY_PATH=$RUNNER_TEMP/AuthKey.p8" >> "$GITHUB_ENV" | ||
| - name: Sign and notarize | ||
| env: | ||
| CAPGO_APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||
| APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }} | ||
| APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }} | ||
| run: bash cli-helper/scripts/sign-and-notarize.sh | ||
| - name: Smoke test signed binary | ||
| run: | | ||
| arch="$(uname -m)" | ||
| case "$arch" in | ||
| arm64) helper="./cli-helper/dist/arm64/Capgo.app/Contents/MacOS/capgo" ;; | ||
| x86_64) helper="./cli-helper/dist/x64/Capgo.app/Contents/MacOS/capgo" ;; | ||
| *) echo "::error::unsupported runner arch: $arch"; exit 1 ;; | ||
| esac | ||
| set +e | ||
| out=$("$helper") | ||
| code=$? | ||
| set -e | ||
| [ "$code" -ne 0 ] || { echo "::error::expected non-zero exit"; exit 1; } | ||
| echo "$out" | jq -e '.ok == false and .errorCode == "INVALID_ARGS"' > /dev/null \ | ||
| || { echo "::error::unexpected helper output: $out"; exit 1; } | ||
| - name: Gate test — keychain-export without handshake is FORBIDDEN_CALLER | ||
| run: | | ||
| arch="$(uname -m)" | ||
| case "$arch" in | ||
| arm64) helper="./cli-helper/dist/arm64/Capgo.app/Contents/MacOS/capgo" ;; | ||
| x86_64) helper="./cli-helper/dist/x64/Capgo.app/Contents/MacOS/capgo" ;; | ||
| *) echo "::error::unsupported runner arch: $arch"; exit 1 ;; | ||
| esac | ||
| set +e | ||
| out=$("$helper" keychain-export --sha1 "$(printf 'a%.0s' {1..40})" --output /tmp/x.p12 --passphrase p | cat) | ||
| set -e | ||
| echo "$out" | jq -e '.ok == false and .errorCode == "FORBIDDEN_CALLER"' > /dev/null \ | ||
| || { echo "::error::gate did not reject missing handshake: $out"; exit 1; } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| - name: Prepare packages | ||
| run: node cli-helper/scripts/prepare-publish.mjs "${{ steps.version.outputs.version }}" | ||
| - name: Publish darwin-arm64 | ||
| working-directory: cli-helper/npm/darwin-arm64 | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
| run: npm publish --provenance --access public | ||
| - name: Publish darwin-x64 | ||
| working-directory: cli-helper/npm/darwin-x64 | ||
| env: | ||
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | ||
| run: npm publish --provenance --access public | ||
| - name: Zip signed bundles for release assets | ||
| run: | | ||
| ditto -c -k --keepParent cli-helper/dist/arm64/Capgo.app cli-helper/dist/Capgo-arm64.zip | ||
| ditto -c -k --keepParent cli-helper/dist/x64/Capgo.app cli-helper/dist/Capgo-x64.zip | ||
| - name: Create tag + GitHub release | ||
| uses: softprops/action-gh-release@v2 | ||
| with: | ||
| tag_name: cli-helper-${{ steps.version.outputs.version }} | ||
| target_commitish: ${{ github.sha }} | ||
| files: | | ||
| cli-helper/dist/Capgo-arm64.zip | ||
| cli-helper/dist/Capgo-x64.zip | ||
| make_latest: false | ||
| token: "${{ secrets.PERSONAL_ACCESS_TOKEN }}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Capgo CLI keychain helper | ||
|
|
||
| Small Swift program (Security framework only), shipped inside a hidden macOS | ||
| app bundle, **`Capgo.app`**. The single binary uses subcommand dispatch — today | ||
| just `keychain-export`: | ||
|
|
||
| Capgo.app/Contents/MacOS/capgo keychain-export \ | ||
| --sha1 <40-hex> --output <path.p12> --passphrase <wrap-pass> --invoked-by capgo-cli | ||
|
|
||
| It exports one code-signing identity from the macOS Keychain as a | ||
| passphrase-wrapped PKCS#12 and always emits one line of JSON on stdout | ||
| (`{"ok":true,...}` or `{"ok":false,"errorCode":...}`). Future helpers are new | ||
| subcommands of the same signed binary. | ||
|
|
||
| ## Why a bundle (not a bare binary) | ||
|
|
||
| `Capgo.app` is an **`LSUIElement` agent** — no Dock icon, no Cmd-Tab entry, no | ||
| window; it runs headlessly and exits. The bundle gives two things a bare binary | ||
| can't: | ||
|
|
||
| - **Branded Keychain prompts.** Because the export runs from inside a signed | ||
| `Capgo.app`, the macOS Keychain "Allow / Always Allow" prompts show the | ||
| **Capgo name + icon** instead of a generic process name. (This requires the | ||
| bundle to be signed — see the dev note below.) | ||
| - **Stable ACL identity.** `CFBundleIdentifier = app.capgo.cli.helper` keys the | ||
| Keychain "Always Allow" grant, and it never changes across releases, so the | ||
| grant persists across CLI upgrades. The CLI also verifies the bundle's | ||
| Developer ID + Capgo Team ID code signature before running it. | ||
|
|
||
| The CLI execs `Capgo.app/Contents/MacOS/capgo` **directly** (never `open | ||
| Capgo.app`), so there is no Dock flash and no Gatekeeper "downloaded from the | ||
| internet" prompt (npm doesn't set the quarantine xattr; direct exec isn't a | ||
| LaunchServices launch). | ||
|
|
||
| Shipped as two precompiled, Developer-ID-signed, notarized, **stapled** npm | ||
| packages: | ||
|
|
||
| - `@capgo/cli-keychain-darwin-arm64` (Apple Silicon, macOS 11+) | ||
| - `@capgo/cli-keychain-darwin-x64` (Intel, macOS 10.15+) | ||
|
|
||
| Both are `optionalDependencies` of `@capgo/cli`; npm installs at most one. Each | ||
| ships its own `Capgo.app`. See SECURITY.md for the threat model. | ||
|
|
||
| ## Dev bootstrap (working on the Swift source) | ||
|
|
||
| The published CLI has no compile fallback. To test local Swift changes quickly: | ||
|
|
||
| swiftc cli-helper/src/helper.swift -framework Security -O -o /tmp/helper-dev | ||
| cd cli && NODE_ENV=development bun run build | ||
| CAPGO_KEYCHAIN_HELPER_PATH=/tmp/helper-dev node dist/index.js ... | ||
|
|
||
| `CAPGO_KEYCHAIN_HELPER_PATH` only exists in dev builds — it is dead-code- | ||
| eliminated from npm release builds (asserted in CI). The env-override path skips | ||
| both the signature check and the bundle, so point it at a binary you built and | ||
| trust. Note: a bare dev binary is **not** signed, so the Keychain prompt shows | ||
| the process name, not "Capgo" — to see the branded prompt, build + sign the | ||
| bundle (`bash cli-helper/scripts/build.sh` then `codesign … Capgo.app`). | ||
|
|
||
| ## Release | ||
|
|
||
| 1. Bump nothing in-repo — the version comes from the dispatch input. | ||
| 2. Run the workflow from the GitHub Actions UI ("Run workflow" → enter the | ||
| version), or: `gh workflow run publish_cli_helper.yml -f version=X.Y.Z` | ||
| 3. `.github/workflows/publish_cli_helper.yml` builds, signs, notarizes, | ||
| smoke-tests, publishes both packages with npm provenance, and creates the | ||
| `cli-helper-X.Y.Z` tag + GitHub release. | ||
| 4. Release only when `src/helper.swift` actually changed. | ||
|
|
||
| Required GitHub secrets: `DEVELOPER_ID_CERT_BASE64`, `DEVELOPER_ID_CERT_PASSWORD` | ||
| (Developer ID Application cert as base64 .p12), `APPLE_TEAM_ID`, plus existing | ||
| `APPLE_KEY_ID`, `APPLE_ISSUER_ID`, `APPLE_KEY_CONTENT` (App Store Connect API | ||
| key, used by notarytool) and `NPM_TOKEN`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| # Security model — Capgo CLI keychain helper | ||
|
|
||
| ## The boundary is the macOS Keychain ACL, not this binary | ||
|
|
||
| Exporting a code-signing private key triggers an OS-level Keychain prompt | ||
| ("Allow" / "Always Allow") that macOS enforces against the **calling binary's | ||
| code signature**. That prompt — not anything in this helper or in `@capgo/cli` | ||
| — is the security boundary. | ||
|
|
||
| ## Invoking the helper grants no privilege | ||
|
|
||
| An attacker who can run this `helper` on a victim's machine already has local | ||
| code execution as that user, and can call Apple's own `SecItemExport` or | ||
| `/usr/bin/security export` directly. This helper is a worse-for-them version of | ||
| tools already present on every Mac. It is **not** a privilege escalation. | ||
|
|
||
| ## Why we don't authenticate the caller | ||
|
|
||
| - The CLI runs as `node dist/index.js`; **node is signed by the user's Node | ||
| install, not by Capgo** — there is no Capgo signature on the parent to pin. | ||
| - A shared secret would live in readable JavaScript in the npm tarball. | ||
| - Parent-PID checks are TOCTOU-racy and subject to PID reuse. | ||
|
|
||
| ## What we do instead | ||
|
|
||
| - The CLI verifies **this binary's** Developer ID + Capgo Team ID signature | ||
| before running it (protects the CLI from a swapped helper). | ||
| - The sensitive `keychain-export` subcommand has an **anti-footgun gate** | ||
| (requires an internal `--invoked-by capgo-cli` handshake and a non-TTY | ||
| stdout). This stops casual/accidental/naive-script misuse. **It is explicitly | ||
| not a security boundary** — a determined local attacker reads the handshake | ||
| out of the open-source CLI. It exists to keep honest software honest. | ||
|
|
||
| ## Reporting expectation | ||
|
|
||
| Demonstrating that you can invoke this helper yourself, or that doing so exports | ||
| a key after the user grants the macOS prompt, is **out of scope by design** — it | ||
| is equivalent to calling Apple's keychain APIs, which any local process with the | ||
| user's privileges can already do. Reports must show a privilege boundary being | ||
| crossed that the OS would otherwise enforce. |
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||
| <plist version="1.0"> | ||
| <dict> | ||
| <key>CFBundleName</key> | ||
| <string>Capgo</string> | ||
| <key>CFBundleDisplayName</key> | ||
| <string>Capgo</string> | ||
| <key>CFBundleIdentifier</key> | ||
| <string>app.capgo.cli.helper</string> | ||
| <key>CFBundleExecutable</key> | ||
| <string>capgo</string> | ||
| <key>CFBundleIconFile</key> | ||
| <string>Capgo</string> | ||
| <key>CFBundlePackageType</key> | ||
| <string>APPL</string> | ||
| <key>CFBundleInfoDictionaryVersion</key> | ||
| <string>6.0</string> | ||
| <key>CFBundleShortVersionString</key> | ||
| <string>__VERSION__</string> | ||
| <key>CFBundleVersion</key> | ||
| <string>__VERSION__</string> | ||
| <key>LSMinimumSystemVersion</key> | ||
| <string>__MINOS__</string> | ||
| <key>LSUIElement</key> | ||
| <true/> | ||
| <key>NSHumanReadableCopyright</key> | ||
| <string>© Capgo</string> | ||
| </dict> | ||
| </plist> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "name": "@capgo/cli-keychain-darwin-arm64", | ||
| "version": "0.0.0", | ||
| "description": "Precompiled macOS (Apple Silicon) keychain helper for @capgo/cli", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/Cap-go/capgo.git", | ||
| "directory": "cli-helper" | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "os": ["darwin"], | ||
| "cpu": ["arm64"], | ||
| "files": ["Capgo.app"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| { | ||
| "name": "@capgo/cli-keychain-darwin-x64", | ||
| "version": "0.0.0", | ||
| "description": "Precompiled macOS (Intel) keychain helper for @capgo/cli", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/Cap-go/capgo.git", | ||
| "directory": "cli-helper" | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "os": ["darwin"], | ||
| "cpu": ["x64"], | ||
| "files": ["Capgo.app"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #!/usr/bin/env bash | ||
| # Build Capgo.app bundles (one per macOS arch) wrapping the keychain helper. | ||
| # | ||
| # Hidden agent app (LSUIElement = no Dock icon, not in Cmd-Tab) branded "Capgo", | ||
| # so the macOS Keychain prompts shown during export display the Capgo name + | ||
| # icon. The bundle identifier (app.capgo.cli.helper, from Info.plist) keys the | ||
| # Keychain "Always Allow" grant and is part of the codesign designated | ||
| # requirement the CLI enforces at runtime. | ||
| # | ||
| # Usage: build.sh [VERSION] | ||
| # VERSION is baked into Info.plist BEFORE signing (changing it after signing | ||
| # would break the seal). Defaults to 0.0.0 for local dev builds. | ||
| # | ||
| # arm64 targets macOS 11 (first Apple Silicon release); x64 targets 10.15 | ||
| # (oldest macOS that can run Node 20, the CLI's floor). | ||
| set -euo pipefail | ||
| cd "$(dirname "$0")/.." | ||
|
|
||
| VERSION="${1:-0.0.0}" | ||
| ASSETS="assets" | ||
| rm -rf dist | ||
| mkdir -p dist | ||
|
|
||
| build_arch() { | ||
| local arch="$1" target="$2" minos="$3" | ||
| local app="dist/$arch/Capgo.app" | ||
| mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources" | ||
| swiftc src/helper.swift -framework Security -O -target "$target" \ | ||
| -o "$app/Contents/MacOS/capgo" | ||
| chmod +x "$app/Contents/MacOS/capgo" | ||
| cp "$ASSETS/Capgo.icns" "$app/Contents/Resources/Capgo.icns" | ||
| sed -e "s/__VERSION__/$VERSION/g" -e "s/__MINOS__/$minos/g" \ | ||
| "$ASSETS/Info.plist.template" > "$app/Contents/Info.plist" | ||
| echo "Built $app (v$VERSION):" | ||
| file "$app/Contents/MacOS/capgo" | ||
| } | ||
|
|
||
| build_arch arm64 arm64-apple-macos11 11.0 | ||
| build_arch x64 x86_64-apple-macos10.15 10.15 |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.