Publish Packages #61
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 | |
| on: | |
| push: | |
| branches: [master] | |
| paths: | |
| - "packages/*/package.json" | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| id-token: write | |
| env: | |
| NODE_VERSION: "22" | |
| jobs: | |
| detect-changes: | |
| name: 🔍 Detect Version Changes | |
| runs-on: ubuntu-latest | |
| outputs: | |
| packages: ${{ steps.detect.outputs.packages }} | |
| has-changes: ${{ steps.detect.outputs.has-changes }} | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v5 | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| - name: 🔍 Detect changed package versions | |
| id: detect | |
| run: | | |
| # Function to get package info | |
| get_package_info() { | |
| local pkg_dir=$1 | |
| local pkg_json="${pkg_dir}/package.json" | |
| if [ ! -f "$pkg_json" ]; then | |
| return | |
| fi | |
| local name=$(node -p "require('./${pkg_json}').name") | |
| local version=$(node -p "require('./${pkg_json}').version") | |
| local private=$(node -p "require('./${pkg_json}').private || false") | |
| # Skip private packages | |
| if [ "$private" = "true" ]; then | |
| return | |
| fi | |
| echo "${pkg_dir}|${name}|${version}" | |
| } | |
| # Function to check if version exists on npm | |
| version_exists_on_npm() { | |
| local name=$1 | |
| local version=$2 | |
| # Try to get the specific version from npm | |
| if npm view "${name}@${version}" version 2>/dev/null; then | |
| return 0 # Version exists | |
| else | |
| return 1 # Version doesn't exist | |
| fi | |
| } | |
| changed_packages=() | |
| # Check packages in dependency order (core first, then platform) | |
| for pkg_dir in packages/core packages/platform; do | |
| if [ ! -d "$pkg_dir" ]; then | |
| continue | |
| fi | |
| pkg_info=$(get_package_info "$pkg_dir") | |
| if [ -z "$pkg_info" ]; then | |
| continue | |
| fi | |
| IFS='|' read -r dir name version <<< "$pkg_info" | |
| echo "📦 Checking ${name}@${version}..." | |
| # Check if this version exists on npm | |
| if version_exists_on_npm "$name" "$version"; then | |
| echo "⏭️ Version ${version} already published for ${name}" | |
| else | |
| echo "✨ New version detected: ${name}@${version}" | |
| changed_packages+=("{\"name\":\"${name}\",\"version\":\"${version}\",\"dir\":\"${dir}\"}") | |
| fi | |
| done | |
| # Build JSON array | |
| if [ ${#changed_packages[@]} -eq 0 ]; then | |
| echo "has-changes=false" >> $GITHUB_OUTPUT | |
| echo "packages=[]" >> $GITHUB_OUTPUT | |
| echo "ℹ️ No version changes detected" | |
| else | |
| echo "has-changes=true" >> $GITHUB_OUTPUT | |
| packages_json=$(printf '%s\n' "${changed_packages[@]}" | jq -s -c '.') | |
| echo "packages=${packages_json}" >> $GITHUB_OUTPUT | |
| echo "🎯 Packages to publish:" | |
| echo "${packages_json}" | jq '.' | |
| fi | |
| verify: | |
| name: ✅ Verify All Packages | |
| needs: [detect-changes] | |
| if: needs.detect-changes.outputs.has-changes == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v5 | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| - name: 🔍 Type check | |
| run: npm run type-check | |
| - name: 🎨 Lint | |
| run: npm run lint | |
| - name: 🎨 Format check | |
| run: npm run format:check | |
| - name: 🧪 Test | |
| run: npm run test | |
| - name: 🏗️ Build | |
| run: npm run build | |
| - name: ✅ All checks passed | |
| run: echo "✅ All packages verified successfully" >> $GITHUB_STEP_SUMMARY | |
| publish: | |
| name: 📤 Publish ${{ matrix.package.name }}@${{ matrix.package.version }} | |
| needs: [detect-changes, verify] | |
| if: needs.detect-changes.outputs.has-changes == 'true' && needs.verify.result == 'success' | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| package: ${{ fromJson(needs.detect-changes.outputs.packages) }} | |
| max-parallel: 1 | |
| fail-fast: true | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v5 | |
| - name: 🔧 Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: "npm" | |
| registry-url: "https://registry.npmjs.org" | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| - name: 🏗️ Build all workspace packages | |
| run: npm run build | |
| - name: 📤 Publish to npm | |
| working-directory: ${{ matrix.package.dir }} | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| run: | | |
| echo "📤 Publishing ${{ matrix.package.name }}@${{ matrix.package.version }}" | |
| npm publish --access public | |
| - name: 🏷️ Create git tag | |
| run: | | |
| git config --global user.name "github-actions[bot]" | |
| git config --global user.email "github-actions[bot]@users.noreply.github.com" | |
| # Extract package name without scope | |
| PKG_SHORT_NAME=$(echo "${{ matrix.package.name }}" | sed 's/@agentage\///') | |
| TAG_NAME="${PKG_SHORT_NAME}@${{ matrix.package.version }}" | |
| git tag -a "${TAG_NAME}" -m "Release ${{ matrix.package.name }}@${{ matrix.package.version }}" | |
| git push origin "${TAG_NAME}" | |
| - name: ✅ Published successfully | |
| run: | | |
| echo "🎉 Successfully published ${{ matrix.package.name }}@${{ matrix.package.version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "📦 Package URL: https://www.npmjs.com/package/${{ matrix.package.name }}/v/${{ matrix.package.version }}" >> $GITHUB_STEP_SUMMARY | |
| summary: | |
| name: 📋 Publish Summary | |
| needs: [detect-changes, verify, publish] | |
| if: always() && needs.detect-changes.outputs.has-changes == 'true' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: 📊 Create summary | |
| run: | | |
| echo "## 📦 Package Publishing Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ "${{ needs.verify.result }}" != "success" ]; then | |
| echo "❌ **Verification failed - packages not published**" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Please fix verification errors and try again." >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ needs.publish.result }}" == "success" ]; then | |
| echo "✅ **All packages published successfully!**" >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ needs.publish.result }}" == "skipped" ]; then | |
| echo "⏭️ **Publishing skipped - verification failed**" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "⚠️ **Some packages failed to publish**" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Packages" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| packages='${{ needs.detect-changes.outputs.packages }}' | |
| if [ "${{ needs.verify.result }}" == "success" ] && [ "${{ needs.publish.result }}" == "success" ]; then | |
| echo "$packages" | jq -r '.[] | "- ✅ **\(.name)** version \(.version) - Published"' >> $GITHUB_STEP_SUMMARY | |
| elif [ "${{ needs.verify.result }}" != "success" ]; then | |
| echo "$packages" | jq -r '.[] | "- ❌ **\(.name)** version \(.version) - Verification failed"' >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "$packages" | jq -r '.[] | "- ⏭️ **\(.name)** version \(.version) - Skipped"' >> $GITHUB_STEP_SUMMARY | |
| fi |