Regenerate changelog with the backfilled DMGs #178
Workflow file for this run
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
| name: CI | |
| # Runs on every push to Production and on all pull requests. | |
| # Tests what actually matters for the current codebase: | |
| # - Native macOS Swift app builds (Xcode on macos-latest) | |
| # - GitHub Pages website linting | |
| # | |
| # Windows and Linux are not supported — Zerm is a native macOS Swift app | |
| # built with AppKit/SwiftUI and has no cross-platform build path. | |
| # The previous CI tested an archived Tauri prototype that is no longer shipped. | |
| on: | |
| push: | |
| branches: [Production, main] | |
| pull_request: | |
| jobs: | |
| # ── Swift build (macOS only) ───────────────────────────────────────────── | |
| swift-build: | |
| name: Swift build (macOS) | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 | |
| - name: Select Xcode | |
| run: sudo xcode-select -s /Applications/Xcode.app | |
| - name: Resolve Swift packages | |
| run: | | |
| xcodebuild -project Zerm.xcodeproj \ | |
| -scheme Zerm \ | |
| -resolvePackageDependencies \ | |
| -clonedSourcePackagesDirPath .ci-packages \ | |
| 2>&1 | tail -5 | |
| - name: Build (no signing) | |
| run: | | |
| xcodebuild \ | |
| -project Zerm.xcodeproj \ | |
| -scheme Zerm \ | |
| -configuration Debug \ | |
| -clonedSourcePackagesDirPath .ci-packages \ | |
| CODE_SIGN_IDENTITY="" \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGNING_ALLOWED=YES \ | |
| DEVELOPMENT_TEAM="" \ | |
| build \ | |
| 2>&1 | xcpretty || xcodebuild \ | |
| -project Zerm.xcodeproj \ | |
| -scheme Zerm \ | |
| -configuration Debug \ | |
| CODE_SIGN_IDENTITY="" \ | |
| CODE_SIGNING_REQUIRED=NO \ | |
| CODE_SIGNING_ALLOWED=YES \ | |
| DEVELOPMENT_TEAM="" \ | |
| build 2>&1 | tail -20 | |
| # ── Website lint ───────────────────────────────────────────────────────── | |
| website-lint: | |
| name: Website lint | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 | |
| - name: Check HTML is valid (basic) | |
| run: | | |
| # Ensure index.html exists and has required landmarks | |
| test -f docs/index.html || (echo "docs/index.html missing" && exit 1) | |
| grep -q 'id="primary-download"' docs/index.html || (echo "Primary download button missing" && exit 1) | |
| grep -q 'id="download"' docs/index.html || (echo "Download section anchor missing" && exit 1) | |
| echo "HTML landmarks OK" | |
| - name: Check site.js has no GitHub Releases redirects | |
| run: | | |
| # Ensure we never send users to /releases page (regression guard) | |
| if grep -q 'github.com/arcusis/Zerm/releases"' docs/site.js; then | |
| echo "FAIL: site.js redirects to GitHub Releases page — fix direct download logic" | |
| exit 1 | |
| fi | |
| echo "No GitHub Releases redirect found — OK" | |
| # ── Security scan ──────────────────────────────────────────────────────── | |
| # Secret detection is handled by the GitGuardian app check and CodeQL, which | |
| # run on every PR. This job only covers the repo-specific home-path check. | |
| # (The repo's Actions policy is `selected` + sha-pinned, so third-party | |
| # actions like gitleaks/gitleaks-action are not permitted to start.) | |
| security-scan: | |
| name: Secret / PII scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Scan for hardcoded personal paths | |
| run: | | |
| # Ensure no absolute home-directory paths are committed in source | |
| FOUND=$(git grep -rE "/Users/[a-z][a-z0-9_-]+" \ | |
| -- "*.swift" "*.yml" "*.yaml" "*.md" "*.html" "*.js" "*.json" \ | |
| | grep -v "arcusis\|example\|placeholder" || true) | |
| if [ -n "$FOUND" ]; then | |
| echo "FAIL: Hardcoded user home paths found:" | |
| echo "$FOUND" | |
| exit 1 | |
| fi | |
| echo "No hardcoded home paths — OK" | |
| - name: Validate Sparkle appcast integrity | |
| run: | | |
| # The appcast XML itself is not signed — only the enclosure bytes are. | |
| # Guard the two properties that keep OTA safe: every advertised update | |
| # must carry an EdDSA signature and be served from the official | |
| # GitHub Releases host. A missing/blank signature or an off-host | |
| # enclosure fails the PR instead of shipping a bad or unverifiable feed. | |
| for feed in docs/appcast.xml appcast.xml; do | |
| [ -f "$feed" ] || continue | |
| echo "Checking $feed" | |
| enclosures=$(grep -c "<enclosure " "$feed" || true) | |
| if [ "$enclosures" -eq 0 ]; then | |
| echo "FAIL: $feed has no <enclosure> element"; exit 1 | |
| fi | |
| sigs=$(grep -c 'sparkle:edSignature="[^"]\{20,\}"' "$feed" || true) | |
| if [ "$sigs" -ne "$enclosures" ]; then | |
| echo "FAIL: $feed has $enclosures enclosure(s) but $sigs signed — every update must be EdDSA-signed"; exit 1 | |
| fi | |
| if grep -q '<enclosure ' "$feed" && ! grep 'url="https://github.com/arcusis/Zerm/releases/download/' "$feed" >/dev/null; then | |
| echo "FAIL: $feed enclosure is not served from the official GitHub Releases host"; exit 1 | |
| fi | |
| done | |
| echo "Appcast integrity — OK" |