Release #23
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 | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Release tag to publish, for example v1.0.0' | |
| required: true | |
| workflow_call: | |
| inputs: | |
| version: | |
| description: 'Release tag to publish, for example v1.0.0' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: release-${{ github.event_name == 'push' && github.ref_name || inputs.version }} | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| name: Build and validate (Node 24.15.0) | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event_name == 'push' && github.ref || inputs.version }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.15.0' | |
| - name: Setup pnpm | |
| run: npm install --global pnpm@11.13.1 | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build package | |
| run: pnpm build | |
| - name: Run tests | |
| run: pnpm test | |
| - name: Run v1 performance tests | |
| run: pnpm --filter=stax-xml test:perf | |
| - name: Collect runtime retention evidence | |
| run: pnpm --filter=benchmark run dev:runtime-retention | |
| - name: Type check package | |
| run: pnpm --filter=stax-xml exec tsc -p tsconfig.json --noEmit | |
| - name: Run W3C conformance subset | |
| run: pnpm test:w3c | |
| - name: Verify release surfaces | |
| run: pnpm verify:release-surfaces | |
| - name: Validate pure-JS package contents | |
| run: node scripts/validate-prerelease.mjs "${{ github.event_name == 'push' && github.ref_name || inputs.version }}" --pack | |
| - name: Generate API documentation | |
| run: pnpm --filter=stax-xml-docs typedoc | |
| - name: Build documentation | |
| run: pnpm docs:build | |
| - name: Validate release documentation snapshot | |
| run: pnpm docs:snapshot:release "${{ github.event_name == 'push' && github.ref_name || inputs.version }}" --dry-run | |
| minimum-node: | |
| name: Test minimum Node.js (20.19.0) | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event_name == 'push' && github.ref || inputs.version }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20.19.0' | |
| - name: Setup compatible pnpm | |
| run: | | |
| npm install --global pnpm@10.34.5 | |
| npm_config_manage_package_manager_versions=false pnpm config set --global manage-package-manager-versions false | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Build package | |
| run: pnpm build | |
| - name: Run tests | |
| run: pnpm test | |
| - name: Run v1 performance tests | |
| run: pnpm --filter=stax-xml test:perf | |
| - name: Collect runtime retention evidence | |
| run: pnpm --filter=benchmark run dev:runtime-retention | |
| - name: Run W3C conformance subset | |
| run: pnpm test:w3c | |
| - name: Verify release surfaces | |
| run: pnpm verify:release-surfaces | |
| - name: Validate pure-JS package contents | |
| run: node scripts/validate-prerelease.mjs "${{ github.event_name == 'push' && github.ref_name || inputs.version }}" --pack | |
| publish: | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - build | |
| - minimum-node | |
| permissions: | |
| contents: write | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event_name == 'push' && github.ref || inputs.version }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24.15.0' | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Ensure npm supports trusted publishing | |
| run: npm install -g npm@^11.5.1 | |
| - name: Setup pnpm | |
| run: npm install --global pnpm@11.13.1 | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile --ignore-scripts | |
| - name: Build facade package | |
| run: pnpm build | |
| - name: Validate pure-JS package contents | |
| run: node scripts/validate-prerelease.mjs "${{ github.event_name == 'push' && github.ref_name || inputs.version }}" --pack | |
| - name: Resolve npm dist-tag | |
| id: npm-dist-tag | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| VERSION="$(node -p "require('./packages/stax-xml/package.json').version")" | |
| if [[ "$VERSION" == *-* ]]; then | |
| echo "tag=next" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "tag=latest" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Publish facade package | |
| working-directory: packages/stax-xml | |
| run: | | |
| VERSION="$(node -p "require('./package.json').version")" | |
| if npm view "stax-xml@$VERSION" version >/dev/null 2>&1; then | |
| echo "stax-xml@$VERSION is already published; skipping npm publish." | |
| else | |
| npm publish --access public --tag "${{ steps.npm-dist-tag.outputs.tag }}" | |
| fi | |
| - name: Smoke published package | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| temp_dir="$(mktemp -d)" | |
| cleanup() { rm -rf "$temp_dir"; } | |
| trap cleanup EXIT | |
| cd "$temp_dir" | |
| npm init -y >/dev/null | |
| npm pkg set type=module >/dev/null | |
| for attempt in 1 2 3 4 5 6 7 8 9 10; do | |
| if npm install --omit=dev --ignore-scripts --prefer-online --loglevel=error \ | |
| --cache "$temp_dir/npm-cache-$attempt" \ | |
| "stax-xml@${{ steps.npm-dist-tag.outputs.version }}"; then | |
| break | |
| fi | |
| if [ "$attempt" = 10 ]; then | |
| exit 1 | |
| fi | |
| echo "npm install attempt $attempt/10 failed; retrying after registry propagation delay..." | |
| sleep 15 | |
| done | |
| node --input-type=module <<'NODE' | |
| import { EventReaderSync, XmlEventType } from 'stax-xml'; | |
| import { x } from 'stax-xml/converter'; | |
| let events = 0; | |
| let startElements = 0; | |
| for (const event of new EventReaderSync('<root><item id="1">ok</item></root>')) { | |
| events++; | |
| if (event.type === XmlEventType.START_ELEMENT) { | |
| startElements++; | |
| } | |
| } | |
| if (events <= 0 || startElements !== 2) { | |
| throw new Error(`Unexpected parse result: events=${events}, startElements=${startElements}`); | |
| } | |
| const projection = x.object({ id: x.string('/root/item/@id') }); | |
| if (projection.parseSync('<root><item id="1"/></root>').id !== '1') { | |
| throw new Error('Converter subpath smoke failed.'); | |
| } | |
| console.log(JSON.stringify({ events, startElements }, null, 2)); | |
| NODE | |
| - name: Generate changelog | |
| if: ${{ !contains(steps.npm-dist-tag.outputs.version, '-') }} | |
| run: pnpm dlx changelogithub@14.0.0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |