From 33c49ee40142e508d5925eedd96b7d08ed8697b5 Mon Sep 17 00:00:00 2001 From: Nathan Davis <271831810+nathandavismail-cmyk@users.noreply.github.com> Date: Wed, 30 Sep 2026 12:13:12 -0700 Subject: [PATCH 1/2] Bring the Mac version up to Windows, plus signing, iCloud and native menus Mac counterparts of every Windows page (Hardware, Login items, Apps, Broken items), the menu bar icon and notifications, FSEvents quick rescans, the macOS cleaner and suggestions, and the macOS follow-up list: Developer ID signing and notarization (off until the Apple secrets are set), iCloud Remove download, leftovers of deleted apps, native menus and Settings. See CHANGELOG.md and docs/testing-macos.md. Co-Authored-By: Claude Opus 5.5 --- .github/ISSUE_TEMPLATE/bug_report.yml | 10 + .github/workflows/release.yml | 80 +- CHANGELOG.md | 125 ++ CONTRIBUTING.md | 53 +- Cargo.lock | 105 +- Cargo.toml | 17 +- README.md | 343 ++++-- docs/releasing.md | 86 +- docs/testing-macos.md | 258 ++++ packaging/macos/heft.entitlements | 15 + scripts/bundle-macos.sh | 19 +- scripts/homebrew-cask.sh | 58 + site/faq.html | 46 +- site/guides/alerts.html | 18 +- site/guides/cleaner.html | 42 +- site/guides/cleaning-up.html | 27 +- site/guides/command-line.html | 20 +- site/guides/disk-usage.html | 2 + site/guides/duplicates.html | 25 +- site/guides/hardware.html | 17 +- site/guides/index.html | 15 +- site/guides/mac-tools.html | 154 +++ site/guides/windows-tools.html | 4 +- site/index.html | 14 +- site/tutorial.html | 8 +- src/app/alerts_view.rs | 72 +- src/app/compress_view.rs | 149 ++- src/app/hardware/dashboard.rs | 65 +- src/app/hardware/draw.rs | 15 + src/app/hardware/mod.rs | 6 +- src/app/hardware/table.rs | 2 +- src/app/icloud_view.rs | 186 +++ src/app/live.rs | 96 +- src/app/mod.rs | 233 +++- src/app/relocate_view.rs | 9 +- src/app/removed_view.rs | 59 +- src/app/screens.rs | 93 +- src/app/settings_view.rs | 109 ++ src/app/suggest_view.rs | 49 +- src/app/theme_toggle.rs | 90 ++ src/app/tools/broken_mac.rs | 406 ++++++ src/app/tools/cleaner.rs | 46 +- src/app/tools/cleaner_mac.rs | 154 +++ src/app/tools/mod.rs | 34 +- src/app/tools/programs_mac.rs | 1161 ++++++++++++++++++ src/app/tools/startup_mac.rs | 507 ++++++++ src/clean/mac.rs | 401 ++++++ src/clean/mod.rs | 272 ++++- src/clean/parse.rs | 102 ++ src/clean/rules.rs | 9 +- src/clean/rules_unix.rs | 688 +++++++++-- src/clean/unix.rs | 414 ++++++- src/clean/windows.rs | 37 +- src/cli.rs | 270 +++- src/compress.rs | 808 +++++++++++- src/mac/appmenu.rs | 284 +++++ src/mac/apps.rs | 1631 +++++++++++++++++++++++++ src/mac/apps/brew.rs | 690 +++++++++++ src/mac/apps/orphans.rs | 357 ++++++ src/mac/apps/updaters.rs | 325 +++++ src/mac/broken.rs | 1535 +++++++++++++++++++++++ src/mac/icloud.rs | 143 +++ src/mac/menubar.rs | 646 ++++++++++ src/mac/mod.rs | 470 +++++++ src/mac/notify.rs | 105 ++ src/mac/startup.rs | 1184 ++++++++++++++++++ src/main.rs | 8 +- src/monitor.rs | 19 +- src/platform/mod.rs | 21 +- src/platform/unix.rs | 150 ++- src/platform/windows.rs | 2 +- src/recommend.rs | 569 ++++++++- src/risk.rs | 135 +- src/scan/fsevents.rs | 1217 ++++++++++++++++++ src/scan/mod.rs | 69 +- src/scan/walk/mod.rs | 74 +- src/scan/walk/update.rs | 545 +++++++++ src/sensors/mac/battery.rs | 191 +++ src/sensors/mac/board.rs | 133 ++ src/sensors/mac/cf.rs | 396 ++++++ src/sensors/mac/cpu.rs | 282 +++++ src/sensors/mac/gpu.rs | 168 +++ src/sensors/mac/hid.rs | 171 +++ src/sensors/mac/mod.rs | 348 ++++++ src/sensors/mac/net.rs | 202 +++ src/sensors/mac/smc.rs | 254 ++++ src/sensors/mac/soc.rs | 426 +++++++ src/sensors/mac/storage.rs | 381 ++++++ src/sensors/mod.rs | 14 +- src/trashlog.rs | 356 +++++- src/tree.rs | 11 + 91 files changed, 20942 insertions(+), 673 deletions(-) create mode 100644 docs/testing-macos.md create mode 100644 packaging/macos/heft.entitlements create mode 100644 scripts/homebrew-cask.sh create mode 100644 site/guides/mac-tools.html create mode 100644 src/app/icloud_view.rs create mode 100644 src/app/settings_view.rs create mode 100644 src/app/theme_toggle.rs create mode 100644 src/app/tools/broken_mac.rs create mode 100644 src/app/tools/cleaner_mac.rs create mode 100644 src/app/tools/programs_mac.rs create mode 100644 src/app/tools/startup_mac.rs create mode 100644 src/clean/mac.rs create mode 100644 src/mac/appmenu.rs create mode 100644 src/mac/apps.rs create mode 100644 src/mac/apps/brew.rs create mode 100644 src/mac/apps/orphans.rs create mode 100644 src/mac/apps/updaters.rs create mode 100644 src/mac/broken.rs create mode 100644 src/mac/icloud.rs create mode 100644 src/mac/menubar.rs create mode 100644 src/mac/mod.rs create mode 100644 src/mac/notify.rs create mode 100644 src/mac/startup.rs create mode 100644 src/scan/fsevents.rs create mode 100644 src/scan/walk/update.rs create mode 100644 src/sensors/mac/battery.rs create mode 100644 src/sensors/mac/board.rs create mode 100644 src/sensors/mac/cf.rs create mode 100644 src/sensors/mac/cpu.rs create mode 100644 src/sensors/mac/gpu.rs create mode 100644 src/sensors/mac/hid.rs create mode 100644 src/sensors/mac/mod.rs create mode 100644 src/sensors/mac/net.rs create mode 100644 src/sensors/mac/smc.rs create mode 100644 src/sensors/mac/soc.rs create mode 100644 src/sensors/mac/storage.rs diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 07e18a8..e9a1b82 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -38,6 +38,8 @@ body: - Startup programs - Installed programs / updates - Registry issues + - Hardware monitor + - Mac tools (login items, apps, broken items) - Something else - type: textarea id: what @@ -58,3 +60,11 @@ body: label: Scan output (for wrong sizes) description: Output of `heft --bench `, or on Windows as administrator `heft --compare C:`. render: text + - type: textarea + id: sensors + attributes: + label: Sensor report (for hardware readings on a Mac) + description: >- + Attach the file from `heft --sensors --report --out report.txt` + (with Heft.app, `/Applications/Heft.app/Contents/MacOS/heft`), and + say which reading is wrong and what it should be. diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 03b9df3..99b01cd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -192,6 +192,34 @@ jobs: with: name: third-party-licenses + # Developer ID signing and notarization. Both are skipped, and the app + # is signed ad hoc, until the repository variable APPLE_TEAM_ID is set + # along with the secrets and variables below. See docs/releasing.md. + - name: Import the signing certificate + if: vars.APPLE_TEAM_ID != '' + env: + CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }} + CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} + TEAM_ID: ${{ vars.APPLE_TEAM_ID }} + run: | + keychain="$RUNNER_TEMP/signing.keychain-db" + password=$(uuidgen) + echo "$CERTIFICATE" | base64 --decode > "$RUNNER_TEMP/certificate.p12" + security create-keychain -p "$password" "$keychain" + security set-keychain-settings -lut 21600 "$keychain" + security unlock-keychain -p "$password" "$keychain" + security import "$RUNNER_TEMP/certificate.p12" -k "$keychain" -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign + rm "$RUNNER_TEMP/certificate.p12" + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$password" "$keychain" > /dev/null + security list-keychains -d user -s "$keychain" $(security list-keychains -d user | tr -d '"') + identity=$(security find-identity -v -p codesigning "$keychain" \ + | sed -n "s/.*\"\(Developer ID Application: .* ($TEAM_ID)\)\"/\1/p" | head -1) + if [ -z "$identity" ]; then + echo "::error::MACOS_CERTIFICATE has no Developer ID Application certificate for team $TEAM_ID" + exit 1 + fi + echo "HEFT_SIGN_IDENTITY=$identity" >> "$GITHUB_ENV" + - run: bash scripts/bundle-macos.sh - name: Smoke test @@ -200,16 +228,52 @@ jobs: cat bench.txt grep -q "^files" bench.txt + # Apple checks the app for malware and issues a ticket, which is then + # stapled to the app so Gatekeeper accepts it without going online. + - name: Notarize + if: vars.APPLE_TEAM_ID != '' + env: + API_KEY: ${{ secrets.APPLE_API_KEY }} + API_KEY_ID: ${{ vars.APPLE_API_KEY_ID }} + API_ISSUER_ID: ${{ vars.APPLE_API_ISSUER_ID }} + run: | + key="$RUNNER_TEMP/AuthKey.p8" + printf '%s\n' "$API_KEY" > "$key" + auth=(--key "$key" --key-id "$API_KEY_ID" --issuer "$API_ISSUER_ID") + ditto -c -k --keepParent target/Heft.app "$RUNNER_TEMP/notarize.zip" + result=$(xcrun notarytool submit "$RUNNER_TEMP/notarize.zip" "${auth[@]}" --wait --timeout 1h --output-format json) + echo "$result" + if [ "$(jq -r .status <<< "$result")" != Accepted ]; then + xcrun notarytool log "$(jq -r .id <<< "$result")" "${auth[@]}" || true + echo "::error::Notarization failed" + exit 1 + fi + rm "$key" + xcrun stapler staple target/Heft.app + spctl --assess --type execute --verbose=2 target/Heft.app + - name: Package run: | mkdir dist ditto -c -k --keepParent target/Heft.app "dist/heft-$VERSION-macos-universal.zip" + - name: Homebrew cask + run: bash scripts/homebrew-cask.sh "$VERSION" "dist/heft-$VERSION-macos-universal.zip" homebrew + + - name: Remove the signing keychain + if: always() && vars.APPLE_TEAM_ID != '' + run: security delete-keychain "$RUNNER_TEMP/signing.keychain-db" || true + - uses: actions/upload-artifact@v7 with: name: dist-macos path: dist/* + - uses: actions/upload-artifact@v7 + with: + name: homebrew-cask + path: homebrew/heft.rb + linux: name: Linux needs: version @@ -283,13 +347,17 @@ jobs: - name: Create draft release env: GH_TOKEN: ${{ github.token }} - SIGNED: ${{ vars.SIGNPATH_ORGANIZATION_ID != '' }} + WINDOWS_SIGNED: ${{ vars.SIGNPATH_ORGANIZATION_ID != '' }} + MACOS_SIGNED: ${{ vars.APPLE_TEAM_ID != '' }} run: | - if [ "$SIGNED" = true ]; then - signing="heft.exe is code-signed through [SignPath Foundation](https://signpath.org/). The macOS download isn't signed yet, so macOS warns the first time you open Heft." - else - signing="The downloads aren't code-signed yet, so Windows and macOS warn the first time you open Heft." - fi + windows="heft.exe is code-signed through [SignPath Foundation](https://signpath.org/)." + macos="Heft.app is signed with a Developer ID and notarized by Apple." + case "$WINDOWS_SIGNED/$MACOS_SIGNED" in + true/true) signing="$windows $macos" ;; + true/*) signing="$windows The macOS download isn't signed yet, so macOS warns the first time you open Heft." ;; + */true) signing="$macos The Windows download isn't signed yet, so Windows warns the first time you open Heft." ;; + *) signing="The downloads aren't code-signed yet, so Windows and macOS warn the first time you open Heft." ;; + esac cat >> notes.md <