Skip to content

Merge pull request #1 from loopengine/feat/1.0.0-rc.0-surface-reconci… #20

Merge pull request #1 from loopengine/feat/1.0.0-rc.0-surface-reconci…

Merge pull request #1 from loopengine/feat/1.0.0-rc.0-surface-reconci… #20

Workflow file for this run

# Release workflow for @loop-engine/* OSS packages
#
# Normal publish trigger:
# git tag v0.2.0 && git push --tags
# → workflow fires automatically, no manual dispatch needed
#
# Pipeline test (dry run):
# GitHub → Actions → RC tag release → Run workflow
# → leave dry_run CHECKED → run
# → exercises install, build, validate:publish, and pnpm publish --dry-run
#
# Manual dispatch with dry_run UNCHECKED:
# Only allowed from main or a version tag — workflow will hard-fail otherwise.
# Use only as an emergency escape hatch, not as a routine publish path.
#
# Tag pushes: inputs.dry_run is undefined; guard step uses if: ${{ !inputs.dry_run }} so it still
# runs, and startsWith(github.ref, 'refs/tags/') passes immediately — do not change that behavior.
#
# Trusted publishing (OIDC): do NOT set NODE_AUTH_TOKEN / NPM_TOKEN on the publish step — that forces token auth and
# yields EOTP in CI. npm + pnpm use the GitHub OIDC token when id-token: write is set and npm CLI is new enough.
# Requirements (npm docs): Node >= 22.14.0, npm CLI >= 11.5.1. Use Node 24 on the runner — it bundles npm 11.x. Do not run
# `npm install -g npm@...` here; it can break the toolcache install (e.g. MODULE_NOT_FOUND promise-retry).
# Each published package needs Trusted Publisher on npmjs (same repo + workflow filename rc-tag-release.yml).
#
# Optional: NPM_READ_TOKEN + NODE_AUTH_TOKEN only if you add private @scope deps during install (public monorepo: omit).
name: RC tag release
on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
dry_run:
description: "Dry run only — does not publish to npm. Uncheck only from main with a version tag pushed."
type: boolean
default: true
required: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
publish:
name: Publish to npm
runs-on: ubuntu-latest
permissions:
contents: write # required to create GitHub Releases
id-token: write # npm provenance (links tarball to this workflow run)
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9.0.0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
cache: pnpm
- name: Show Node and npm versions (OIDC needs npm >= 11.5.1)
run: node --version && npm --version
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build all packages
run: pnpm build
- name: Validate no workspace:* in publish targets
run: pnpm validate:publish
- name: Enforce main or tag for real publish
if: ${{ !inputs.dry_run }}
run: |
IS_TAG=${{ startsWith(github.ref, 'refs/tags/') }}
IS_MAIN=${{ github.ref_name == 'main' }}
if [ "$IS_TAG" != "true" ] && [ "$IS_MAIN" != "true" ]; then
echo "❌ Real publish is only allowed from main or a version tag."
echo " Current ref: ${{ github.ref }}"
echo " To test the pipeline safely, re-run with dry_run checked."
exit 1
fi
echo "✅ Ref check passed: ${{ github.ref }}"
- name: Publish to npm
run: |
FLAGS="--access public --no-git-checks"
if [ "${{ inputs.dry_run }}" = "true" ]; then
FLAGS="$FLAGS --dry-run"
echo "ℹ️ Dry run mode — no packages will be published"
fi
# Provenance is automatic with trusted publishing; do not pass NODE_AUTH_TOKEN (token auth → EOTP in CI).
pnpm publish -r $FLAGS
# Skip only on workflow_dispatch with dry_run (inputs undefined on tag push — do not use !inputs.dry_run alone).
- name: Create GitHub Release
if: ${{ github.event_name != 'workflow_dispatch' || !inputs.dry_run }}
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
body: |
## @loop-engine ${{ github.ref_name }}
Published packages:
- See [npm @loop-engine org](https://www.npmjs.com/org/loop-engine) for full package list and changelogs.
### Install
```bash
npm install @loop-engine/sdk@${{ github.ref_name }}
```
### What changed
See [CHANGELOG.md](https://github.com/loopengine/loop-engine/blob/main/CHANGELOG.md)
for detailed changes, or view the [npm release history](https://www.npmjs.com/package/@loop-engine/sdk?activeTab=versions).
draft: false
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }}
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Verify clean install
if: github.event_name == 'push'
run: |
VERSION="${GITHUB_REF_NAME#v}"
mkdir -p /tmp/install-test && cd /tmp/install-test
npm init -y
npm install "@loop-engine/sdk@${VERSION}"
node -e "const { createLoopSystem } = require('@loop-engine/sdk'); console.log('✅ @loop-engine/sdk installs cleanly')"