Publish CLIProxyAPI Pro Management #120
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: Publish CLIProxyAPI Pro Management | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: '0 20 * * *' | |
| jobs: | |
| check-version: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| should_release: ${{ steps.compare.outputs.should_release }} | |
| target_release_tag: ${{ steps.compare.outputs.target_release_tag }} | |
| current_management_tag: ${{ steps.compare.outputs.current_management_tag }} | |
| upstream_tag: ${{ steps.compare.outputs.upstream_tag }} | |
| upstream_sha: ${{ steps.compare.outputs.upstream_sha }} | |
| upstream_base_version: ${{ steps.compare.outputs.upstream_base_version }} | |
| build_version: ${{ steps.compare.outputs.build_version }} | |
| steps: | |
| - name: Compare latest management release | |
| id: compare | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CURRENT_REPO: ${{ github.repository }} | |
| UPSTREAM_REPO: router-for-me/Cli-Proxy-API-Management-Center | |
| run: | | |
| set -euo pipefail | |
| normalize_version() { | |
| local version="$1" | |
| version="${version#v}" | |
| version="${version%-pro}" | |
| echo "${version}" | |
| } | |
| version_gt() { | |
| local left="$1" | |
| local right="$2" | |
| [ "$(printf '%s\n%s\n' "${right}" "${left}" | sort -V | tail -n 1)" = "${left}" ] && [ "${left}" != "${right}" ] | |
| } | |
| target_release_tag="$(gh release view --repo "${CURRENT_REPO}" --json tagName --jq '.tagName' 2>/dev/null || true)" | |
| upstream_tag="$(gh release view --repo "${UPSTREAM_REPO}" --json tagName --jq '.tagName')" | |
| if [ -z "${upstream_tag}" ]; then | |
| echo "No upstream latest release found." >&2 | |
| exit 1 | |
| fi | |
| upstream_sha="$(gh api "repos/${UPSTREAM_REPO}/commits/${upstream_tag}" --jq '.sha')" | |
| if [ -z "${target_release_tag}" ]; then | |
| echo "No current Pro release found. Management-only update will wait for the core release workflow." | |
| echo "should_release=false" >> "${GITHUB_OUTPUT}" | |
| echo "target_release_tag=" >> "${GITHUB_OUTPUT}" | |
| echo "current_management_tag=" >> "${GITHUB_OUTPUT}" | |
| echo "upstream_tag=${upstream_tag}" >> "${GITHUB_OUTPUT}" | |
| echo "upstream_sha=${upstream_sha}" >> "${GITHUB_OUTPUT}" | |
| echo "upstream_base_version=$(normalize_version "${upstream_tag}")" >> "${GITHUB_OUTPUT}" | |
| echo "build_version=v$(normalize_version "${upstream_tag}")-pro" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| current_body="$(gh release view "${target_release_tag}" --repo "${CURRENT_REPO}" --json body --jq '.body // ""')" | |
| current_management_tag="$(printf '%s\n' "${current_body}" | sed -n 's/^- Management upstream release: //p' | head -n 1)" | |
| has_management_asset="$(gh release view "${target_release_tag}" --repo "${CURRENT_REPO}" --json assets --jq 'any(.assets[]; .name == "management.html")')" | |
| upstream_base_version="$(normalize_version "${upstream_tag}")" | |
| current_base_version="0.0.0" | |
| if [ -n "${current_management_tag}" ]; then | |
| current_base_version="$(normalize_version "${current_management_tag}")" | |
| fi | |
| build_version="v${upstream_base_version}-pro" | |
| should_release="false" | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| should_release="true" | |
| elif [ "${has_management_asset}" != "true" ]; then | |
| should_release="true" | |
| elif version_gt "${upstream_base_version}" "${current_base_version}"; then | |
| should_release="true" | |
| fi | |
| echo "target_release_tag=${target_release_tag}" | |
| echo "current_management_tag=${current_management_tag:-none}" | |
| echo "current_base_version=${current_base_version}" | |
| echo "upstream_tag=${upstream_tag}" | |
| echo "upstream_sha=${upstream_sha}" | |
| echo "upstream_base_version=${upstream_base_version}" | |
| echo "build_version=${build_version}" | |
| echo "has_management_asset=${has_management_asset}" | |
| echo "should_release=${should_release}" | |
| echo "target_release_tag=${target_release_tag}" >> "${GITHUB_OUTPUT}" | |
| echo "current_management_tag=${current_management_tag}" >> "${GITHUB_OUTPUT}" | |
| echo "upstream_tag=${upstream_tag}" >> "${GITHUB_OUTPUT}" | |
| echo "upstream_sha=${upstream_sha}" >> "${GITHUB_OUTPUT}" | |
| echo "upstream_base_version=${upstream_base_version}" >> "${GITHUB_OUTPUT}" | |
| echo "build_version=${build_version}" >> "${GITHUB_OUTPUT}" | |
| echo "should_release=${should_release}" >> "${GITHUB_OUTPUT}" | |
| validate-repository: | |
| needs: check-version | |
| if: needs.check-version.outputs.should_release == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout customizations | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - name: Set up Python | |
| uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 | |
| with: | |
| python-version: '3.x' | |
| - name: Set up Go for actionlint | |
| uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: stable | |
| cache: false | |
| - name: Install actionlint | |
| env: | |
| GOBIN: ${{ runner.temp }}/validation-bin | |
| run: | | |
| go install github.com/rhysd/actionlint/cmd/[email protected] | |
| echo "${GOBIN}" >> "${GITHUB_PATH}" | |
| - name: Validate repository sources | |
| env: | |
| VALIDATION_REQUIRE_TOOLS: "1" | |
| run: bash scripts/validation/repo.sh | |
| validate-management: | |
| needs: check-version | |
| if: needs.check-version.outputs.should_release == 'true' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout customizations | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: customizations-repo | |
| - name: Checkout Management upstream release | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: router-for-me/Cli-Proxy-API-Management-Center | |
| ref: ${{ needs.check-version.outputs.upstream_sha }} | |
| path: upstream | |
| - name: Set up Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version-file: upstream/package.json | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: ${{ runner.os }}-bun-${{ hashFiles('upstream/bun.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-bun- | |
| - name: Validate Management customization | |
| env: | |
| VERSION: ${{ needs.check-version.outputs.build_version }} | |
| run: bash customizations-repo/scripts/validation/management.sh upstream | |
| build-and-release: | |
| needs: | |
| - check-version | |
| - validate-repository | |
| - validate-management | |
| if: needs.check-version.outputs.should_release == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout customizations | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: customizations-repo | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Checkout management upstream release | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: router-for-me/Cli-Proxy-API-Management-Center | |
| ref: ${{ needs.check-version.outputs.upstream_sha }} | |
| path: upstream | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| - name: Apply Pro customizations | |
| run: bash customizations-repo/cliproxyapi-pro-management/apply.sh upstream | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2 | |
| with: | |
| bun-version-file: upstream/package.json | |
| - name: Cache Bun dependencies | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.bun/install/cache | |
| key: ${{ runner.os }}-bun-${{ hashFiles('upstream/bun.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-bun- | |
| - name: Install dependencies | |
| working-directory: upstream | |
| run: bun install --frozen-lockfile | |
| - name: Build all-in-one HTML | |
| working-directory: upstream | |
| env: | |
| VERSION: ${{ needs.check-version.outputs.build_version }} | |
| run: bun run build | |
| - name: Prepare release asset | |
| working-directory: upstream | |
| run: | | |
| set -euo pipefail | |
| cd dist | |
| mv index.html management.html | |
| ls -lh management.html | |
| - name: Update release notes and upload management asset | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| CURRENT_REPO: ${{ github.repository }} | |
| TARGET_RELEASE_TAG: ${{ needs.check-version.outputs.target_release_tag }} | |
| MANAGEMENT_TAG: ${{ needs.check-version.outputs.upstream_tag }} | |
| MANAGEMENT_BUILD_VERSION: ${{ needs.check-version.outputs.build_version }} | |
| MANAGEMENT_SHA: ${{ github.sha }} | |
| run: | | |
| set -euo pipefail | |
| gh release view "${TARGET_RELEASE_TAG}" --repo "${CURRENT_REPO}" --json body --jq '.body // ""' > current-release-notes.md | |
| gh release view "${MANAGEMENT_TAG}" --repo router-for-me/Cli-Proxy-API-Management-Center --json body --jq '.body // ""' > management-upstream-notes.md | |
| management_sha="$(git -C upstream rev-parse HEAD)" | |
| customization_sha="$(git -C customizations-repo rev-parse HEAD)" | |
| export MANAGEMENT_SHA="${management_sha}" | |
| export CUSTOMIZATION_SHA="${customization_sha}" | |
| python3 - <<'PY' | |
| from pathlib import Path | |
| import os | |
| body = Path('current-release-notes.md').read_text() | |
| upstream_notes = Path('management-upstream-notes.md').read_text().strip() | |
| management_tag = os.environ['MANAGEMENT_TAG'] | |
| management_build_version = os.environ['MANAGEMENT_BUILD_VERSION'] | |
| management_sha = os.environ['MANAGEMENT_SHA'] | |
| customization_sha = os.environ['CUSTOMIZATION_SHA'] | |
| def replace_line(text, prefix, line): | |
| lines = text.splitlines() | |
| replaced = False | |
| for index, current in enumerate(lines): | |
| if current.startswith(prefix): | |
| lines[index] = line | |
| replaced = True | |
| break | |
| if not replaced: | |
| lines.append(line) | |
| return '\n'.join(lines) + ('\n' if text.endswith('\n') or lines else '') | |
| body = replace_line(body, '- Management upstream release:', f'- Management upstream release: {management_tag}') | |
| body = replace_line(body, '- Management build version:', f'- Management build version: {management_build_version}') | |
| body = replace_line(body, '- Management upstream commit:', f'- Management upstream commit: {management_sha}') | |
| body = replace_line(body, '- Customization commit:', f'- Customization commit: {customization_sha}') | |
| start = '<!-- cli-proxyapi-pro-management-start -->' | |
| end = '<!-- cli-proxyapi-pro-management-end -->' | |
| section = ( | |
| f'{start}\n' | |
| '## Management upstream release notes\n\n' | |
| f'{upstream_notes if upstream_notes else "No management upstream release notes were provided."}\n' | |
| f'{end}' | |
| ) | |
| if start in body and end in body: | |
| before = body.split(start, 1)[0].rstrip() | |
| after = body.split(end, 1)[1].lstrip() | |
| body = f'{before}\n\n{section}\n' | |
| if after: | |
| body += f'\n{after}' | |
| else: | |
| body = body.rstrip() + f'\n\n{section}\n' | |
| Path('release-notes.md').write_text(body) | |
| PY | |
| gh release edit "${TARGET_RELEASE_TAG}" \ | |
| --repo "${CURRENT_REPO}" \ | |
| --notes-file release-notes.md | |
| gh release upload "${TARGET_RELEASE_TAG}" \ | |
| upstream/dist/management.html \ | |
| --repo "${CURRENT_REPO}" \ | |
| --clobber | |
| cleanup-runs: | |
| runs-on: ubuntu-latest | |
| needs: build-and-release | |
| permissions: | |
| actions: write | |
| contents: read | |
| steps: | |
| - name: Delete old workflow runs | |
| uses: Mattraks/delete-workflow-runs@0cf693bc9909e5e867ee8f27b813224ba862939c # v2 | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| repository: ${{ github.repository }} | |
| retain_days: 7 | |
| keep_minimum_runs: 6 |