chore(deps): 升级 dsh peers 到 0.1.2-rc.1 / upgrade dsh peers to 0.1.2-rc.1 #55
Workflow file for this run
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: Release | |
| # PR-driven release. Merging a `release vX.Y.Z` PR (opened by the Release prep | |
| # workflow) runs the whole release inline on the pull_request event: | |
| # validate -> sanity gate -> npm publish dsh-advisor@X.Y.Z -> create+push the | |
| # vX.Y.Z tag (skipped if it already exists) -> GitHub Release. Prerelease | |
| # versions (e.g. v0.1.1-alpha.1) are supported: they publish to a prerelease | |
| # npm dist-tag and never touch the `latest` tag. | |
| # | |
| # npm publish uses OIDC trusted publishing (`permissions: id-token: write` | |
| # below): no NODE_AUTH_TOKEN / NPM_TOKEN secret is required — npm exchanges | |
| # the workflow's OIDC token for a short-lived publish token. The npmjs org | |
| # must configure a trusted publisher for this repository + workflow (see | |
| # https://docs.npmjs.com/generating-provenance-statements). The tag and | |
| # GitHub Release are created with the workflow's GITHUB_TOKEN. | |
| # | |
| # NOTE: publish happens BEFORE tag creation (mirror mstar-harness). If the tag | |
| # already exists (e.g. a re-run after a partial failure), publish still | |
| # proceeds and the tag step skips. | |
| on: | |
| pull_request: | |
| types: [closed] | |
| branches: [main] | |
| permissions: | |
| contents: write | |
| # id-token: write enables OIDC token exchange for npm trusted publishing | |
| # (publish step below); the GitHub Release + tag steps use GITHUB_TOKEN. | |
| id-token: write | |
| concurrency: | |
| group: release | |
| cancel-in-progress: false | |
| jobs: | |
| release: | |
| if: > | |
| github.event.pull_request.merged == true | |
| && startsWith(github.event.pull_request.title, 'release v') | |
| && startsWith(github.event.pull_request.head.ref, 'release/v') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout merge commit | |
| uses: actions/checkout@v4 | |
| with: | |
| # Release the exact merge commit of the merged release PR, with full | |
| # history so `git describe --tags` can find the previous release tag. | |
| ref: ${{ github.event.pull_request.merge_commit_sha }} | |
| fetch-depth: 0 | |
| # pnpm/action-setup must run before setup-node so that setup-node's | |
| # `cache: pnpm` can locate the pnpm store path (same order as ci.yml). | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 11.21.0 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "24.19.0" | |
| registry-url: https://registry.npmjs.org | |
| cache: pnpm | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Resolve version | |
| id: ver | |
| run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" | |
| # The Release prep workflow derives the version from the PR title | |
| # ("release v<version>") and bumps package.json to match. If the merged | |
| # PR drifted from that contract (e.g. the version was edited inside the | |
| # PR without re-running prep), publishing the drifted version would | |
| # silently produce a mismatched tag and an empty GitHub Release — fail | |
| # loudly instead. | |
| - name: Cross-check version vs PR title | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| set -euo pipefail | |
| TITLE_VER="${TITLE#release v}" | |
| if [ "$TITLE_VER" != "$VERSION" ]; then | |
| echo "::error::PR title version \"${TITLE_VER}\" does not match package.json version \"${VERSION}\". Re-run Release prep for v${VERSION} instead of hand-editing the PR." | |
| exit 1 | |
| fi | |
| echo "PR title and package.json agree on ${VERSION}" | |
| - name: Validate version | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| if [ -z "$VERSION" ]; then | |
| echo "::error::package.json version is empty; refusing to release." | |
| exit 1 | |
| fi | |
| # Version guard (mirror release-prep): X.Y.Z or X.Y.Z-prerelease | |
| # (semver; the suffix must contain at least one digit, matching | |
| # parseVersion in prepare-release.mjs — digitless suffixes like | |
| # 0.1.1-alpha are rejected). The version flows into an awk regex | |
| # anchor below; reject metacharacters up front so a malformed | |
| # package.json version cannot break the extraction (awk exit-2) | |
| # after publish. '-' is a literal character in awk ERE outside a | |
| # character class, so prerelease suffixes need no extra escaping | |
| # there. | |
| if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]*[0-9][0-9A-Za-z.-]*)?$ ]]; then | |
| echo "::error::Invalid version \"$VERSION\" in package.json. Expected X.Y.Z or X.Y.Z-prerelease (e.g. 0.2.0, 0.1.1-alpha.1)." | |
| exit 1 | |
| fi | |
| # Tag-exists policy (mirror mstar-harness): publish proceeds even if | |
| # v$VERSION already exists (e.g. re-run after a partial failure); the | |
| # tag step below skips creation when the tag is already present. | |
| echo "Releasing dsh-advisor@${VERSION}" | |
| - name: Sanity gate (typecheck + build + test) | |
| run: | | |
| pnpm run typecheck | |
| pnpm run build | |
| pnpm run test | |
| - name: Assert packed tarball contents (pre-publish guard) | |
| run: | | |
| set -euo pipefail | |
| # Same guard as ci.yml: npm 11 writes the Tarball Contents listing to | |
| # STDERR (stdout carries only the tarball filename), so capture both | |
| # streams; refuse to publish a tarball missing the built entrypoint | |
| # or the cordis bundle patch. | |
| npm pack --dry-run --ignore-scripts 2>&1 | tee "$RUNNER_TEMP/pack-listing.txt" | |
| grep -Eq "lib/index\.js( |$)" "$RUNNER_TEMP/pack-listing.txt" | |
| grep -Eq "cordis\.patch\.yml( |$)" "$RUNNER_TEMP/pack-listing.txt" | |
| - name: Publish to npm | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| # OIDC trusted publishing: no NODE_AUTH_TOKEN / NPM_TOKEN env or | |
| # secret — npm exchanges the workflow's id-token (permissions above) | |
| # for a short-lived publish token with provenance. The npmjs org must | |
| # have a trusted publisher configured for this repo + workflow. | |
| # | |
| # Prerelease dist-tag: a version containing '-' (e.g. | |
| # 0.1.1-alpha.1) publishes to the prerelease-prefix tag (text | |
| # between the first '-' and the first '.' after it -> "alpha") | |
| # instead of the default `latest`, so prereleases never clobber the | |
| # latest release and consumers opting into the tag can install it. | |
| # Formal X.Y.Z versions publish without --tag (default latest). | |
| # --provenance is explicitly requested: it makes sigstore signing | |
| # deterministic under OIDC trusted publishing (matches the sibling | |
| # dsh-llm-fallbacks release workflow). | |
| if [[ "${VERSION}" == *-* ]]; then | |
| PRETAG="${VERSION#*-}" | |
| PRETAG="${PRETAG%%.*}" | |
| npm publish --provenance --access public --tag "$PRETAG" | |
| else | |
| npm publish --provenance --access public | |
| fi | |
| - name: Configure git identity | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Extract release notes | |
| run: | | |
| set -euo pipefail | |
| # Release body source: the `## [<version>]` section of CHANGELOG.md, | |
| # written by prepare-release.mjs during release-prep and committed in | |
| # the release PR — the same section the PR body uses (the PR body | |
| # additionally appends a merge-instruction line; the Release body is | |
| # the section only). | |
| # Guard on the file existing: under `set -e`, awk on a missing | |
| # CHANGELOG.md exits 2 and aborts the step. The version anchor is | |
| # prefix-safe: the pattern is anchored at `^## \[<version>\]`, so | |
| # `0.1.1` cannot match a `## [0.1.10]` header. | |
| # No git-log fallback on the Release side: every release PR prepared | |
| # by the current prep writes its CHANGELOG section before the PR | |
| # opens, so a missing section is a contract break — fail loudly | |
| # instead of shipping an empty GitHub Release (mirror | |
| # dsh-llm-fallbacks; an empty Release is a silent quality | |
| # regression, not a recoverable one). | |
| VERSION="${{ steps.ver.outputs.version }}" | |
| if [ -f CHANGELOG.md ]; then | |
| # Escape regex metacharacters in the version inside awk (the gsub | |
| # runs after `-v` argument escape processing, which would strip | |
| # backslashes from a shell-escaped value) so the anchor matches | |
| # literally: dots must not act as any-char. VERSION is validated | |
| # upstream (X.Y.Z or X.Y.Z-prerelease); '-' is a literal character | |
| # in awk ERE outside a character class, so prerelease suffixes | |
| # need no extra escaping. | |
| awk -v v="$VERSION" ' | |
| BEGIN { gsub(/\./, "\\\\&", v) } | |
| /^## \[/ { if (in_section) exit } | |
| $0 ~ "^## \\[" v "\\]" { in_section = 1 } | |
| in_section | |
| ' CHANGELOG.md > /tmp/notes.md | |
| fi | |
| if [ ! -s /tmp/notes.md ]; then | |
| echo "::error::No changelog section found for v${VERSION} in CHANGELOG.md; refusing to create an empty GitHub Release." | |
| exit 1 | |
| fi | |
| - name: Create + push tag | |
| env: | |
| VERSION: ${{ steps.ver.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| TAG="v${VERSION}" | |
| if git rev-parse "$TAG" >/dev/null 2>&1; then | |
| echo "Tag $TAG already exists; skipping tag creation." | |
| exit 0 | |
| fi | |
| git tag -a -m "Release ${TAG}" "$TAG" | |
| git push origin "$TAG" | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: v${{ steps.ver.outputs.version }} | |
| name: v${{ steps.ver.outputs.version }} | |
| body_path: /tmp/notes.md | |
| draft: false | |
| # A version containing '-' (e.g. 0.1.1-alpha.1) is a prerelease — | |
| # mark the GitHub Release as pre-release so it is never presented as | |
| # the latest stable release, matching the npm prerelease dist-tag | |
| # used by the publish step above. | |
| prerelease: ${{ contains(steps.ver.outputs.version, '-') }} |