Sync packages from monorepo (3d5eb83) #92
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
| name: Publish packages to npm | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| jobs: | |
| publish: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 2 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "24" | |
| - name: Install dependencies | |
| run: corepack enable && YARN_ENABLE_IMMUTABLE_INSTALLS=false yarn install | |
| - name: Build publishable packages | |
| run: | | |
| set -e | |
| for dir in packages/*/; do | |
| if [ -f "$dir/package.json" ]; then | |
| is_private=$(node -p "try { require('./$dir/package.json').private || false } catch(e) { false }") | |
| has_build=$(node -p "try { !!require('./$dir/package.json').scripts?.build } catch(e) { false }") | |
| if [ "$is_private" != "true" ] && [ "$has_build" = "true" ]; then | |
| echo "🔨 Building $dir" | |
| cd "$dir" | |
| yarn build | |
| cd - | |
| fi | |
| fi | |
| done | |
| - name: Publish changed packages | |
| id: publish | |
| run: | | |
| failed="" | |
| published="" | |
| skipped="" | |
| for dir in packages/*/; do | |
| if [ ! -f "$dir/package.json" ]; then | |
| continue | |
| fi | |
| name=$(node -p "require('./$dir/package.json').name") | |
| # Skip private packages | |
| is_private=$(node -p "try { require('./$dir/package.json').private || false } catch(e) { false }") | |
| if [ "$is_private" = "true" ]; then | |
| skipped="$skipped $name" | |
| continue | |
| fi | |
| # Check if any files changed in this package (skip on workflow_dispatch — publish all) | |
| if [ "${{ github.event_name }}" = "push" ]; then | |
| changed=$(git diff --name-only HEAD~1 -- "$dir" | head -1) | |
| if [ -z "$changed" ]; then | |
| skipped="$skipped $name" | |
| continue | |
| fi | |
| fi | |
| # Get the current version from npm, default to 0.0.0 if unpublished | |
| current=$(npm view "$name" version 2>/dev/null || echo "0.0.0") | |
| # Increment patch version | |
| IFS='.' read -r major minor patch <<< "$current" | |
| next_version="$major.$minor.$((patch + 1))" | |
| echo "📦 Publishing $name@$next_version (was $current)" | |
| cd "$dir" | |
| # Clean package.json: set version, strip devDeps, resolve workspace:/catalog: refs | |
| node -e " | |
| const fs = require('fs'); | |
| const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8')); | |
| pkg.version = '$next_version'; | |
| delete pkg.devDependencies; | |
| for (const depType of ['dependencies', 'peerDependencies']) { | |
| if (!pkg[depType]) continue; | |
| for (const [k, v] of Object.entries(pkg[depType])) { | |
| if (v.startsWith('workspace:') || v.startsWith('catalog:')) { | |
| pkg[depType][k] = '*'; | |
| } | |
| } | |
| } | |
| fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n'); | |
| " | |
| if npm publish --provenance --access public; then | |
| published="$published $name@$next_version" | |
| else | |
| echo "⚠️ Failed to publish $name@$next_version" | |
| failed="$failed $name@$next_version" | |
| fi | |
| cd - | |
| done | |
| # Write job summary | |
| echo "## Publish summary" >> "$GITHUB_STEP_SUMMARY" | |
| if [ -n "$published" ]; then | |
| echo "### Published" >> "$GITHUB_STEP_SUMMARY" | |
| for pkg in $published; do | |
| echo "- $pkg" >> "$GITHUB_STEP_SUMMARY" | |
| done | |
| fi | |
| if [ -n "$failed" ]; then | |
| echo "### Failed" >> "$GITHUB_STEP_SUMMARY" | |
| for pkg in $failed; do | |
| echo "- $pkg" >> "$GITHUB_STEP_SUMMARY" | |
| done | |
| fi | |
| if [ -n "$skipped" ]; then | |
| echo "### Skipped" >> "$GITHUB_STEP_SUMMARY" | |
| for pkg in $skipped; do | |
| echo "- $pkg" >> "$GITHUB_STEP_SUMMARY" | |
| done | |
| fi | |
| if [ -z "$published" ] && [ -z "$failed" ]; then | |
| echo "No packages to publish." >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| if [ -n "$failed" ]; then | |
| echo "publish_failed=true" >> "$GITHUB_OUTPUT" | |
| echo "failed_packages=$failed" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Notify Slack on publish failure | |
| if: steps.publish.outputs.publish_failed == 'true' | |
| uses: slackapi/slack-github-action@v2.1.0 | |
| with: | |
| webhook: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| webhook-type: incoming-webhook | |
| payload: | | |
| { | |
| "text": "npm publish failed for:${{ steps.publish.outputs.failed_packages }}\n<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View run>" | |
| } |