name: Publish alpha release on: workflow_dispatch: inputs: version: description: Exact package version to publish (for example 0.1.0-alpha.4.8) required: true type: string confirm: description: Type PUBLISH to authorize this alpha release required: true type: string permissions: contents: write id-token: write concurrency: group: npm-release cancel-in-progress: false jobs: publish: if: github.ref == 'refs/heads/main' runs-on: ubuntu-24.04 timeout-minutes: 30 environment: npm-release steps: - name: Check out the selected main commit uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 persist-credentials: false - name: Set up pnpm uses: pnpm/action-setup@0977fd99725f1db4007ccb2928dbb4e90d06cc86 # v6.0.10 with: version: 10.30.3 - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version: 24.15.0 cache: pnpm cache-dependency-path: pnpm-lock.yaml - name: Pin npm for Trusted Publishing shell: bash run: | set -euo pipefail npm install --global npm@11.6.4 --no-fund --no-audit test "$(npm --version)" = "11.6.4" test "$(node --version)" = "v24.15.0" test "$(pnpm --version)" = "10.30.3" - name: Install dependencies from the lockfile run: pnpm --config.minimum-release-age=0 install --frozen-lockfile - name: Validate release input and target availability shell: bash env: GH_TOKEN: ${{ github.token }} VERSION: ${{ inputs.version }} CONFIRM: ${{ inputs.confirm }} run: | set -euo pipefail readonly PACKAGE='dsh-codex-connect' if [[ "$CONFIRM" != 'PUBLISH' ]]; then echo 'The confirmation input must be exactly PUBLISH.' >&2 exit 1 fi if [[ ! "$VERSION" =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)-alpha\.(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*$ ]]; then echo "Version must be a strict alpha semver (got: $VERSION)." >&2 exit 1 fi package_name="$(node -p "JSON.parse(require('fs').readFileSync('package.json', 'utf8')).name")" package_version="$(node -p "JSON.parse(require('fs').readFileSync('package.json', 'utf8')).version")" if [[ "$package_name" != "$PACKAGE" || "$package_version" != "$VERSION" ]]; then echo "Input $VERSION does not match $PACKAGE@$package_version." >&2 exit 1 fi set +e npm_output="$(npm view "$PACKAGE@$VERSION" version --json 2>&1)" npm_status=$? set -e if (( npm_status == 0 )); then echo "npm version $PACKAGE@$VERSION already exists." >&2 exit 1 fi if [[ "$npm_output" != *E404* && "$npm_output" != *'404 Not Found'* && "$npm_output" != *'No match found'* ]]; then printf '%s\n' "$npm_output" >&2 exit 1 fi set +e git ls-remote --exit-code --refs origin "refs/tags/v${VERSION}" >/dev/null 2>&1 tag_status=$? set -e if (( tag_status == 0 )); then echo "Git tag v$VERSION already exists." >&2 exit 1 fi if (( tag_status != 2 )); then echo "Could not verify whether Git tag v$VERSION exists (git status $tag_status)." >&2 exit 1 fi set +e release_output="$(gh release view "v${VERSION}" --repo "$GITHUB_REPOSITORY" 2>&1)" release_status=$? set -e if (( release_status == 0 )); then echo "GitHub release v$VERSION already exists." >&2 exit 1 fi if [[ "$release_output" != *'not found'* && "$release_output" != *'Not Found'* && "$release_output" != *404* ]]; then printf '%s\n' "$release_output" >&2 exit 1 fi - name: Run complete check before publishing run: pnpm run check - name: Publish alpha through npm Trusted Publishing shell: bash env: VERSION: ${{ inputs.version }} run: | set -euo pipefail npm publish --tag alpha --provenance - name: Verify npm version and alpha dist-tag shell: bash env: VERSION: ${{ inputs.version }} run: | set -euo pipefail readonly PACKAGE='dsh-codex-connect' for attempt in 1 2 3 4 5 6; do version_json="$(npm view "$PACKAGE@$VERSION" version --json 2>/dev/null || true)" alpha_json="$(npm view "$PACKAGE" dist-tags.alpha --json 2>/dev/null || true)" if node -e ' const [expected, versionRaw, alphaRaw] = process.argv.slice(1) const parse = (raw) => { try { return JSON.parse(raw) } catch { return raw.trim() } } if (parse(versionRaw) !== expected || parse(alphaRaw) !== expected) process.exit(1) ' "$VERSION" "$version_json" "$alpha_json"; then echo "npm published $PACKAGE@$VERSION with alpha=$VERSION." exit 0 fi if (( attempt < 6 )); then sleep 10 fi done echo "npm did not expose $PACKAGE@$VERSION and dist-tags.alpha=$VERSION after six attempts." >&2 exit 1 - name: Create GitHub prerelease shell: bash env: GH_TOKEN: ${{ github.token }} VERSION: ${{ inputs.version }} run: gh release create "v${VERSION}" --repo "$GITHUB_REPOSITORY" --prerelease --target "$GITHUB_SHA" --generate-notes