Skills Development Testing Apple Notes Automation in CI

Testing Apple Notes Automation in CI

v20260423
apple-notes-ci-integration
This guide addresses the challenges of automating Apple Notes within Continuous Integration (CI) pipelines on macOS. Because standard CI environments restrict TCC (Transparency, Consent, and Control) permissions, direct automation via osascript usually fails. It provides patterns for using mock clients for unit testing and outlines best practices for running real integration tests on self-hosted runners with proper permissions.
Get Skill
419 downloads
Overview

Apple Notes CI Integration

Overview

Apple Notes automation is macOS-only because it depends on the Apple Events subsystem and Notes.app. CI pipelines must use GitHub Actions macOS runners (macos-latest or macos-14). However, macOS CI runners have restricted TCC (Transparency, Consent, and Control) permissions, which means direct Notes.app automation via osascript will fail in CI. The standard pattern is to run unit tests against a mock JXA client in CI, and reserve real Notes.app integration tests for local macOS machines or self-hosted runners with pre-granted automation permissions.

GitHub Actions Workflow

# .github/workflows/notes-ci.yml
name: Notes Automation CI
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  unit-tests:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: "20", cache: "npm" }
      - run: npm ci
      - name: Verify macOS version
        run: sw_vers
      - name: Lint JXA scripts
        run: |
          # Validate JavaScript syntax in all .jxa files
          for f in scripts/*.jxa; do
            node --check "$f" 2>/dev/null || echo "WARN: $f is osascript-only"
          done
      - name: Unit tests (mocked Notes client)
        run: npm test
      - name: Validate JXA templates
        run: |
          # Ensure osascript can parse (but not execute) JXA scripts
          for f in scripts/*.jxa; do
            osascript -l JavaScript -e "$(cat "$f")" 2>&1 | grep -v "Not authorized" || true
          done

Mock Client for CI

// tests/mocks/notes-client.mock.ts
export class MockAppleNotesClient {
  private notes: Array<{ id: string; title: string; body: string; folder: string }> = [];

  createNote(title: string, body: string, folder = "Notes"): string {
    const id = `mock-note-${Date.now()}-${Math.random().toString(36).slice(2)}`;
    this.notes.push({ id, title, body, folder });
    return id;
  }

  listNotes() { return [...this.notes]; }
  getNote(id: string) { return this.notes.find(n => n.id === id) || null; }
  searchNotes(q: string) { return this.notes.filter(n => n.title.includes(q) || n.body.includes(q)); }
  deleteNote(id: string) { this.notes = this.notes.filter(n => n.id !== id); }
  getFolders() { return [...new Set(this.notes.map(n => n.folder))]; }
}

Self-Hosted Runner with TCC Pre-Approval

# On a self-hosted macOS runner, pre-grant automation permissions:
# 1. Open System Settings > Privacy & Security > Automation
# 2. Grant your CI user's terminal access to Notes.app
# 3. Verify with:
osascript -l JavaScript -e 'Application("Notes").defaultAccount.notes.length'

# For headless runners, use tccutil (requires SIP adjustment or MDM profile):
# sudo tccutil --insert com.apple.Notes --service AppleEvents --app /usr/bin/osascript

Error Handling

Issue Cause Solution
"Not authorized to send Apple events" in CI TCC blocks automation on CI runners Use mock client; real tests on self-hosted runner
osascript syntax errors not caught JXA has no standalone linter Use node --check for JS syntax; parse-only validation
Flaky tests on macos-latest Runner image updates change Notes state Pin to macos-14; always use mocked client
Tests pass locally, fail in CI Different macOS version or missing app Check sw_vers output; ensure Notes.app exists on runner
Timeout waiting for Notes.app App launch delay on cold runner Add open -a Notes && sleep 3 before osascript calls

Resources

Next Steps

For diagnosing CI failures, see apple-notes-common-errors. For production deployment of automation scripts, see apple-notes-deploy-integration.

Info
Category Development
Name apple-notes-ci-integration
Version v20260423
Size 4.5KB
Updated At 2026-04-28
Language