feat(desktop): add rollout and website publication workflow

This commit is contained in:
winewill committed 2026-11-04 17:29:11 +08:00
1 parent 92fcc7c978
commit 7cc43b47c1
9 files changed
+820 -13

No files matched your search

+256
View File
@@ -0,0 +1,256 @@
name: Publish Desktop · Rollout & Website
run-name: Rollout Desktop package ${{ inputs.package_run_id }} / attempt ${{ inputs.package_run_attempt }} to ${{ inputs.rollout_percentage || 'unchanged' }}
on:
workflow_dispatch:
inputs:
package_run_id:
description: '已经完成首次 COS 发布的 Package Desktop run ID'
type: string
required: true
rollout_percentage:
description: '目标放量比例:0–100 整数,只允许保持或增加;留空只发布官网'
type: string
required: false
default: ''
upload_website:
description: '上传已发布版本的官网安装包并刷新缓存(仅 production)'
type: boolean
default: false
required: true
package_run_attempt:
description: '已发布的原打包 attempt,必须明确填写'
type: string
required: true
default: '1'
permissions:
contents: read
actions: read
jobs:
route:
runs-on: ubuntu-latest
outputs:
selection: ${{ steps.route.outputs.selection }}
runner: ${{ steps.route.outputs.runner }}
steps:
- name: Require master for publication
run: node -e "if (process.env.GITHUB_REF !== 'refs/heads/master') throw new Error('Desktop publication must be dispatched from master')"
- uses: actions/[email protected]
with:
persist-credentials: false
- name: Reject debugging packages before dependency installation
id: preflight
env:
GH_TOKEN: ${{ github.token }}
run: node apps/desktop/scripts/preflight-desktop-publish.mjs
- uses: pnpm/[email protected]
- uses: actions/[email protected]
with:
node-version: '24'
- run: pnpm install --frozen-lockfile
- name: Resolve original package and machine
id: route
env:
GH_TOKEN: ${{ github.token }}
DESKTOP_PUBLISH_RUNNERS: ${{ vars.DESKTOP_PUBLISH_RUNNERS }}
DESKTOP_PACKAGE_ATTEMPT: ${{ steps.preflight.outputs.attempt }}
run: node --import tsx apps/desktop/scripts/resolve-desktop-publish-ci.ts
prepare:
needs: route
runs-on: [self-hosted, '${{ needs.route.outputs.runner }}']
timeout-minutes: 30
outputs:
route: ${{ steps.local.outputs.route }}
preset: ${{ steps.local.outputs.preset }}
approval: ${{ steps.check.outputs.approval }}
website-approval: ${{ steps.check.outputs.website-approval }}
website-destination: ${{ steps.check.outputs.website-destination }}
label: ${{ steps.check.outputs.label }}
env:
DESKTOP_ROLLOUT_PERCENTAGE: ${{ inputs.rollout_percentage }}
DESKTOP_PACKAGE_SELECTION: ${{ needs.route.outputs.selection }}
DESKTOP_UPLOAD_WEBSITE: ${{ inputs.upload_website }}
DOWNLOAD_PROD_EO_ZONE_ID: ${{ vars.DOWNLOAD_PROD_EO_ZONE_ID }}
DSH_TELEMETRY_DISABLED: '1'
steps:
- uses: actions/[email protected]
with:
persist-credentials: false
clean: false
path: desktop-publisher
- uses: pnpm/[email protected]
with:
package_json_file: desktop-publisher/package.json
dest: ${{ runner.temp }}/publish-pnpm-${{ github.run_id }}-${{ github.run_attempt }}
- uses: actions/[email protected]
with:
node-version: '24'
- name: Check local publication configuration before dependency installation
working-directory: desktop-publisher
run: node apps/desktop/scripts/preflight-desktop-publish-local.mjs
- run: pnpm install --frozen-lockfile
working-directory: desktop-publisher
- name: Resolve retained package and approval environment
id: local
working-directory: desktop-publisher
env:
GH_TOKEN: ${{ github.token }}
run: node --import tsx apps/desktop/scripts/publish-desktop-rollout-ci.ts route
- name: Verify initial publication and metadata without upload credentials
id: check
working-directory: desktop-publisher
env:
DESKTOP_PUBLISH_ROUTE: ${{ steps.local.outputs.route }}
run: node --import tsx apps/desktop/scripts/publish-desktop-rollout-ci.ts check
publish:
name: Approve ${{ needs.prepare.outputs.label }}
needs: [route, prepare]
runs-on: [self-hosted, '${{ needs.route.outputs.runner }}']
environment: ${{ needs.prepare.outputs.preset == 'production' && 'desktop-production' || 'desktop-test' }}
concurrency:
group: desktop-publish-${{ needs.route.outputs.runner }}-${{ needs.prepare.outputs.preset }}
cancel-in-progress: false
timeout-minutes: 90
env:
DESKTOP_ROLLOUT_PERCENTAGE: ${{ inputs.rollout_percentage }}
DESKTOP_ROLLOUT_APPROVAL: ${{ needs.prepare.outputs.approval }}
DESKTOP_UPLOAD_WEBSITE: ${{ inputs.upload_website }}
DOWNLOAD_PROD_EO_ZONE_ID: ${{ vars.DOWNLOAD_PROD_EO_ZONE_ID }}
DESKTOP_PUBLISH_ROUTE: ${{ needs.prepare.outputs.route }}
DSH_TELEMETRY_DISABLED: '1'
steps:
- uses: actions/[email protected]
with:
persist-credentials: false
clean: false
path: desktop-publisher
- uses: pnpm/[email protected]
with:
package_json_file: desktop-publisher/package.json
dest: ${{ runner.temp }}/publish-pnpm-${{ github.run_id }}-${{ github.run_attempt }}
- uses: actions/[email protected]
with:
node-version: '24'
- name: Check local publication configuration before dependency installation
working-directory: desktop-publisher
run: node apps/desktop/scripts/preflight-desktop-publish-local.mjs
- run: pnpm install --frozen-lockfile
working-directory: desktop-publisher
- name: Verify initial publication and metadata without upload credentials
id: check
working-directory: desktop-publisher
run: node --import tsx apps/desktop/scripts/publish-desktop-rollout-ci.ts check
- name: Apply rollout to the published feed
id: publish
working-directory: desktop-publisher
run: node --import tsx apps/desktop/scripts/publish-desktop-rollout-ci.ts apply
- name: Retain publication audit
continue-on-error: true
if: always() && steps.publish.outputs.record != ''
uses: actions/[email protected]
with:
name: desktop-publication-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.publish.outputs.record }}/
if-no-files-found: error
retention-days: 30
upload-website-installer:
needs: [route, prepare, publish]
if: inputs.upload_website && needs.prepare.outputs.preset != 'test'
runs-on: [self-hosted, '${{ needs.route.outputs.runner }}']
environment: desktop-production
timeout-minutes: 60
concurrency:
group: desktop-website-upload-${{ needs.prepare.outputs.website-destination }}
cancel-in-progress: false
env:
DESKTOP_PUBLISH_ROUTE: ${{ needs.prepare.outputs.route }}
DESKTOP_WEBSITE_APPROVAL: ${{ needs.prepare.outputs.website-approval }}
DESKTOP_ROLLOUT_APPROVAL: ${{ needs.prepare.outputs.approval }}
DESKTOP_ROLLOUT_PERCENTAGE: ${{ inputs.rollout_percentage }}
DESKTOP_UPLOAD_WEBSITE: ${{ inputs.upload_website }}
DOWNLOAD_PROD_EO_ZONE_ID: ${{ vars.DOWNLOAD_PROD_EO_ZONE_ID }}
steps:
- uses: actions/[email protected]
with:
persist-credentials: false
clean: false
path: website-publisher
- uses: pnpm/[email protected]
with:
package_json_file: website-publisher/package.json
dest: ${{ runner.temp }}/website-pnpm-${{ github.run_id }}-${{ github.run_attempt }}
- uses: actions/[email protected]
with:
node-version: '24'
- name: Check local publication configuration
working-directory: website-publisher
run: node apps/desktop/scripts/preflight-desktop-publish-local.mjs
- run: pnpm install --frozen-lockfile
working-directory: website-publisher
- name: Upload website installer
id: website
working-directory: website-publisher
run: node --import tsx apps/desktop/scripts/publish-desktop-rollout-ci.ts website-upload
- name: Archive website publication diagnostics
if: always() && steps.website.outputs.record != ''
continue-on-error: true
uses: actions/[email protected]
with:
name: website-upload-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.website.outputs.record }}/
if-no-files-found: warn
retention-days: 30
purge-website-installer:
needs: [route, prepare, upload-website-installer]
if: inputs.upload_website && needs.prepare.outputs.preset != 'test'
runs-on: [self-hosted, '${{ needs.route.outputs.runner }}']
environment: desktop-production
timeout-minutes: 60
concurrency:
group: desktop-website-purge-${{ needs.prepare.outputs.website-destination }}
cancel-in-progress: false
env:
DESKTOP_PUBLISH_ROUTE: ${{ needs.prepare.outputs.route }}
DESKTOP_WEBSITE_APPROVAL: ${{ needs.prepare.outputs.website-approval }}
DESKTOP_ROLLOUT_APPROVAL: ${{ needs.prepare.outputs.approval }}
DESKTOP_ROLLOUT_PERCENTAGE: ${{ inputs.rollout_percentage }}
DESKTOP_UPLOAD_WEBSITE: ${{ inputs.upload_website }}
DOWNLOAD_PROD_EO_ZONE_ID: ${{ vars.DOWNLOAD_PROD_EO_ZONE_ID }}
steps:
- uses: actions/[email protected]
with:
persist-credentials: false
clean: false
path: website-publisher
- uses: pnpm/[email protected]
with:
package_json_file: website-publisher/package.json
dest: ${{ runner.temp }}/website-pnpm-${{ github.run_id }}-${{ github.run_attempt }}
- uses: actions/[email protected]
with:
node-version: '24'
- name: Check local publication configuration
working-directory: website-publisher
run: node apps/desktop/scripts/preflight-desktop-publish-local.mjs
- run: pnpm install --frozen-lockfile
working-directory: website-publisher
- name: Recover and observe website cache purge
id: website
working-directory: website-publisher
run: node --import tsx apps/desktop/scripts/publish-desktop-rollout-ci.ts website-purge
- name: Archive website publication diagnostics
if: always() && steps.website.outputs.record != ''
continue-on-error: true
uses: actions/[email protected]
with:
name: website-purge-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ steps.website.outputs.record }}/
if-no-files-found: warn
retention-days: 30