171 lines
5.9 KiB
YAML
171 lines
5.9 KiB
YAML
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 <<EOF
|
|
DEVELOPMENT_TEAM =
|
|
BUNDLE_IDENTIFIER_PREFIX = ${CI_BUNDLE_IDENTIFIER_PREFIX}
|
|
EOF
|
|
|
|
- name: Generate Xcode project
|
|
run: make generate
|
|
|
|
- name: Build and run tests
|
|
run: |
|
|
xcodebuild \
|
|
-project "${PROJECT_NAME}.xcodeproj" \
|
|
-scheme "${SCHEME}" \
|
|
-configuration Debug \
|
|
-destination "platform=macOS" \
|
|
-derivedDataPath "${DERIVED_DATA}" \
|
|
CODE_SIGNING_ALLOWED=NO \
|
|
CODE_SIGNING_REQUIRED=NO \
|
|
CODE_SIGN_IDENTITY= \
|
|
test \
|
|
-quiet
|
|
|
|
- name: Package Debug app artifact
|
|
if: github.event_name == 'workflow_dispatch'
|
|
run: |
|
|
set -euo pipefail
|
|
PRODUCTS_DIR="${DERIVED_DATA}/Build/Products/Debug"
|
|
APP_PATH="${PRODUCTS_DIR}/MacTools Dev.app"
|
|
ARTIFACT_ROOT="build/debug-artifact/MacTools-Debug"
|
|
|
|
find "$PRODUCTS_DIR" -maxdepth 1 -name "*.bundle" -type d -print0 | while IFS= read -r -d '' bundle; do
|
|
codesign --force --deep --sign - "$bundle"
|
|
codesign --verify --deep --strict "$bundle"
|
|
done
|
|
|
|
if [[ -d "$APP_PATH/Contents/Frameworks" ]]; then
|
|
find "$APP_PATH/Contents/Frameworks" -type d \( -name "*.framework" -o -name "*.xpc" \) -print0 | while IFS= read -r -d '' item; do
|
|
codesign --force --deep --sign - "$item"
|
|
done
|
|
fi
|
|
|
|
codesign --force --deep --sign - --entitlements Configs/MacTools.entitlements "$APP_PATH"
|
|
codesign --verify --deep --strict "$APP_PATH"
|
|
|
|
./scripts/plugins/sync-debug-plugins.sh \
|
|
--source-dir Plugins \
|
|
--products-dir "$PRODUCTS_DIR" \
|
|
--output-dir build/LocalPlugins \
|
|
--skip-install
|
|
|
|
rm -rf build/debug-artifact
|
|
mkdir -p "$ARTIFACT_ROOT"
|
|
ditto "$APP_PATH" "$ARTIFACT_ROOT/MacTools Dev.app"
|
|
ditto build/LocalPlugins "$ARTIFACT_ROOT/LocalPlugins"
|
|
|
|
cat > "$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
|