Skip to content

release(v2.2.2): 冷启动窗口前置 / FindBar 反向查找 / 标准菜单本地化 #42

release(v2.2.2): 冷启动窗口前置 / FindBar 反向查找 / 标准菜单本地化

release(v2.2.2): 冷启动窗口前置 / FindBar 反向查找 / 标准菜单本地化 #42

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version (e.g. v1.0.0)'
required: true
type: string
use_ci_build:
description: 'Use CI build instead of local build upload (NOT recommended: CI builds have invisible text bug)'
required: false
type: boolean
default: false
env:
SCHEME: MarkdownReader
PRODUCT_NAME: MarkdownReader
BUNDLE_ID: com.markdownreader.app
permissions:
contents: write
jobs:
# 默认模式:CI 仅创建 draft release 占位,等待本地 release-local.sh 上传产物
# 推送 tag 后执行: ./release-local.sh 构建并上传,然后 gh release edit --draft=false 发布
create-release:
name: Create Release (await local upload)
if: ${{ !inputs.use_ci_build }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Determine version
id: version
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
TAG="${{ inputs.version }}"
else
TAG="${{ github.ref_name }}"
fi
VERSION="${TAG#v}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Validate CHANGELOG
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
if [ ! -f CHANGELOG.md ]; then
echo "❌ CHANGELOG.md not found!"
exit 1
fi
if ! grep -q "\\[$VERSION\\]" CHANGELOG.md && ! grep -q "\\[$TAG\\]" CHANGELOG.md; then
echo "❌ CHANGELOG.md does not contain version $VERSION or $TAG"
exit 1
fi
echo "✅ CHANGELOG.md validated for version $VERSION"
- name: Create draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ steps.version.outputs.tag }}"
VERSION="${{ steps.version.outputs.version }}"
cat > /tmp/release-body.md << 'BODY'
## 安装说明
1. 下载 `.dmg` 文件,双击打开
2. 将 **Markdown Reader** 拖入 **Applications** 文件夹
3. 首次打开时,macOS 可能提示「无法验证开发者」:
- 打开 **系统设置 > 隐私与安全性**
- 找到被阻止的 app,点击 **仍要打开**
- 或在终端运行:`xattr -cr /Applications/MarkdownReader.app`
4. 也可以直接右键点击 app → 选择 **打开**
---
BODY
if [ -f "docs/releases/release-notes-${TAG}.md" ]; then
cat "docs/releases/release-notes-${TAG}.md" >> /tmp/release-body.md
elif [ -f "CHANGELOG.md" ]; then
awk -v ver="$VERSION" '
/^## \[/ && section { exit }
/^## \[/ && $0 ~ "\\[" ver "\\]" { section = 1 }
section { print }
' CHANGELOG.md >> /tmp/release-body.md
fi
gh release create "$TAG" \
--title "$TAG" \
--draft \
--notes-file /tmp/release-body.md
echo "✅ Draft release $TAG created"
echo " 上传本地构建: ./release-local.sh $VERSION"
echo " 发布: gh release edit $TAG --draft=false"
# CI 构建作为后备(已知问题:CI 构建的编辑模式文字可能不可见)
ci-build:
name: Build & Release (CI fallback)
if: ${{ inputs.use_ci_build }}
runs-on: macos-15
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Determine version
id: version
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
TAG="${{ inputs.version }}"
else
TAG="${{ github.ref_name }}"
fi
VERSION="${TAG#v}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Validate CHANGELOG
run: |
VERSION="${{ steps.version.outputs.version }}"
TAG="${{ steps.version.outputs.tag }}"
if [ ! -f CHANGELOG.md ]; then
echo "❌ CHANGELOG.md not found!"
exit 1
fi
if ! grep -q "\\[$VERSION\\]" CHANGELOG.md && ! grep -q "\\[$TAG\\]" CHANGELOG.md; then
echo "❌ CHANGELOG.md does not contain version $VERSION or $TAG"
exit 1
fi
echo "✅ CHANGELOG.md validated for version $VERSION"
- name: Install create-dmg
run: brew install create-dmg
- name: Build
run: swift build -c release --arch arm64
- name: Patch Bundle.module resource paths
run: |
PATCHED=0
while IFS= read -r accessor; do
if grep -q 'Bundle\.main\.bundleURL\.appendingPathComponent' "$accessor"; then
sed -i '' 's/Bundle\.main\.bundleURL\.appendingPathComponent/(Bundle.main.resourceURL ?? Bundle.main.bundleURL).appendingPathComponent/g' "$accessor"
PATCHED=$((PATCHED + 1))
echo "📝 Patched Bundle.module path: $accessor"
fi
done < <(find .build -name "resource_bundle_accessor.swift" -type f)
if [[ "$PATCHED" -gt 0 ]]; then
echo "🔨 Rebuilding with patched Bundle.module paths..."
swift build -c release --arch arm64
else
echo "✅ No patches needed (accessors already use resourceURL)"
fi
- name: Assemble .app bundle
run: |
VERSION="${{ steps.version.outputs.version }}"
APP_DIR="${{ env.PRODUCT_NAME }}.app"
RESOURCES_DIR="$APP_DIR/Contents/Resources"
MACOS_DIR="$APP_DIR/Contents/MacOS"
mkdir -p "$MACOS_DIR"
mkdir -p "$RESOURCES_DIR"
BUILD_DIR=".build/arm64-apple-macosx/release"
cp "$BUILD_DIR/${{ env.PRODUCT_NAME }}" "$MACOS_DIR/"
sed "s/__VERSION__/$VERSION/g" scripts/Info.plist > "$APP_DIR/Contents/Info.plist"
RESOURCE_BUNDLE="$BUILD_DIR/${{ env.PRODUCT_NAME }}_MarkdownReader.bundle"
if [ -d "$RESOURCE_BUNDLE" ]; then
cp -R "$RESOURCE_BUNDLE/" "$RESOURCES_DIR/"
echo "✅ Copied SPM resource bundle"
fi
for bundle in "$BUILD_DIR"/*.bundle; do
bundle_name=$(basename "$bundle")
if [[ "$bundle_name" != "${{ env.PRODUCT_NAME }}_MarkdownReader.bundle" ]]; then
cp -R "$bundle" "$RESOURCES_DIR/"
echo "📦 Copied dependency bundle: $bundle_name"
fi
done
echo "📦 Compiling Assets.xcassets with actool..."
actool \
--compile "$RESOURCES_DIR" \
--platform macosx \
--minimum-deployment-target 26 \
--app-icon AppIcon \
--output-format human-readable-text \
--output-partial-info-plist /tmp/partial.plist \
"Sources/${{ env.PRODUCT_NAME }}/Assets.xcassets"
echo -n "APPL????" > "$APP_DIR/Contents/PkgInfo"
echo "✅ .app bundle assembled"
- name: Code sign .app
run: |
# 不使用 --deep(Apple 已弃用),分别签名 bundle 和主 app
find "${{ env.PRODUCT_NAME }}.app/Contents/Resources" -name "*.bundle" -exec codesign --force --sign - {} \; 2>/dev/null || true
codesign --force --sign - "${{ env.PRODUCT_NAME }}.app"
echo "✅ App signed (ad-hoc)"
- name: Create DMG
run: |
VERSION="${{ steps.version.outputs.version }}"
DMG_NAME="${{ env.PRODUCT_NAME }}-$VERSION.dmg"
rm -f "$DMG_NAME"
create-dmg \
--volname "${{ env.PRODUCT_NAME }} $VERSION" \
--volicon "${{ env.PRODUCT_NAME }}.app/Contents/Resources/AppIcon.icns" \
--window-pos 200 120 \
--window-size 600 400 \
--icon-size 100 \
--icon "${{ env.PRODUCT_NAME }}.app" 175 190 \
--app-drop-link 425 190 \
"$DMG_NAME" \
"${{ env.PRODUCT_NAME }}.app"
VOLICON="${{ env.PRODUCT_NAME }}.app/Contents/Resources/AppIcon.icns"
if [ -f "$VOLICON" ]; then
swiftc scripts/seticon.swift -o /tmp/seticon
/tmp/seticon "$VOLICON" "$DMG_NAME"
fi
echo "dmg_name=$DMG_NAME" >> "$GITHUB_ENV"
- name: Create ZIP
run: |
VERSION="${{ steps.version.outputs.version }}"
ZIP_NAME="${{ env.PRODUCT_NAME }}-$VERSION.zip"
zip -r "$ZIP_NAME" "${{ env.PRODUCT_NAME }}.app"
echo "zip_name=$ZIP_NAME" >> "$GITHUB_ENV"
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${{ steps.version.outputs.tag }}"
VERSION="${{ steps.version.outputs.version }}"
DMG_NAME="${{ env.PRODUCT_NAME }}-$VERSION.dmg"
ZIP_NAME="${{ env.PRODUCT_NAME }}-$VERSION.zip"
cat > /tmp/release-body.md << 'BODY'
## 安装说明
1. 下载 `.dmg` 文件,双击打开
2. 将 **Markdown Reader** 拖入 **Applications** 文件夹
3. 首次打开时,macOS 可能提示「无法验证开发者」:
- 打开 **系统设置 > 隐私与安全性**
- 找到被阻止的 app,点击 **仍要打开**
- 或在终端运行:`xattr -cr /Applications/MarkdownReader.app`
4. 也可以直接右键点击 app → 选择 **打开**
---
BODY
if [ -f "docs/releases/release-notes-${TAG}.md" ]; then
cat "docs/releases/release-notes-${TAG}.md" >> /tmp/release-body.md
elif [ -f "CHANGELOG.md" ]; then
awk -v ver="$VERSION" '
/^## \[/ && section { exit }
/^## \[/ && $0 ~ "\\[" ver "\\]" { section = 1 }
section { print }
' CHANGELOG.md >> /tmp/release-body.md
fi
gh release create "$TAG" \
--title "$TAG" \
--notes-file /tmp/release-body.md \
"$DMG_NAME" \
"$ZIP_NAME"
echo "✅ GitHub Release $TAG created"