Skip to content

ClashX

ClashX #19

Workflow file for this run

name: ClashX
on:
push:
tags: [ v* ]
workflow_dispatch:
inputs:
logLevel:
schedule:
- cron: '0 0 * * *' # 每天午夜检查一次
jobs:
check-meta-update:
runs-on: ubuntu-latest
# 只在定时任务和手动触发时运行检查
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
outputs:
has-update: ${{ steps.check.outputs.has-update }}
latest-tag: ${{ steps.check.outputs.latest-tag }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check MetaCubeX/mihomo updates
id: check
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# 获取MetaCubeX/mihomo的最新release版本
LATEST_TAG=$(curl -s https://api.github.com/repos/MetaCubeX/mihomo/releases/latest | jq -r '.tag_name')
echo "Latest MetaCubeX/mihomo version: ${LATEST_TAG}"
# 从版本文件中读取当前使用的 mihomo 版本
if [ -f ".mihomo-version" ]; then
CURRENT_VERSION=$(cat .mihomo-version | tr -d '\n\r' || echo "")
else
# 尝试从最新的 tag message 中读取(兼容旧版本)
LAST_TAG=$(git tag -l "v*" --sort=-version:refname | head -1)
if [ -n "$LAST_TAG" ]; then
CURRENT_VERSION=$(git tag -l "$LAST_TAG" --format='%(contents)' | grep -oP 'MetaCubeX/mihomo \K.*' || echo "")
else
CURRENT_VERSION=""
fi
fi
echo "Current mihomo version: ${CURRENT_VERSION}"
# 比较版本,如果不同则创建新tag
if [ -z "${CURRENT_VERSION}" ]; then
echo "No current version found, will create initial tag"
SHOULD_UPDATE=true
elif [ "${LATEST_TAG}" != "${CURRENT_VERSION}" ]; then
echo "Found new version: ${LATEST_TAG} (current: ${CURRENT_VERSION})"
SHOULD_UPDATE=true
else
echo "Already on latest version: ${CURRENT_VERSION}"
SHOULD_UPDATE=false
fi
# 输出检测结果
echo "has-update=${SHOULD_UPDATE}" >> $GITHUB_OUTPUT
echo "latest-tag=${LATEST_TAG}" >> $GITHUB_OUTPUT
# 如果需要更新,创建新tag
if [ "${SHOULD_UPDATE}" = true ]; then
git config --global user.name "github-actions[bot]"
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
# 获取最后一个版本号
LAST_TAG=$(git tag -l "v*" --sort=-version:refname | head -1)
if [ -z "$LAST_TAG" ]; then
NEW_VERSION="v1.0.0"
else
LAST_VERSION=$(echo $LAST_TAG | sed 's/v//')
# 生成新版本号(增加patch版本)
if [[ $LAST_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then
MAJOR=${BASH_REMATCH[1]}
MINOR=${BASH_REMATCH[2]}
PATCH=${BASH_REMATCH[3]}
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="v${MAJOR}.${MINOR}.${NEW_PATCH}"
else
NEW_VERSION="v1.0.0"
fi
fi
# 创建tag并推送(这会触发tag push事件)
git tag -a "${NEW_VERSION}" -m "Auto update: MetaCubeX/mihomo ${LATEST_TAG}"
git push origin "${NEW_VERSION}"
echo "Created and pushed new tag: ${NEW_VERSION}"
else
echo "No update needed, skipping tag creation"
fi
build:
runs-on: macos-26
needs: [check-meta-update]
# 只在以下情况构建:1) tag push触发 2) 手动触发 3) 定时任务检测到新版本
if: |
always() && (
startsWith(github.ref, 'refs/tags/v') ||
(github.event_name == 'workflow_dispatch') ||
(needs.check-meta-update.result == 'success' && needs.check-meta-update.outputs.has-update == 'true')
)
steps:
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get latest MetaCubeX/mihomo tag
id: get-tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# 如果是从 check-meta-update 传过来的,直接使用
if [ -n "${{ needs.check-meta-update.outputs.latest-tag }}" ]; then
LATEST_TAG="${{ needs.check-meta-update.outputs.latest-tag }}"
echo "latest-tag=${LATEST_TAG}" >> $GITHUB_OUTPUT
echo "Using tag from check job: ${LATEST_TAG}"
else
# 使用 GitHub CLI 获取最新 tag(更可靠)
LATEST_TAG=$(gh release view --repo MetaCubeX/mihomo --json tagName --jq '.tagName')
echo "latest-tag=${LATEST_TAG}" >> $GITHUB_OUTPUT
echo "Latest tag: ${LATEST_TAG}"
# 备用方案:使用 curl + jq
if [ -z "$LATEST_TAG" ]; then
echo "Trying backup method with curl..."
LATEST_TAG=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
https://api.github.com/repos/MetaCubeX/mihomo/releases/latest | \
jq -r '.tag_name')
echo "latest-tag=${LATEST_TAG}" >> $GITHUB_OUTPUT
echo "Latest tag (backup): ${LATEST_TAG}"
fi
fi
- name: download meta core
uses: robinraju/[email protected]
with:
repository: 'MetaCubeX/mihomo'
tag: ${{ steps.get-tag.outputs.latest-tag }}
fileName: "mihomo-darwin-???64-v?.*.*.gz"
out-file-path: "clash.meta"
token: ${{ secrets.GITHUB_TOKEN }}
- name: build infos
run: |
/usr/libexec/PlistBuddy -c "Set CFBundleVersion $(git rev-list --count origin/master..origin/meta)" ClashX/Info.plist
/usr/libexec/PlistBuddy -c "Set CFBundleShortVersionString $(git describe --tags --abbrev=0)" ClashX/Info.plist
/usr/libexec/PlistBuddy -c "Add coreVersion string $(ls clash.meta | grep -m1 "" | sed -ne 's/.*64-\(.*\).gz/\1/p')" ClashX/Info.plist
/usr/libexec/PlistBuddy -c "Add gitBranch string $GITHUB_REF_NAME" ClashX/Info.plist
/usr/libexec/PlistBuddy -c "Add gitCommit string ${GITHUB_SHA::7}" ClashX/Info.plist
/usr/libexec/PlistBuddy -c "Add buildTime string $(date +%Y-%m-%d\ %H:%M)" ClashX/Info.plist
/usr/libexec/PlistBuddy -c 'Print CFBundleVersion' ClashX/Info.plist
/usr/libexec/PlistBuddy -c 'Print CFBundleShortVersionString' ClashX/Info.plist
/usr/libexec/PlistBuddy -c 'Print coreVersion' ClashX/Info.plist
/usr/libexec/PlistBuddy -c 'Print gitBranch' ClashX/Info.plist
/usr/libexec/PlistBuddy -c 'Print gitCommit' ClashX/Info.plist
/usr/libexec/PlistBuddy -c 'Print buildTime' ClashX/Info.plist
- name: install deps
run: |
bash install_dependency.sh
xcodebuild -resolvePackageDependencies -project ClashX.xcodeproj
- name: build
run: |
xcodebuild archive -project ClashX.xcodeproj -scheme ClashX\ Meta -archivePath archive/ClashX.xcarchive -showBuildTimingSummary -allowProvisioningUpdates
- name: create zip
run: ditto -c -k --sequesterRsrc --keepParent archive/ClashX.xcarchive/Products/Applications/ClashX\ Meta.app "ClashX Meta.zip"
- name: Update mihomo version file
if: startsWith(github.ref, 'refs/tags/')
run: |
# 将当前使用的 mihomo 版本写入文件
echo "${{ steps.get-tag.outputs.latest-tag }}" > .mihomo-version
git config --global user.name "github-actions[bot]"
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
# 提交版本文件到仓库
git add .mihomo-version
if ! git diff --cached --quiet; then
git commit -m "Update mihomo version to ${{ steps.get-tag.outputs.latest-tag }}"
git push origin HEAD:meta || git push origin HEAD:main || echo "Failed to push version file, but continuing..."
fi
- name: upload Artifact
uses: actions/upload-artifact@v4
if: "!startsWith(github.ref, 'refs/tags/')"
with:
name: "ClashX Meta.zip"
path: "*.zip"
- name: load sparkle-repo
uses: actions/checkout@v4
if: startsWith(github.ref, 'refs/tags/')
with:
ref: sparkle
path: 'sparkle-repo'
- name: update sparkle-repo
if: startsWith(github.ref, 'refs/tags/')
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
rm -f sparkle-repo/*.delta
cp "ClashX Meta.zip" "sparkle-repo/ClashX Meta $GITHUB_REF_NAME.zip"
brew install sparkle
echo '${{ secrets.ED_KEY }}' | $(brew --prefix)/Caskroom/sparkle/2.*/bin/generate_appcast sparkle-repo --maximum-deltas 2 --auto-prune-update-files --ed-key-file -
cd sparkle-repo
rm -rf old_updates
git checkout --orphan temp-sparkle
git add -A
git commit -m "Sparkle updates - $GITHUB_REF_NAME"
git branch -D sparkle
git checkout -b sparkle
git branch -D temp-sparkle
git push --force-with-lease origin sparkle
- name: upload build to github
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
generate_release_notes: true
files: |
ClashX Meta.zip