Merge pull request #1 from loopengine/feat/1.0.0-rc.0-surface-reconci… #20
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
| # 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')" |