chore: release v3.1.3 #14
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: Publish to npm | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: "Existing release tag to republish after a recoverable workflow failure, for example v3.0.0." | |
| required: true | |
| default: "v3.0.0" | |
| concurrency: | |
| group: publish-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} | |
| cancel-in-progress: false | |
| jobs: | |
| publish: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v5 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: npm | |
| registry-url: https://registry.npmjs.org | |
| - name: Verify tag matches package.json version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| RELEASE_TAG="${{ inputs.release_tag }}" | |
| else | |
| RELEASE_TAG="${GITHUB_REF#refs/tags/}" | |
| fi | |
| if [[ ! "${RELEASE_TAG}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Release tag ${RELEASE_TAG} must be an exact stable SemVer tag such as v3.0.0" | |
| exit 1 | |
| fi | |
| TAG_VERSION="${RELEASE_TAG#v}" | |
| PKG_VERSION=$(node -p "require('./package.json').version") | |
| if [ "${TAG_VERSION}" != "${PKG_VERSION}" ]; then | |
| echo "Requested version ${TAG_VERSION} does not match package.json version ${PKG_VERSION}" | |
| exit 1 | |
| fi | |
| TAG_COMMIT=$(git rev-parse "${RELEASE_TAG}^{commit}") | |
| HEAD_COMMIT=$(git rev-parse HEAD) | |
| if [ "${TAG_COMMIT}" != "${HEAD_COMMIT}" ]; then | |
| echo "Release tag ${RELEASE_TAG} does not resolve to checked-out commit ${HEAD_COMMIT}" | |
| exit 1 | |
| fi | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Restore MongoDB memory-server binaries | |
| uses: actions/cache@v5 | |
| with: | |
| path: .cache/mongodb-memory-server/binaries | |
| key: mongodb-memory-server-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('scripts/validation/server-matrix-config.cjs') }} | |
| - name: Run release preflight | |
| run: npm run release:preflight | |
| - name: Verify npm publish authentication | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| if [ -z "${NODE_AUTH_TOKEN:-}" ]; then | |
| echo "::error::NPM_TOKEN is not configured or is not available to this repository. Grant the same npm publish secret used by schema-dsl to vextjs/monSQLize, or configure npm trusted publishing and adjust this workflow." | |
| exit 2 | |
| fi | |
| npm whoami --registry=https://registry.npmjs.org/ | |
| - name: Inspect existing registry state | |
| id: registry-state | |
| shell: bash | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| EXPECTED_GIT_HEAD=$(git rev-parse HEAD) | |
| PUBLISHED_VERSION=$(npm view "monsqlize@${VERSION}" version --registry=https://registry.npmjs.org/ 2>/dev/null || true) | |
| if [ "${PUBLISHED_VERSION}" != "${VERSION}" ]; then | |
| echo "already_published=false" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| REGISTRY_GIT_HEAD=$(npm view "monsqlize@${VERSION}" gitHead --registry=https://registry.npmjs.org/) | |
| if [ "${REGISTRY_GIT_HEAD}" != "${EXPECTED_GIT_HEAD}" ]; then | |
| echo "::error::monsqlize@${VERSION} already exists with gitHead=${REGISTRY_GIT_HEAD:-missing}; expected=${EXPECTED_GIT_HEAD}" | |
| exit 1 | |
| fi | |
| echo "monsqlize@${VERSION} already exists from this exact tag commit; publish will be skipped and registry acceptance will resume." | |
| echo "already_published=true" >> "${GITHUB_OUTPUT}" | |
| - name: Publish to npm | |
| if: steps.registry-state.outputs.already_published != 'true' | |
| run: npm publish --provenance --access public --ignore-scripts | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| - name: Verify registry and installed package | |
| shell: bash | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| for attempt in 1 2 3 4 5 6; do | |
| REGISTRY_VERSION=$(npm view "monsqlize@${VERSION}" version --registry=https://registry.npmjs.org/ 2>/dev/null || true) | |
| if [ "${REGISTRY_VERSION}" = "${VERSION}" ]; then | |
| break | |
| fi | |
| if [ "${attempt}" = "6" ]; then | |
| echo "::error::monsqlize@${VERSION} did not become readable from npm" | |
| exit 1 | |
| fi | |
| sleep 10 | |
| done | |
| CONSUMER_DIR="${RUNNER_TEMP}/monsqlize-registry-smoke" | |
| INTEGRITY=$(npm view "monsqlize@${VERSION}" dist.integrity --registry=https://registry.npmjs.org/) | |
| LATEST=$(npm view monsqlize dist-tags.latest --registry=https://registry.npmjs.org/) | |
| if [ -z "${INTEGRITY}" ] || [ "${LATEST}" != "${VERSION}" ]; then | |
| echo "::error::registry acceptance failed: integrity=${INTEGRITY:-missing}, latest=${LATEST:-missing}, expected=${VERSION}" | |
| exit 1 | |
| fi | |
| mkdir -p "${CONSUMER_DIR}" | |
| cd "${CONSUMER_DIR}" | |
| npm init -y | |
| npm install "monsqlize@${VERSION}" "typescript@5.9.3" "@types/node@25.6.2" --ignore-scripts --no-audit --no-fund --registry=https://registry.npmjs.org/ | |
| node -e "const p=require('monsqlize/package.json'); const M=require('monsqlize'); if(!M || p.version!==process.argv[1] || typeof M.dataTasks?.preview!=='function') process.exit(1)" "${VERSION}" | |
| node --input-type=module -e "import M,{dataTasks} from 'monsqlize'; if(!M || typeof dataTasks?.apply!=='function') process.exit(1)" | |
| node -e "require('node:fs').writeFileSync('consumer.ts', \"import MonSQLize, { dataTasks } from 'monsqlize';\\nvoid MonSQLize; void dataTasks.preview;\\n\")" | |
| ./node_modules/.bin/tsc --noEmit --module NodeNext --moduleResolution NodeNext --target ES2021 consumer.ts | |
| ./node_modules/.bin/monsqlize --version | grep -Fx "${VERSION}" | |
| - name: Summarize release follow-up | |
| shell: bash | |
| run: | | |
| RELEASE_TAG="${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref_name }}" | |
| VERSION=$(node -p "require('./package.json').version") | |
| { | |
| echo "## monSQLize ${VERSION} published" | |
| echo | |
| echo "Registry acceptance and installed-package smoke tests passed for \`${RELEASE_TAG}\`." | |
| echo | |
| echo "1. [Create or confirm the GitHub Release](https://github.com/${GITHUB_REPOSITORY}/releases/new?tag=${RELEASE_TAG})." | |
| echo "2. Run **Deploy Docs to GitHub Pages** with \`release_tag=${RELEASE_TAG}\`." | |
| } >> "${GITHUB_STEP_SUMMARY}" |