name: Build on: push: branches: - main pull_request: workflow_dispatch: permissions: contents: read concurrency: group: build-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: PROJECT_NAME: MacTools SCHEME: MacTools DERIVED_DATA: build/DerivedData CI_BUNDLE_IDENTIFIER_PREFIX: dev.mactools.ci jobs: build: name: Build and test runs-on: macos-26 timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v5 - name: Show Xcode version run: xcodebuild -version - name: Install XcodeGen run: | if ! command -v xcodegen >/dev/null 2>&1; then brew install xcodegen fi - name: Write CI local config run: | cat > LocalConfig.xcconfig < "$ARTIFACT_ROOT/run-debug.sh" <<'EOF' #!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "$0")" && pwd)" LOCAL_CATALOG_PATH="$ROOT/LocalPlugins/catalog.local.json" PACKAGES_DIR="$ROOT/LocalPlugins/Packages" INSTALL_DIR="$HOME/Library/Application Support/MacTools Dev/Plugins/Installed" /usr/bin/ruby -rjson -ruri -e ' root = ARGV.fetch(0) catalog_path = File.join(root, "LocalPlugins", "catalog.dev.json") output_path = File.join(root, "LocalPlugins", "catalog.local.json") catalog = JSON.parse(File.read(catalog_path)) (catalog["plugins"] || []).each do |plugin| package = plugin["package"] || {} package_path = File.expand_path(File.join(root, "LocalPlugins", "Packages", "#{plugin.fetch("id")}.mactoolsplugin")) package["url"] = URI::DEFAULT_PARSER.escape("file://#{package_path}") end File.write(output_path, JSON.pretty_generate(catalog)) ' "$ROOT" mkdir -p "$INSTALL_DIR" find "$PACKAGES_DIR" -maxdepth 1 -name "*.mactoolsplugin" -type d -print0 | while IFS= read -r -d '' package; do destination="$INSTALL_DIR/$(basename "$package")" staging="$INSTALL_DIR/.$(basename "$package").syncing.$$" rm -rf "$staging" ditto "$package" "$staging" rm -rf "$destination" mv "$staging" "$destination" done LOCAL_CATALOG_URL="$(/usr/bin/ruby -ruri -e 'puts URI::DEFAULT_PARSER.escape("file://#{File.expand_path(ARGV.fetch(0))}")' "$LOCAL_CATALOG_PATH")" export MACTOOLS_PLUGIN_CATALOG_URL="$LOCAL_CATALOG_URL" open "$ROOT/MacTools Dev.app" EOF chmod +x "$ARTIFACT_ROOT/run-debug.sh" cat > "$ARTIFACT_ROOT/README.txt" <<'EOF' This is an unsigned Debug build for local testing. Run ./run-debug.sh to launch MacTools Dev with the bundled local plugin catalog. If macOS blocks the app because it was downloaded from the internet, remove quarantine: xattr -dr com.apple.quarantine "MacTools Dev.app" Then run ./run-debug.sh again. EOF (cd build/debug-artifact && ditto -c -k --sequesterRsrc --keepParent MacTools-Debug MacTools-Debug.zip) - name: Upload Debug app artifact if: github.event_name == 'workflow_dispatch' uses: actions/upload-artifact@v4 with: name: MacTools-Debug path: build/debug-artifact/MacTools-Debug.zip if-no-files-found: error - name: Build unsigned Release app if: github.event_name != 'pull_request' run: | xcodebuild \ -project "${PROJECT_NAME}.xcodeproj" \ -scheme "${SCHEME}" \ -configuration Release \ -destination "generic/platform=macOS" \ -derivedDataPath "${DERIVED_DATA}" \ CODE_SIGNING_ALLOWED=NO \ CODE_SIGNING_REQUIRED=NO \ CODE_SIGN_IDENTITY= \ build \ -quiet