ci(release): pack on pull requests and publish from family tags

Each sequence gets its own workflow so the two version models never meet in one
file. Pack runs without credentials on every pull request and master push, so a
pull request proves the whole publish set still packs; publication is a manual
dispatch guarded by the npm-publish environment, runs only from that family's
tag, and never builds - it uploads the bytes pack produced.
This commit is contained in:
imccyu
2026-08-10 23:35:36 +08:00
parent 8cd38945f1
commit 4e91230dd6
2 changed files with 252 additions and 0 deletions

127
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,127 @@
# Pack and publish the dsh release sequence: every package under packages/ plus
# the apps/ entries, all on one version. The vendored framework and the native
# packages are separate sequences with their own workflows and version lines.
#
# Pack runs without credentials on every pull request and master push, so a
# pull request proves the whole publish set still packs. Publication is a
# manual dispatch from a dsh-v* tag and consumes exactly the packed bytes.
name: Release (dsh)
on:
pull_request:
push:
branches: [master]
workflow_dispatch:
inputs:
publish:
description: Publish the packed tarballs to npm. Must run from a dsh-v* tag.
required: true
type: boolean
default: false
permissions:
contents: read
concurrency:
# dist-tags are shared registry state; never race two release runs.
group: ${{ github.workflow }}
cancel-in-progress: false
env:
PRIMARY_NODE_VERSION: '24'
DSH_TELEMETRY_DISABLED: '1'
jobs:
pack:
name: Pack npm tarballs
runs-on: ubuntu-24.04
steps:
# Complete history: the release scripts read tags.
- uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false
- uses: pnpm/action-setup@v4
with:
dest: ${{ runner.temp }}/setup-pnpm
- uses: actions/setup-node@v6
with:
node-version: ${{ env.PRIMARY_NODE_VERSION }}
- name: Configure pnpm store path
id: pnpm-store
run: |
store_root="$HOME/.local/share/pnpm/store"
echo "PNPM_CONFIG_STORE_DIR=$store_root" >> "$GITHUB_ENV"
store_path=$(PNPM_CONFIG_STORE_DIR="$store_root" pnpm store path --silent)
echo "path=$store_path" >> "$GITHUB_OUTPUT"
- uses: actions/cache/restore@v4
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: ${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-${{ hashFiles('pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-node-${{ env.PRIMARY_NODE_VERSION }}-pnpm-
- name: Install (immutable)
run: pnpm install --frozen-lockfile
- name: Verify release version
env:
RELEASE_PUBLISH: ${{ inputs.publish }}
run: pnpm run release:verify --family dsh
- name: Build
run: pnpm run build
- name: Pack release tarballs
run: pnpm run release:pack --family dsh --out dist/npm
- uses: actions/upload-artifact@v4
with:
name: dsh-npm-tarballs
path: dist/npm/*
if-no-files-found: error
retention-days: 7
publish:
name: Publish to npm
if: inputs.publish
needs: pack
runs-on: ubuntu-24.04
# Required reviewers and the allowed tags live on the environment; this is
# the only step in the sequence that can write to the registry.
environment: npm-publish
permissions:
contents: read
id-token: write
steps:
# Checkout and install carry the release scripts only. There is no build
# step: publication uploads the bytes the pack job produced.
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: pnpm/action-setup@v4
with:
dest: ${{ runner.temp }}/setup-pnpm
- uses: actions/setup-node@v6
with:
node-version: ${{ env.PRIMARY_NODE_VERSION }}
registry-url: https://registry.npmjs.org
- name: Install (immutable, no package scripts)
run: pnpm install --frozen-lockfile --ignore-scripts
- uses: actions/download-artifact@v4
with:
name: dsh-npm-tarballs
path: dist/npm
- name: Publish tarballs
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: pnpm run release:publish --family dsh --from dist/npm