From 513b4cf6b252bf8dc4c2f58a4ed65e9189d94152 Mon Sep 17 00:00:00 2001 From: Tunglies <77394545+Tunglies@users.noreply.github.com> Date: Mon, 18 May 2026 21:46:43 +0800 Subject: [PATCH] chore: automate mihomo changelog sync --- .github/workflows/sync-mihomo-changelog.yml | 78 +++++++++++++++ Changelog.md | 2 +- scripts/sync-mihomo-version.mjs | 104 ++++++++++++++++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/sync-mihomo-changelog.yml create mode 100644 scripts/sync-mihomo-version.mjs diff --git a/.github/workflows/sync-mihomo-changelog.yml b/.github/workflows/sync-mihomo-changelog.yml new file mode 100644 index 000000000..dd8dac468 --- /dev/null +++ b/.github/workflows/sync-mihomo-changelog.yml @@ -0,0 +1,78 @@ +name: Sync Mihomo Changelog + +on: + workflow_dispatch: + schedule: + # UTC+8 Monday 11:30 + - cron: '30 3 * * 1' + +permissions: + contents: write + pull-requests: write + +concurrency: + group: sync-mihomo-changelog + cancel-in-progress: false + +jobs: + sync: + name: Sync Changelog + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + ref: ${{ github.event.repository.default_branch }} + + - name: Install Node + uses: actions/setup-node@v6 + with: + node-version: '24.15.0' + + - name: Sync Mihomo version + run: node scripts/sync-mihomo-version.mjs + + - name: Detect changelog changes + id: changes + run: | + if git diff --quiet -- Changelog.md; then + echo "changed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + + mihomo_version="$(grep -Eo 'Mihomo\(Meta\).*v[0-9]+(\.[0-9]+)+' Changelog.md | grep -Eo 'v[0-9]+(\.[0-9]+)+' | head -n 1)" + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "mihomo_version=$mihomo_version" >> "$GITHUB_OUTPUT" + + - name: Open pull request + if: steps.changes.outputs.changed == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BASE_BRANCH: ${{ github.event.repository.default_branch }} + MIHOMO_VERSION: ${{ steps.changes.outputs.mihomo_version }} + run: | + branch="chore/sync-mihomo-changelog" + title="chore: sync Mihomo changelog to ${MIHOMO_VERSION}" + body="Automated update for the Mihomo core version recorded in Changelog.md." + + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git fetch origin "$branch:refs/remotes/origin/$branch" || true + git checkout -B "$branch" + git add Changelog.md + git commit -m "$title" + git push --force-with-lease origin "$branch" + + if gh pr view "$branch" --repo "$GITHUB_REPOSITORY" > /dev/null 2>&1; then + gh pr edit "$branch" \ + --repo "$GITHUB_REPOSITORY" \ + --title "$title" \ + --body "$body" + else + gh pr create \ + --repo "$GITHUB_REPOSITORY" \ + --base "$BASE_BRANCH" \ + --head "$branch" \ + --title "$title" \ + --body "$body" + fi diff --git a/Changelog.md b/Changelog.md index cc8db4f23..ac615ad18 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,7 +3,7 @@ > [!IMPORTANT] > 关于版本的说明:Clash Verge 版本号遵循 x.y.z:x 为重大架构变更,y 为功能新增,z 为 Bug 修复。 -- **Mihomo(Meta) 内核升级至 v1.19.24** +- **Mihomo(Meta) 内核升级至 v1.19.4** ### 🐞 修复问题 diff --git a/scripts/sync-mihomo-version.mjs b/scripts/sync-mihomo-version.mjs new file mode 100644 index 000000000..5ccfcfa70 --- /dev/null +++ b/scripts/sync-mihomo-version.mjs @@ -0,0 +1,104 @@ +import fs from 'node:fs' +import fsp from 'node:fs/promises' +import path from 'node:path' + +const VERSION_URL = + 'https://github.com/MetaCubeX/mihomo/releases/latest/download/version.txt' +const DEFAULT_CHANGELOG = 'Changelog.md' + +const args = process.argv.slice(2) +const CHECK = args.includes('--check') +const DRY_RUN = args.includes('--dry-run') + +const logError = (message, ...optionalParams) => + console.error(message, ...optionalParams) +const logInfo = (message, ...optionalParams) => + console.log(message, ...optionalParams) + +function readArgValue(name) { + const index = args.indexOf(name) + if (index === -1) return null + return args[index + 1] ?? null +} + +function normalizeVersion(version) { + const normalized = version.trim() + return normalized.startsWith('v') ? normalized : `v${normalized}` +} + +async function fetchLatestVersion() { + const explicitVersion = readArgValue('--version') + if (explicitVersion) return normalizeVersion(explicitVersion) + + const response = await fetch(VERSION_URL, { + method: 'GET', + }) + + if (!response.ok) { + throw new Error(`Failed to fetch ${VERSION_URL}: ${response.status}`) + } + + return normalizeVersion(await response.text()) +} + +function replaceExistingLine(content, version) { + const mihomoLine = + /^(\s*-\s*(?:\*\*)?\s*Mihomo\(Meta\)\s*内核升级至\s*)v?\d+(?:\.\d+)+(?:[-+][^\s*]+)?((?:\*\*)?\s*)$/m + + if (!mihomoLine.test(content)) return null + + return content.replace(mihomoLine, `$1${version}$2`) +} + +function insertMihomoLine(content, version) { + const title = /^## .+$/m + const match = content.match(title) + + if (!match || match.index === undefined) { + throw new Error('could not find changelog title') + } + + const titleEnd = match.index + match[0].length + const before = content.slice(0, titleEnd) + const after = content.slice(titleEnd).replace(/^\n*/, '\n\n') + + return `${before}\n\n- **Mihomo(Meta) 内核升级至 ${version}**${after}` +} + +async function main() { + const cwd = process.cwd() + const changelogArg = readArgValue('--file') + const changelogPath = path.join(cwd, changelogArg || DEFAULT_CHANGELOG) + + if (!fs.existsSync(changelogPath)) { + throw new Error(`could not find ${path.relative(cwd, changelogPath)}`) + } + + const version = await fetchLatestVersion() + const content = await fsp.readFile(changelogPath, 'utf-8') + const nextContent = + replaceExistingLine(content, version) ?? insertMihomoLine(content, version) + + if (nextContent === content) { + logInfo(`Mihomo version in changelog is already ${version}`) + return + } + + if (CHECK) { + logError(`Mihomo version in changelog is not ${version}`) + process.exit(1) + } + + if (DRY_RUN) { + logInfo(`Would update Mihomo version in changelog to ${version}`) + return + } + + await fsp.writeFile(changelogPath, nextContent) + logInfo(`Updated Mihomo version in changelog to ${version}`) +} + +main().catch((error) => { + logError('sync-mihomo-version failed:', error.message) + process.exit(1) +})