name: Publish package to npm on: # Release automatically when a merge to development bumps the version in # package.json: the workflow publishes to npm and creates the matching # GitHub Release. Merges that keep the version unchanged are a no-op. push: branches: [development] # Fallbacks: publish a manually created GitHub Release, or run the # workflow from the Actions tab. Both are safe to re-run — each step # checks whether its outcome (npm version, git tag) already exists. release: types: [published] workflow_dispatch: permissions: # Required to create the GitHub Release and push the version tag. contents: write # Required for npm Trusted Publishing (OIDC) — exchanges a short-lived # token with npm at publish time, so no NPM_TOKEN secret is needed. id-token: write jobs: publish: name: Publish to npm runs-on: ubuntu-latest env: HUSKY: 0 GH_TOKEN: ${{ github.token }} steps: - name: Checkout uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 22 cache: npm registry-url: https://registry.npmjs.org # Trusted Publishing requires npm >= 11.5.1, newer than the version # bundled with Node 22. - name: Update npm run: npm install -g npm@latest - name: Determine version id: version run: echo "version=$(node -p "require('./package.json').version")" >> "$GITHUB_OUTPUT" - name: Check whether this version is already on npm id: npm-check run: | if npm view "ontouml-js@${{ steps.version.outputs.version }}" version --json > /dev/null 2>&1; then echo "published=true" >> "$GITHUB_OUTPUT" echo "ontouml-js@${{ steps.version.outputs.version }} is already on npm; skipping publish." else echo "published=false" >> "$GITHUB_OUTPUT" fi - name: Install dependencies if: steps.npm-check.outputs.published == 'false' run: npm ci # prepublishOnly type-checks (tsc), runs the test suite, and rebuilds # dist/ before the package is published; the files whitelist in # package.json keeps the tarball to dist/ (+ README and LICENSE). # Trusted Publishing authenticates via OIDC and attaches provenance # automatically — no token required. - name: Publish if: steps.npm-check.outputs.published == 'false' run: npm publish --access public # A Release created here with GITHUB_TOKEN does not re-trigger this # workflow (GitHub suppresses recursive workflow events), which is why # the npm publish above lives in the same run instead of a separate # release-triggered one. - name: Create GitHub Release if: github.event_name == 'push' run: | TAG="v${{ steps.version.outputs.version }}" if gh release view "$TAG" > /dev/null 2>&1; then echo "Release $TAG already exists; skipping." else gh release create "$TAG" --target "$GITHUB_SHA" --title "$TAG" --generate-notes fi