Skip to content

new: publish to homebrew#1135

Merged
lollipopkit merged 7 commits into
mainfrom
lollipopkit/issue896
Apr 23, 2026
Merged

new: publish to homebrew#1135
lollipopkit merged 7 commits into
mainfrom
lollipopkit/issue896

Conversation

@lollipopkit
Copy link
Copy Markdown
Owner

@lollipopkit lollipopkit commented Apr 23, 2026

Fixes #896

Summary by CodeRabbit

  • Documentation

    • Added macOS release docs (EN and ZH) describing notarized DMG creation, prerequisites, environment variables, and release steps.
  • New Features

    • End-to-end macOS DMG release pipeline: build, signing, notarization, stapling, packaging, and optional GitHub release upload.
    • Release helper scripts to prepare and package DMG artifacts.
    • Top-level Makefile to streamline dev, build, test, codegen, and release workflows.
  • Chores

    • Added a release environment template and updated ignore rules to skip local env files.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

Adds a macOS release pipeline: introduces .env.release.example for Apple signing/notarization variables; updates .gitignore to ignore .env.release and .env; adds a top-level Makefile with build, test, gen, and release targets; adds two release scripts (scripts/release/release-macos-dmg.sh, scripts/release/package-dmg-from-xcarchive.sh) that build/archive, sign, package into a DMG, notarize/staple, and optionally upload a GitHub Release; and updates README.md and README_zh.md documenting prerequisites and the release workflow.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (1 warning, 2 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The pull request title 'new: publish to homebrew' is vague and does not clearly describe the actual changes, which focus on creating a macOS release pipeline with notarization and DMG packaging. Revise the title to accurately reflect the main changes, such as 'Add macOS release pipeline with notarization and DMG packaging' or 'Add release automation for signed and notarized macOS DMG builds'.
Linked Issues check ❓ Inconclusive Issue #896 description is empty, making it impossible to validate whether the code changes meet the stated requirements and objectives. Provide the full content of issue #896 to assess compliance with its coding requirements and objectives.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Out of Scope Changes check ✅ Passed All changes appear directly related to establishing a complete macOS release workflow including signing, notarization, and DMG packaging, which aligns with the homebrew publishing objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lollipopkit/issue896

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
scripts/release/release-macos-dmg.sh (1)

6-6: Unused variable DEFAULT_ENV_FILE.

This variable is assigned but never referenced. It appears to be leftover from development.

🧹 Remove unused variable
 REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
-DEFAULT_ENV_FILE=""
 if [[ -n "${SERVERBOX_RELEASE_ENV_FILE:-}" ]]; then
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release/release-macos-dmg.sh` at line 6, The script defines an unused
variable DEFAULT_ENV_FILE="" which should be removed; delete the
DEFAULT_ENV_FILE assignment from release-macos-dmg.sh and verify there are no
remaining references to DEFAULT_ENV_FILE elsewhere in the script (remove them if
any) so the script contains only variables that are actually used.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/release/release-macos-dmg.sh`:
- Line 6: The script defines an unused variable DEFAULT_ENV_FILE="" which should
be removed; delete the DEFAULT_ENV_FILE assignment from release-macos-dmg.sh and
verify there are no remaining references to DEFAULT_ENV_FILE elsewhere in the
script (remove them if any) so the script contains only variables that are
actually used.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bbd43315-aeb4-4baa-af7f-bf1c9bfcfe46

📥 Commits

Reviewing files that changed from the base of the PR and between fc996bd and 314ce88.

📒 Files selected for processing (7)
  • .env.release.example
  • .gitignore
  • Makefile
  • README.md
  • README_zh.md
  • scripts/release/package-dmg-from-xcarchive.sh
  • scripts/release/release-macos-dmg.sh

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 23, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
scripts/release/release-macos-dmg.sh (1)

80-83: ⚠️ Potential issue | 🔴 Critical

Block recursive deletion of /tmp and /var/folders roots.

At Line [81], exact /tmp and /var/folders are still accepted, and at Line [195] that value can flow into safe_remove -rf. A misconfigured DMG_STAGING_PATH=/tmp can wipe the full temp root.

💡 Proposed fix
 validate_allowed_path() {
   local label="$1"
   local path="$2"
   local normalized
   normalized="$(normalize_abs_path "$path")"

   case "$normalized" in
-    "$REPO_ROOT/build" | "$REPO_ROOT/build/"* | /tmp | /tmp/* | /var/folders | /var/folders/*)
+    "$REPO_ROOT/build" | "$REPO_ROOT/build/"* | /tmp/* | /var/folders/*)
       printf '%s\n' "$normalized"
       ;;
+    /tmp | /var/folders)
+      echo "$label must be a subdirectory under /tmp or /var/folders: $normalized" >&2
+      exit 1
+      ;;
     *)
       echo "$label must be under $REPO_ROOT/build, /tmp, or /var/folders: $normalized" >&2
       exit 1
       ;;
   esac
 }

Also applies to: 193-195

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release/release-macos-dmg.sh` around lines 80 - 83, The case branch
that currently allows "$REPO_ROOT/build", "$REPO_ROOT/build/"* , /tmp and
/var/folders lets an exact /tmp or /var/folders value flow into safe_remove -rf;
change the validation so normalized (and any value derived from
DMG_STAGING_PATH) explicitly rejects the root temp directories by checking
normalized == "/tmp" or normalized == "/var/folders" (and their trailing-slash
variants) and returning an error instead of printing and continuing; ensure
safe_remove and any callers (e.g., the code path that uses DMG_STAGING_PATH)
never receive these exact roots by adding this explicit equality guard before
invoking safe_remove.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@scripts/release/release-macos-dmg.sh`:
- Around line 80-83: The case branch that currently allows "$REPO_ROOT/build",
"$REPO_ROOT/build/"* , /tmp and /var/folders lets an exact /tmp or /var/folders
value flow into safe_remove -rf; change the validation so normalized (and any
value derived from DMG_STAGING_PATH) explicitly rejects the root temp
directories by checking normalized == "/tmp" or normalized == "/var/folders"
(and their trailing-slash variants) and returning an error instead of printing
and continuing; ensure safe_remove and any callers (e.g., the code path that
uses DMG_STAGING_PATH) never receive these exact roots by adding this explicit
equality guard before invoking safe_remove.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: db4cc982-df18-4df1-b7ab-d12c3104c6c4

📥 Commits

Reviewing files that changed from the base of the PR and between 5d5dba8 and f0413e6.

📒 Files selected for processing (1)
  • scripts/release/release-macos-dmg.sh

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/release/release-macos-dmg.sh`:
- Around line 74-117: The validation functions (validate_allowed_path and
validate_path_within_base) currently compare raw normalized strings and can be
bypassed by symlinks; update them to canonicalize (resolve symlinks) for both
the candidate path and the base/allowed directories before performing the prefix
checks, e.g. call a realpath/readlink -f equivalent on "$path" and on
"$REPO_ROOT/build" (and any base passed into validate_path_within_base) or
explicitly detect and reject any path containing symlink components returned by
normalize_abs_path; ensure the prefix/case comparisons use these resolved values
(referencing normalize_abs_path, validate_allowed_path,
validate_path_within_base, and REPO_ROOT) and fail with an error if
canonicalization fails or any symlink is detected.
- Around line 198-215: The script doesn't create parent directories for
EXPORT_OPTIONS_PATH and OVERRIDE_XCCONFIG_PATH before writing to them, causing
"No such file or directory" when those are nested under BUILD_ROOT; add mkdir -p
"$(dirname "$EXPORT_OPTIONS_PATH")" and mkdir -p "$(dirname
"$OVERRIDE_XCCONFIG_PATH")" (or a single mkdir -p for both dirs) prior to using
/usr/libexec/PlistBuddy -c 'Clear dict' "$EXPORT_OPTIONS_PATH" and before the
cat >"$OVERRIDE_XCCONFIG_PATH" heredoc so the parent directories exist when
writing those files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a8cbc129-7bd0-4eb3-9000-ebe0aec507fa

📥 Commits

Reviewing files that changed from the base of the PR and between f0413e6 and a581b4a.

📒 Files selected for processing (1)
  • scripts/release/release-macos-dmg.sh

Comment thread scripts/release/release-macos-dmg.sh
Comment thread scripts/release/release-macos-dmg.sh Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/release/release-macos-dmg.sh (2)

335-339: Consider allowing custom release notes.

The release is created with empty notes. An optional RELEASE_NOTES environment variable would allow customization without modifying the script.

💡 Optional: Support custom release notes

At variable defaults section (~line 228), add:

RELEASE_NOTES="${RELEASE_NOTES:-}"

Then update the create command:

   gh release create "$RELEASE_TAG" \
     --repo "$APP_REPO_SLUG" \
     --title "$RELEASE_TITLE" \
-    --notes ""
+    --notes "$RELEASE_NOTES"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release/release-macos-dmg.sh` around lines 335 - 339, Add support for
optional custom release notes by introducing a RELEASE_NOTES environment
variable (e.g., set RELEASE_NOTES="${RELEASE_NOTES:-}") and then pass it into
the gh release create invocation instead of the empty string; update the gh
release create call that uses RELEASE_TAG, APP_REPO_SLUG and RELEASE_TITLE to
use --notes "$RELEASE_NOTES" so callers can supply custom notes via
RELEASE_NOTES.

322-327: Consider adding a timeout for notarization.

The notarytool submit --wait command waits indefinitely for Apple's servers. In rare cases, notarization can take an extended time or hang. Consider wrapping with a timeout for CI reliability.

💡 Optional: Add timeout wrapper
-xcrun notarytool submit "$DMG_PATH" \
-  --keychain-profile "$APPLE_NOTARY_KEYCHAIN_PROFILE" \
-  --wait
+NOTARIZATION_TIMEOUT="${NOTARIZATION_TIMEOUT:-3600}"
+if ! timeout "$NOTARIZATION_TIMEOUT" xcrun notarytool submit "$DMG_PATH" \
+  --keychain-profile "$APPLE_NOTARY_KEYCHAIN_PROFILE" \
+  --wait; then
+  echo "notarization timed out or failed after ${NOTARIZATION_TIMEOUT}s" >&2
+  exit 1
+fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/release/release-macos-dmg.sh` around lines 322 - 327, Wrap the xcrun
notarytool submit "$DMG_PATH" --keychain-profile
"$APPLE_NOTARY_KEYCHAIN_PROFILE" --wait call in a timeout so CI won't block
indefinitely: replace the bare call with a timeout wrapper (e.g. timeout or
gtimeout) that uses a configurable env var like NOTARIZE_TIMEOUT, check exit
code for timeout vs success, and fail the script with a clear message if the
timeout is reached; keep the subsequent xcrun stapler staple/validate steps
conditional on a successful notarization return.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@scripts/release/release-macos-dmg.sh`:
- Around line 335-339: Add support for optional custom release notes by
introducing a RELEASE_NOTES environment variable (e.g., set
RELEASE_NOTES="${RELEASE_NOTES:-}") and then pass it into the gh release create
invocation instead of the empty string; update the gh release create call that
uses RELEASE_TAG, APP_REPO_SLUG and RELEASE_TITLE to use --notes
"$RELEASE_NOTES" so callers can supply custom notes via RELEASE_NOTES.
- Around line 322-327: Wrap the xcrun notarytool submit "$DMG_PATH"
--keychain-profile "$APPLE_NOTARY_KEYCHAIN_PROFILE" --wait call in a timeout so
CI won't block indefinitely: replace the bare call with a timeout wrapper (e.g.
timeout or gtimeout) that uses a configurable env var like NOTARIZE_TIMEOUT,
check exit code for timeout vs success, and fail the script with a clear message
if the timeout is reached; keep the subsequent xcrun stapler staple/validate
steps conditional on a successful notarization return.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fe384001-7f38-43f5-b199-d55b4f1af0ba

📥 Commits

Reviewing files that changed from the base of the PR and between a581b4a and dd81561.

📒 Files selected for processing (1)
  • scripts/release/release-macos-dmg.sh

@lollipopkit lollipopkit merged commit 5443ef4 into main Apr 23, 2026
1 check passed
@lollipopkit lollipopkit deleted the lollipopkit/issue896 branch April 23, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

new: publish to homebrew

1 participant