From 901496898387ef3386b96d79003f97998c7da849 Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 21 Feb 2026 17:05:27 -0800 Subject: [PATCH 1/2] Adding publish npm package workflow --- .github/workflows/publish-npm-package.yaml | 123 +++++++++++++++++++++ docs/publish-npm-package/README.md | 65 +++++++++++ 2 files changed, 188 insertions(+) create mode 100644 .github/workflows/publish-npm-package.yaml create mode 100644 docs/publish-npm-package/README.md diff --git a/.github/workflows/publish-npm-package.yaml b/.github/workflows/publish-npm-package.yaml new file mode 100644 index 0000000..74349d7 --- /dev/null +++ b/.github/workflows/publish-npm-package.yaml @@ -0,0 +1,123 @@ +name: Publish npm Package + +on: + workflow_call: + inputs: + package-name: + required: true + type: string + description: "The npm package name (e.g. `@datum-cloud/datum-ui`)" + package-path: + required: true + type: string + description: "Path to the package directory relative to the repo root (e.g. `packages/datum-ui`)" + node-version: + required: false + type: number + description: "Node.js version to use" + default: 24 + outputs: + new-version: + description: "The new version that was published (e.g. `v1.2.3`)" + value: ${{ jobs.publish.outputs.new-version }} + +jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + # Skip the bot commit that this workflow itself creates when bumping the + # version. The committer name for GITHUB_TOKEN pushes is "github-actions[bot]". + if: github.actor != 'github-actions[bot]' + outputs: + package: ${{ steps.filter.outputs.package }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check changed paths + id: filter + uses: dorny/paths-filter@v3 + with: + filters: | + package: + - '${{ inputs.package-path }}/**' + + publish: + name: Publish to npm + needs: changes + if: needs.changes.outputs.package == 'true' + runs-on: ubuntu-latest + permissions: + contents: write # needed to push the version bump commit and tag + id-token: write # needed for npm trusted publishing (OIDC) + outputs: + new-version: ${{ steps.version.outputs.new-version }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup pnpm + uses: pnpm/action-setup@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ inputs.node-version }} + cache: pnpm + registry-url: https://registry.npmjs.org + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Determine version bump type from PR labels + id: bump-type + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + # Find the PR that was merged into this commit and read its labels. + # Falls back to "patch" if no relevant label is found. + PR_LABELS=$(gh pr list \ + --state merged \ + --base main \ + --search "${{ github.sha }}" \ + --json labels \ + --jq '.[0].labels[].name' 2>/dev/null || true) + + if echo "$PR_LABELS" | grep -q "release:major"; then + echo "type=major" >> "$GITHUB_OUTPUT" + elif echo "$PR_LABELS" | grep -q "release:minor"; then + echo "type=minor" >> "$GITHUB_OUTPUT" + else + echo "type=patch" >> "$GITHUB_OUTPUT" + fi + + - name: Configure git for version bump commit + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Bump version and create git tag + id: version + working-directory: ${{ inputs.package-path }} + run: | + NEW_VERSION=$(npm version ${{ steps.bump-type.outputs.type }} \ + --message "chore: release ${{ inputs.package-name }} v%s [skip ci]") + echo "new-version=${NEW_VERSION}" >> "$GITHUB_OUTPUT" + + - name: Push version bump commit and tag + run: git push origin main --follow-tags + + - name: Build package + run: pnpm --filter ${{ inputs.package-name }} build + + - name: Publish to npm + working-directory: ${{ inputs.package-path }} + run: pnpm publish --no-git-checks --access public --provenance + + - name: Summary + run: | + echo "### Published ${{ steps.version.outputs.new-version }}" >> "$GITHUB_STEP_SUMMARY" + echo "" >> "$GITHUB_STEP_SUMMARY" + echo "Package: \`${{ inputs.package-name }}\`" >> "$GITHUB_STEP_SUMMARY" + echo "Registry: https://www.npmjs.com/package/${{ inputs.package-name }}" >> "$GITHUB_STEP_SUMMARY" diff --git a/docs/publish-npm-package/README.md b/docs/publish-npm-package/README.md new file mode 100644 index 0000000..ac5d8de --- /dev/null +++ b/docs/publish-npm-package/README.md @@ -0,0 +1,65 @@ +# Publish npm Package + +The `.github/workflows/publish-npm-package.yaml` reusable GitHub Action +automatically versions and publishes a pnpm monorepo package to **npm**. + +It detects changes to the package path on every push to `main`, determines the +version bump type from PR labels (`release:major`, `release:minor`, or +`patch` as the default), commits the version bump, and publishes with +[npm provenance](https://docs.npmjs.com/generating-provenance-statements). + +## Inputs + +- **package-name** (required): The npm package name (e.g. `@datum-cloud/datum-ui`). +- **package-path** (required): Path to the package directory relative to the + repo root (e.g. `packages/datum-ui`). +- **node-version** (optional, default: `24`): Node.js version to use. + +## Outputs + +- **new-version**: The new version that was published (e.g. `v1.2.3`). + +## Version Bump Strategy + +The workflow reads labels from the PR that was merged into the triggering +commit: + +| Label | Bump | +|-------|------| +| `release:major` | major | +| `release:minor` | minor | +| _(none)_ | patch | + +## Best Practices + +- Always use a tagged version when referencing this workflow to prevent + unexpected breaking changes. +- Add `release:major` or `release:minor` labels to PRs before merging when + you want a non-patch bump. +- The workflow skips bot commits automatically, so the version bump commit it + pushes will not trigger a second publish run. + +## Workflow Example + +Create a workflow in your repository (e.g., `.github/workflows/publish.yaml`) +that calls this reusable action: + +```yaml +name: Publish datum-ui + +on: + push: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + publish-datum-ui: + uses: datum-cloud/actions/.github/workflows/publish-npm-package.yaml@main + with: + package-name: "@datum-cloud/datum-ui" + package-path: packages/datum-ui +``` From d076c663b589a7f4446b4d3eebb06f89f62386dd Mon Sep 17 00:00:00 2001 From: Kevin Date: Sat, 21 Feb 2026 17:12:10 -0800 Subject: [PATCH 2/2] Grouping the redirect to please shellcheck --- .github/workflows/publish-npm-package.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-npm-package.yaml b/.github/workflows/publish-npm-package.yaml index 74349d7..6daf12f 100644 --- a/.github/workflows/publish-npm-package.yaml +++ b/.github/workflows/publish-npm-package.yaml @@ -117,7 +117,9 @@ jobs: - name: Summary run: | - echo "### Published ${{ steps.version.outputs.new-version }}" >> "$GITHUB_STEP_SUMMARY" - echo "" >> "$GITHUB_STEP_SUMMARY" - echo "Package: \`${{ inputs.package-name }}\`" >> "$GITHUB_STEP_SUMMARY" - echo "Registry: https://www.npmjs.com/package/${{ inputs.package-name }}" >> "$GITHUB_STEP_SUMMARY" + { + echo "### Published ${{ steps.version.outputs.new-version }}" + echo "" + echo "Package: \`${{ inputs.package-name }}\`" + echo "Registry: https://www.npmjs.com/package/${{ inputs.package-name }}" + } >> "$GITHUB_STEP_SUMMARY"