Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,51 @@ jobs:
- name: Resolve packages
run: xcodebuild -resolvePackageDependencies -project Parcel.xcodeproj -scheme Parcel

- name: Verify scripts
run: |
bash -n \
Scripts/release.sh \
Scripts/verify-release.sh \
Scripts/verify-release-gates.sh \
Scripts/update-appcast.sh \
Scripts/test-update-appcast.sh \
Scripts/test-real-sparkle-signing.sh \
Scripts/verify-sparkle-key-consistency.sh \
Scripts/verify-no-network-ai.sh \
Scripts/verify-workflows.sh \
Scripts/verify-website-export-artifact.sh \
Scripts/ship-status.sh \
Scripts/final-local-qa.sh

- name: Verify workflows
run: bash Scripts/verify-workflows.sh

- name: Verify no network AI
run: bash Scripts/verify-no-network-ai.sh

- name: Build Debug
run: |
xcodebuild -project Parcel.xcodeproj -scheme Parcel -configuration Debug \
-derivedDataPath .derivedData build \
CODE_SIGN_IDENTITY="-" CODE_SIGNING_ALLOWED=YES

- name: Run unit tests
run: |
xcodebuild test -project Parcel.xcodeproj -scheme ParcelUnit -configuration Debug \
-derivedDataPath .derivedData-unit \
CODE_SIGN_IDENTITY="-" CODE_SIGNING_ALLOWED=YES

build-website:
runs-on: ubuntu-latest
defaults:
run:
working-directory: Website
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: Website/package-lock.json
- run: npm ci && npm run build
- name: Build website
working-directory: Website
run: npm ci && npm run lint && npm run build
- name: Verify website export artifact
run: bash Scripts/verify-website-export-artifact.sh
73 changes: 68 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
tags:
- "v*"

permissions:
contents: write

jobs:
release:
runs-on: macos-15
Expand All @@ -14,29 +17,89 @@ jobs:
- name: Install XcodeGen
run: brew install xcodegen

- name: Import Developer ID signing certificate
env:
DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64: ${{ secrets.DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 }}
DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD: ${{ secrets.DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
set -euo pipefail

if [[ -z "${DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64:-}" ]]; then
echo "Missing DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64 secret." >&2
exit 1
fi
if [[ -z "${DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD:-}" ]]; then
echo "Missing DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD secret." >&2
exit 1
fi

KEYCHAIN_PASSWORD="${KEYCHAIN_PASSWORD:-$(uuidgen)}"
CERTIFICATE_PATH="$RUNNER_TEMP/developer-id-application.p12"
KEYCHAIN_PATH="$RUNNER_TEMP/parcel-signing.keychain-db"
trap 'rm -f "$CERTIFICATE_PATH"' EXIT

echo -n "$DEVELOPER_ID_APPLICATION_CERTIFICATE_BASE64" | base64 --decode -o "$CERTIFICATE_PATH"
security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH"
security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security import "$CERTIFICATE_PATH" \
-P "$DEVELOPER_ID_APPLICATION_CERTIFICATE_PASSWORD" \
-A \
-t cert \
-f pkcs12 \
-k "$KEYCHAIN_PATH"
security list-keychains -d user -s "$KEYCHAIN_PATH"
security default-keychain -d user -s "$KEYCHAIN_PATH"
security set-key-partition-list -S apple-tool:,apple: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH"
security find-identity -v -p codesigning "$KEYCHAIN_PATH"

- name: Build, export, notarize
env:
DEVELOPMENT_TEAM: ${{ secrets.DEVELOPMENT_TEAM }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
UPDATE_APPCAST: "1"
SPARKLE_ED_PRIVATE_KEY: ${{ secrets.SPARKLE_ED_PRIVATE_KEY }}
SPARKLE_KEYCHAIN_ACCOUNT: ${{ secrets.SPARKLE_KEYCHAIN_ACCOUNT }}
PARCEL_SCREEN_RECORDING_VERIFIED: ${{ secrets.PARCEL_SCREEN_RECORDING_VERIFIED }}
PARCEL_SECOND_DISPLAY_VERIFIED: ${{ secrets.PARCEL_SECOND_DISPLAY_VERIFIED }}
PARCEL_SUPABASE_URL: ${{ secrets.PARCEL_SUPABASE_URL }}
PARCEL_SUPABASE_ANON_KEY: ${{ secrets.PARCEL_SUPABASE_ANON_KEY }}
PARCEL_SUPABASE_BUCKET: ${{ secrets.PARCEL_SUPABASE_BUCKET }}
PARCEL_MACOS13_VM_VERIFIED: ${{ secrets.PARCEL_MACOS13_VM_VERIFIED }}
run: |
chmod +x Scripts/release.sh
chmod +x Scripts/*.sh
./Scripts/release.sh

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
- uses: actions/setup-node@v4
with:
files: build/Parcel.zip
generate_release_notes: true
node-version: "22"
cache: npm
cache-dependency-path: Website/package-lock.json

- name: Build website
working-directory: Website
run: |
npm ci
npm run lint
npm run build

- name: Verify website export artifact
run: bash Scripts/verify-website-export-artifact.sh

- name: Upload website artifact
uses: actions/upload-artifact@v4
with:
name: website-dist
path: Website/out

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: build/Parcel.zip
generate_release_notes: true

- name: Delete signing keychain
if: always()
run: security delete-keychain "$RUNNER_TEMP/parcel-signing.keychain-db" || true
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ xcuserdata/
## XcodeGen — the project is generated from project.yml.
## Regenerate locally with `xcodegen generate`.
Parcel.xcodeproj/
Notable.xcodeproj/

## Swift Package Manager
.build/
Expand All @@ -31,5 +32,20 @@ Package.resolved
## Misc
*.log
.derivedData-release/
.vercel-deploy*.json
.vercel-*
.deploy-*
.mcp-*
qa-evidence/
.cursor/

# Local deployment and macOS UI-automation helpers (not release inputs)
Scripts/deploy-parts-helper.mjs
Scripts/mcp-deploy.cjs
Scripts/mcp-deploy.mjs
Scripts/click-add-screen-recording.swift
Scripts/dump-settings-ax.swift
Scripts/enable-screen-recording.swift
Scripts/install-dev.sh

# Legacy, unused local artwork retained only for migration reference
Website/public/assets/notable-permission.svg
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
</p>

<p>
<a href="https://parcel.parable.dev"><img alt="Live site" src="https://img.shields.io/badge/live_site-parcel.parable.dev-8b5cf6?style=flat-square&labelColor=1a1a1a"></a>
<a href="https://parcel-zeta-silk.vercel.app"><img alt="Live site" src="https://img.shields.io/badge/live_site-parcel--zeta--silk.vercel.app-8b5cf6?style=flat-square&labelColor=1a1a1a"></a>
<img alt="macOS 13+" src="https://img.shields.io/badge/macOS-13%2B-000?style=flat-square&logo=apple&logoColor=white&labelColor=1a1a1a">
<img alt="14 tools" src="https://img.shields.io/badge/tools-14-ec4899?style=flat-square&labelColor=1a1a1a">
<img alt="0 cloud AI" src="https://img.shields.io/badge/cloud_AI-0-5ee4b5?style=flat-square&labelColor=1a1a1a">
<a href="LICENSE"><img alt="MIT License" src="https://img.shields.io/badge/license-MIT-22c55e?style=flat-square&labelColor=1a1a1a"></a>
</p>

<p>
<a href="https://parcel.parable.dev"><b>Website</b></a>
<a href="https://parcel-zeta-silk.vercel.app"><b>Website</b></a>
&nbsp;·&nbsp;
<a href="https://parcel.parable.dev/downloads/Parcel.zip"><b>Download</b></a>
<a href="https://parcel-zeta-silk.vercel.app/downloads/Parcel.zip"><b>Download</b></a>
&nbsp;·&nbsp;
<a href="docs/README.md">Docs</a>
&nbsp;·&nbsp;
Expand All @@ -28,7 +28,7 @@
<a href="CONTRIBUTING.md">Contributing</a>
</p>

<a href="https://parcel.parable.dev">
<a href="https://parcel-zeta-silk.vercel.app">
<img src=".github/assets/hero.svg" alt="Parcel — Capture, mark up, and ship" width="100%">
</a>

Expand Down Expand Up @@ -95,12 +95,16 @@ Signed, notarized builds via [`Scripts/release.sh`](Scripts/release.sh):

```sh
DEVELOPMENT_TEAM=XXXXXXXXXX \
APPLE_ID=you@example.com \
APPLE_APP_PASSWORD=xxxx-xxxx-xxxx-xxxx \
NOTARYTOOL_PROFILE=parcel-release \
UPDATE_APPCAST=1 \
./Scripts/release.sh
```

Set `SKIP_NOTARIZE=1` for unsigned local Release builds. Tag `v*` triggers [`.github/workflows/release.yml`](.github/workflows/release.yml).
Use `APPLE_ID` + `APPLE_APP_PASSWORD` instead of `NOTARYTOOL_PROFILE` if preferred. Run
[`Scripts/verify-release-gates.sh`](Scripts/verify-release-gates.sh) before release and
[`Scripts/verify-release.sh`](Scripts/verify-release.sh) after packaging. Set `SKIP_NOTARIZE=1`
for unsigned local Release builds. See [docs/RELEASE_READINESS.md](docs/RELEASE_READINESS.md)
for the full public ZIP runbook. Tag `v*` triggers [`.github/workflows/release.yml`](.github/workflows/release.yml).

<br>

Expand All @@ -116,7 +120,7 @@ Sources/Parcel/
Vision/ On-device OCR, faces, QR, translation
Upload/ Supabase Storage REST client
Hotkeys/ Carbon global hotkey + Preferences
Website/ Next.js marketing site (parcel.parable.dev)
Website/ Next.js marketing site (parcel-zeta-silk.vercel.app)
docs/ Architecture, parity, QA, integrations
Scripts/ release.sh, generate_icons.sh
Casks/ Homebrew cask (parcel.rb)
Expand Down Expand Up @@ -170,5 +174,5 @@ Parcel is released under the [MIT License](LICENSE) — free and open. Built by
<br>

<div align="center">
<sub>Part of the Parable ecosystem · <a href="https://github.com/bswxyz/parable">Parable components & templates</a> · <a href="https://parcel.parable.dev">parcel.parable.dev</a></sub>
<sub>Part of the Parable ecosystem · <a href="https://github.com/bswxyz/parable">Parable components & templates</a> · <a href="https://parcel-zeta-silk.vercel.app">parcel-zeta-silk.vercel.app</a></sub>
</div>
Loading
Loading