ClashX #31
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| token: ${{ secrets.PAT_TOKEN || secrets.GITHUB_TOKEN }} | |
| - 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/') || needs.check-meta-update.outputs.has-update == 'true' | |
| 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/') || needs.check-meta-update.outputs.has-update == 'true' | |
| with: | |
| ref: sparkle | |
| path: 'sparkle-repo' | |
| - name: update sparkle-repo | |
| if: startsWith(github.ref, 'refs/tags/') || needs.check-meta-update.outputs.has-update == 'true' | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email 'github-actions[bot]@users.noreply.github.com' | |
| # 获取正确的tag名称 | |
| if [[ "${{ github.ref }}" == refs/tags/* ]]; then | |
| TAG_NAME="${{ github.ref_name }}" | |
| else | |
| TAG_NAME=$(git tag -l "v*" --sort=-version:refname | head -1) | |
| fi | |
| rm -f sparkle-repo/*.delta | |
| cp "ClashX Meta.zip" "sparkle-repo/ClashX Meta ${TAG_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 - ${TAG_NAME}" | |
| git branch -D sparkle | |
| git checkout -b sparkle | |
| git branch -D temp-sparkle | |
| git push --force-with-lease origin sparkle | |
| - name: Get release tag name | |
| id: release-tag | |
| if: startsWith(github.ref, 'refs/tags/') || needs.check-meta-update.outputs.has-update == 'true' | |
| run: | | |
| if [[ "${{ github.ref }}" == refs/tags/* ]]; then | |
| # 手动打tag触发:直接使用github.ref | |
| echo "tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT | |
| else | |
| # 定时任务触发:获取最新创建的tag | |
| LATEST_TAG=$(git tag -l "v*" --sort=-version:refname | head -1) | |
| echo "tag=${LATEST_TAG}" >> $GITHUB_OUTPUT | |
| fi | |
| - name: upload build to github | |
| uses: softprops/action-gh-release@v2 | |
| if: startsWith(github.ref, 'refs/tags/') || needs.check-meta-update.outputs.has-update == 'true' | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ steps.release-tag.outputs.tag }} | |
| generate_release_notes: true | |
| files: | | |
| ClashX Meta.zip | |