Skip to content

Commit 5443ef4

Browse files
authored
new: publish to homebrew (#1135)
* new: publish to homebrew Fixes #896 * fix * fix * fix * fix * fix * fix
1 parent fc996bd commit 5443ef4

7 files changed

Lines changed: 603 additions & 0 deletions

File tree

.env.release.example

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
APPLE_TEAM_ID="TEAMID1234"
2+
APPLE_NOTARY_KEYCHAIN_PROFILE="serverbox-notary"
3+
SIGNING_IDENTITY="Developer ID Application"
4+
APP_PROFILE_NAME="ServerBox DMG Profile"
5+
6+
# Optional overrides
7+
# SERVERBOX_RELEASE_ENV_FILE="/abs/path/to/.env.release"
8+
# MARKETING_VERSION_OVERRIDE="1.0.1365"
9+
# CURRENT_PROJECT_VERSION_OVERRIDE="1365"
10+
# APP_NAME="Server Box"
11+
# APP_ASSET_NAME="ServerBox"
12+
# APP_BUNDLE_ID="com.lollipopkit.toolbox"
13+
# VOLUME_NAME="ServerBox"
14+
# APP_REPO_SLUG="lollipopkit/flutter_server_box"
15+
# PUBLISH_GITHUB_RELEASE="1"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,5 @@ untranlated.json
6767
more_build_data.json
6868
trans.txt
6969
android/app/.cxx
70+
.env.release
71+
.env

Makefile

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
SHELL := /bin/bash
2+
3+
.DEFAULT_GOAL := help
4+
5+
FLUTTER ?= flutter
6+
DART ?= dart
7+
DEVICE ?=
8+
TEST ?=
9+
PLATFORM ?=
10+
ENV_FILE ?=
11+
XCARCHIVE_PATH ?=
12+
APP_PATH ?=
13+
14+
.PHONY: help deps pub-get run run-device analyze test test-one coverage \
15+
gen gen-build gen-build-clean gen-l10n build build-android build-ios \
16+
build-macos build-linux build-windows clean release-macos-dmg package-dmg
17+
18+
help:
19+
@printf '%s\n' \
20+
'Usage: make <target> [VAR=value]' \
21+
'' \
22+
'Common targets:' \
23+
' deps Install Dart/Flutter dependencies' \
24+
' run Run app on default device' \
25+
' run-device Run app on a specific device: make run-device DEVICE=<id>' \
26+
' analyze Run static analysis for lib/ and test/' \
27+
' test Run all tests' \
28+
' test-one Run a single test: make test-one TEST=test/foo_test.dart' \
29+
' coverage Run tests with coverage output' \
30+
'' \
31+
'Code generation:' \
32+
' gen Run build_runner and gen-l10n' \
33+
' gen-build Run build_runner build --delete-conflicting-outputs' \
34+
' gen-build-clean Run build_runner build with --clean' \
35+
' gen-l10n Regenerate localization files' \
36+
'' \
37+
'Build targets:' \
38+
' build Build via fl_build: make build PLATFORM=<android|ios|macos|linux|windows>' \
39+
' build-android Build Android package' \
40+
' build-ios Build iOS package' \
41+
' build-macos Build macOS package' \
42+
' build-linux Build Linux package' \
43+
' build-windows Build Windows package' \
44+
' clean Run flutter clean' \
45+
'' \
46+
'Release scripts:' \
47+
' release-macos-dmg Run scripts/release/release-macos-dmg.sh' \
48+
' Optional: make release-macos-dmg ENV_FILE=.env.release' \
49+
' package-dmg Run scripts/release/package-dmg-from-xcarchive.sh' \
50+
' Example: make package-dmg APP_PATH="/path/Server Box.app"' \
51+
' Example: make package-dmg XCARCHIVE_PATH=/path/Runner.xcarchive'
52+
53+
deps pub-get:
54+
$(FLUTTER) pub get
55+
56+
run:
57+
$(FLUTTER) run
58+
59+
run-device:
60+
@if [ -z "$(DEVICE)" ]; then \
61+
echo 'DEVICE is required. Example: make run-device DEVICE=<id>'; \
62+
exit 1; \
63+
fi
64+
$(FLUTTER) run -d $(DEVICE)
65+
66+
analyze:
67+
$(FLUTTER) analyze lib test
68+
69+
test:
70+
$(FLUTTER) test
71+
72+
test-one:
73+
@if [ -z "$(TEST)" ]; then \
74+
echo 'TEST is required. Example: make test-one TEST=test/cpu_test.dart'; \
75+
exit 1; \
76+
fi
77+
$(FLUTTER) test $(TEST)
78+
79+
coverage:
80+
$(FLUTTER) test --coverage
81+
82+
gen: gen-build gen-l10n
83+
84+
gen-build:
85+
$(DART) run build_runner build --delete-conflicting-outputs
86+
87+
gen-build-clean:
88+
$(DART) run build_runner build --delete-conflicting-outputs --clean
89+
90+
gen-l10n:
91+
$(FLUTTER) gen-l10n
92+
93+
build:
94+
@if [ -z "$(PLATFORM)" ]; then \
95+
echo 'PLATFORM is required. Example: make build PLATFORM=android'; \
96+
exit 1; \
97+
fi
98+
$(DART) run fl_build -p $(PLATFORM)
99+
100+
build-android:
101+
$(DART) run fl_build -p android
102+
103+
build-ios:
104+
$(DART) run fl_build -p ios
105+
106+
build-macos:
107+
$(DART) run fl_build -p macos
108+
109+
build-linux:
110+
$(DART) run fl_build -p linux
111+
112+
build-windows:
113+
$(DART) run fl_build -p windows
114+
115+
clean:
116+
$(FLUTTER) clean
117+
118+
release-macos-dmg:
119+
@if [ -n "$(ENV_FILE)" ]; then \
120+
SERVERBOX_RELEASE_ENV_FILE="$(ENV_FILE)" bash scripts/release/release-macos-dmg.sh; \
121+
else \
122+
bash scripts/release/release-macos-dmg.sh; \
123+
fi
124+
125+
package-dmg:
126+
@if [ -z "$(APP_PATH)" ] && [ -z "$(XCARCHIVE_PATH)" ]; then \
127+
echo 'APP_PATH or XCARCHIVE_PATH is required.'; \
128+
echo 'Example: make package-dmg APP_PATH="/path/Server Box.app"'; \
129+
echo 'Example: make package-dmg XCARCHIVE_PATH=/path/Runner.xcarchive'; \
130+
exit 1; \
131+
fi
132+
@if [ -n "$(APP_PATH)" ]; then \
133+
APP_PATH="$(APP_PATH)" bash scripts/release/package-dmg-from-xcarchive.sh; \
134+
else \
135+
XCARCHIVE_PATH="$(XCARCHIVE_PATH)" bash scripts/release/package-dmg-from-xcarchive.sh; \
136+
fi

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ If I forgot to add your name to the contributors list, please add a comment in t
7373
2. Clone this repo, run `flutter run` to start the app.
7474
3. Run `dart run fl_build -p PLATFORM` to build the app.
7575

76+
### Release macOS notarized DMG
77+
78+
1. Copy `.env.release.example` to `.env.release`.
79+
2. Fill in `APPLE_TEAM_ID` and `APPLE_NOTARY_KEYCHAIN_PROFILE`.
80+
3. Make sure the `Developer ID Application` certificate is already installed in Keychain.
81+
4. Make sure notarization credentials are already stored via `xcrun notarytool store-credentials`.
82+
5. Install the provisioning profile used for DMG packaging. The script defaults to `ServerBox DMG Profile`, and you can override it with `APP_PROFILE_NAME`.
83+
6. Run `bash scripts/release/release-macos-dmg.sh`.
84+
85+
This flow does not modify the default Xcode Release signing config. It injects a temporary `xcconfig` only for archive/export, builds a signed `.app`, packages a DMG, submits it to notarization, staples the result, and optionally uploads the DMG to the GitHub Release for `v<version>`.
86+
7687
### Translation
7788

7889
- [Guide](https://blog.lpkt.cn/posts/faq/) can be found in my blog.

README_zh.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ Linux / Windows | [GitHub](https://github.com/lollipopkit/flutter_server_box/rel
7575
2. 克隆这个仓库, 运行 `flutter run` 启动应用
7676
3. 运行 `dart run fl_build -p PLATFORM` 构建应用
7777

78+
### 发布 macOS 公证 DMG
79+
80+
1. 复制 `.env.release.example``.env.release`
81+
2. 填入 `APPLE_TEAM_ID``APPLE_NOTARY_KEYCHAIN_PROFILE`
82+
3. 确保 `Developer ID Application` 证书已经安装到 Keychain
83+
4. 确保已经通过 `xcrun notarytool store-credentials` 存好了公证凭据
84+
5. 安装用于 DMG 打包的 provisioning profile。脚本默认使用 `ServerBox DMG Profile`,也可以通过 `APP_PROFILE_NAME` 覆盖
85+
6. 运行 `bash scripts/release/release-macos-dmg.sh`
86+
87+
这套流程不会修改工程默认的 Xcode Release 签名配置。脚本只会在归档和导出时注入临时 `xcconfig`,生成已签名 `.app`、打包 DMG、提交公证、回填 stapler,并可选把 DMG 上传到 `v<version>` 对应的 GitHub Release。
88+
7889
### 翻译
7990

8091
[指南](https://blog.lpkt.cn/faq/) 可在我的博客中找到。
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
6+
7+
APP_NAME="${APP_NAME:-Server Box}"
8+
APP_ASSET_NAME="${APP_ASSET_NAME:-ServerBox}"
9+
VOLUME_NAME="${VOLUME_NAME:-ServerBox}"
10+
XCARCHIVE_PATH="${1:-${XCARCHIVE_PATH:-}}"
11+
APP_PATH="${APP_PATH:-}"
12+
ARTIFACTS_PATH="${ARTIFACTS_PATH:-$REPO_ROOT/build/artifacts}"
13+
DMG_STAGING_PATH="${DMG_STAGING_PATH:-$REPO_ROOT/build/dmg-root}"
14+
REQUIRE_SPCTL="${REQUIRE_SPCTL:-0}"
15+
16+
if [[ -z "$APP_PATH" && -z "$XCARCHIVE_PATH" ]]; then
17+
echo "APP_PATH or XCARCHIVE_PATH is required" >&2
18+
echo "Usage: APP_PATH=/abs/path/to/Server Box.app $0" >&2
19+
echo " or: XCARCHIVE_PATH=/abs/path/to/Runner.xcarchive $0" >&2
20+
exit 1
21+
fi
22+
23+
if [[ -z "$APP_PATH" ]]; then
24+
if [[ ! -d "$XCARCHIVE_PATH" ]]; then
25+
echo "xcarchive not found: $XCARCHIVE_PATH" >&2
26+
exit 1
27+
fi
28+
APP_PATH="$XCARCHIVE_PATH/Products/Applications/${APP_NAME}.app"
29+
fi
30+
31+
if [[ ! -d "$APP_PATH" ]]; then
32+
echo "app bundle not found: $APP_PATH" >&2
33+
exit 1
34+
fi
35+
36+
INFO_PLIST="$APP_PATH/Contents/Info.plist"
37+
if [[ ! -f "$INFO_PLIST" ]]; then
38+
echo "Info.plist not found: $INFO_PLIST" >&2
39+
exit 1
40+
fi
41+
42+
APP_VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$INFO_PLIST")"
43+
APP_BUILD="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$INFO_PLIST")"
44+
DMG_BASENAME="${DMG_BASENAME:-${APP_ASSET_NAME}-${APP_VERSION}-${APP_BUILD}}"
45+
DMG_PATH="${DMG_PATH:-$ARTIFACTS_PATH/${DMG_BASENAME}.dmg}"
46+
47+
mkdir -p "$ARTIFACTS_PATH"
48+
rm -rf "$DMG_STAGING_PATH"
49+
mkdir -p "$DMG_STAGING_PATH"
50+
51+
codesign --verify --deep --strict --verbose=2 "$APP_PATH"
52+
53+
if ! spctl -a -t exec -vv "$APP_PATH"; then
54+
if [[ "$REQUIRE_SPCTL" == "1" ]]; then
55+
echo "spctl assessment failed for $APP_PATH" >&2
56+
exit 1
57+
fi
58+
59+
echo "warning: spctl assessment failed for $APP_PATH; continuing because REQUIRE_SPCTL=0" >&2
60+
fi
61+
62+
ditto "$APP_PATH" "$DMG_STAGING_PATH/${APP_NAME}.app"
63+
ln -s /Applications "$DMG_STAGING_PATH/Applications"
64+
65+
rm -f "$DMG_PATH"
66+
hdiutil create \
67+
-volname "$VOLUME_NAME" \
68+
-srcfolder "$DMG_STAGING_PATH" \
69+
-ov \
70+
-format UDZO \
71+
"$DMG_PATH"
72+
73+
echo "Created DMG at $DMG_PATH"
74+
echo "Version: $APP_VERSION ($APP_BUILD)"

0 commit comments

Comments
 (0)