Skip to main content
Glama
publish.yml19 kB
name: Publish to NPM on: # Allow manual publishing - will create release via Release Drafter workflow_dispatch: inputs: version_bump: description: 'Version bump type' required: true default: 'patch' type: choice options: - patch - minor - major - prerelease skip_tests: description: 'Skip tests for emergency releases' required: false default: false type: boolean # Trigger when tags are created (for compatibility with existing auto-release workflows) push: tags: - 'v*' # Allow this workflow to be called from other workflows workflow_call: inputs: version: description: 'Version to publish (e.g., v1.2.3)' required: false type: string skip_tests: description: 'Skip tests for emergency releases' required: false default: false type: boolean secrets: NPM_TOKEN: required: true jobs: # First job: Create or update release via Release Drafter (for manual dispatch only) create-release: if: github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest permissions: contents: write pull-requests: write outputs: release-id: ${{ steps.release.outputs.id }} release-tag: ${{ steps.release.outputs.tag_name }} release-version: ${{ steps.release.outputs.name }} steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - name: Update Release Draft id: drafter uses: release-drafter/release-drafter@v6 with: config-name: release-drafter.yml disable-autolabeler: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Determine next version id: version run: | CURRENT_VERSION="${{ steps.drafter.outputs.resolved_version }}" BUMP_TYPE="${{ github.event.inputs.version_bump }}" echo "Current resolved version: $CURRENT_VERSION" echo "Requested bump type: $BUMP_TYPE" # If Release Drafter already resolved to a new version, use it if [[ -n "$CURRENT_VERSION" && "$CURRENT_VERSION" != "null" ]]; then NEW_VERSION="$CURRENT_VERSION" echo "Using Release Drafter resolved version: $NEW_VERSION" else # Fallback: determine version from package.json and bump type PACKAGE_VERSION=$(node -p "require('./package.json').version") echo "Package.json version: $PACKAGE_VERSION" # Simple version bumping logic IFS='.' read -ra VERSION_PARTS <<< "$PACKAGE_VERSION" MAJOR=${VERSION_PARTS[0]} MINOR=${VERSION_PARTS[1]} PATCH=${VERSION_PARTS[2]} case "$BUMP_TYPE" in major) NEW_VERSION="$((MAJOR + 1)).0.0" ;; minor) NEW_VERSION="$MAJOR.$((MINOR + 1)).0" ;; patch) NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))" ;; prerelease) NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))-beta.1" ;; *) NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))" ;; esac echo "Calculated new version: $NEW_VERSION" fi echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT echo "tag=v$NEW_VERSION" >> $GITHUB_OUTPUT - name: Update package.json version run: | NEW_VERSION="${{ steps.version.outputs.version }}" CURRENT_VERSION=$(node -p "require('./package.json').version") echo "Target version: $NEW_VERSION" echo "Current package.json version: $CURRENT_VERSION" if [[ "$NEW_VERSION" != "$CURRENT_VERSION" ]]; then echo "Updating package.json to version: $NEW_VERSION" npm version $NEW_VERSION --no-git-tag-version echo "✅ Package.json updated from $CURRENT_VERSION to $NEW_VERSION" else echo "✅ Package.json already at correct version: $NEW_VERSION" fi - name: Commit version bump run: | NEW_VERSION="${{ steps.version.outputs.version }}" # Check if there are changes to commit if git diff --exit-code package.json package-lock.json; then echo "✅ No version changes to commit - package.json already at correct version" else echo "📝 Committing version bump changes..." git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add package.json package-lock.json git commit -m "chore: bump version to $NEW_VERSION" git push origin main echo "✅ Version bump committed and pushed" fi - name: Create/Update Release id: release run: | TAG_NAME="${{ steps.version.outputs.tag }}" VERSION="${{ steps.version.outputs.version }}" DRAFT_ID="${{ steps.drafter.outputs.id }}" echo "Creating release with tag: $TAG_NAME" if [[ -n "$DRAFT_ID" && "$DRAFT_ID" != "null" ]]; then echo "Publishing existing draft release: $DRAFT_ID" # Update and publish the draft RELEASE_DATA=$(gh api repos/${{ github.repository }}/releases/$DRAFT_ID \ --method PATCH \ --field tag_name="$TAG_NAME" \ --field name="Release v$VERSION" \ --field draft=false \ --field prerelease=${{ github.event.inputs.version_bump == 'prerelease' }}) else echo "Creating new release" # Create new release RELEASE_DATA=$(gh api repos/${{ github.repository }}/releases \ --method POST \ --field tag_name="$TAG_NAME" \ --field name="Release v$VERSION" \ --field body="Release $VERSION" \ --field draft=false \ --field prerelease=${{ github.event.inputs.version_bump == 'prerelease' }}) fi RELEASE_ID=$(echo "$RELEASE_DATA" | jq -r '.id') RELEASE_TAG=$(echo "$RELEASE_DATA" | jq -r '.tag_name') RELEASE_NAME=$(echo "$RELEASE_DATA" | jq -r '.name') echo "id=$RELEASE_ID" >> $GITHUB_OUTPUT echo "tag_name=$RELEASE_TAG" >> $GITHUB_OUTPUT echo "name=$RELEASE_NAME" >> $GITHUB_OUTPUT echo "✅ Release created: $RELEASE_NAME ($RELEASE_TAG)" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Second job: Test and publish to NPM test-and-publish: runs-on: ubuntu-latest needs: [create-release] # Run if we created a release OR if triggered by tag push OR called from another workflow if: always() && (needs.create-release.result == 'success' || github.event_name == 'push' || github.event_name == 'workflow_call') permissions: contents: write packages: write steps: - name: Checkout code uses: actions/checkout@v6 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - name: Determine version and source id: version run: | if [[ "${{ github.event_name }}" == "workflow_call" && -n "${{ inputs.version }}" ]]; then # Called from another workflow with version TAG_NAME="${{ inputs.version }}" VERSION=${TAG_NAME#v} # Remove 'v' prefix SOURCE="workflow_call" echo "🔄 Publishing from workflow call: ${TAG_NAME} (version: ${VERSION})" elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == refs/tags/* ]]; then # Triggered by tag push TAG_NAME="${{ github.ref_name }}" VERSION=${TAG_NAME#v} # Remove 'v' prefix SOURCE="tag_push" echo "🏷️ Publishing from existing tag: ${TAG_NAME} (version: ${VERSION})" elif [[ "${{ needs.create-release.result }}" == "success" ]]; then # From release creation job TAG_NAME="${{ needs.create-release.outputs.release-tag }}" VERSION=${TAG_NAME#v} # Remove 'v' prefix SOURCE="release_drafter" echo "📝 Publishing from Release Drafter: ${TAG_NAME} (version: ${VERSION})" else echo "❌ Could not determine version source" exit 1 fi echo "version=${VERSION}" >> $GITHUB_OUTPUT echo "source=${SOURCE}" >> $GITHUB_OUTPUT echo "tag=${TAG_NAME}" >> $GITHUB_OUTPUT - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '20' cache: 'npm' registry-url: 'https://registry.npmjs.org' - name: Install dependencies run: npm ci - name: Run linting if: ${{ !inputs.skip_tests && !github.event.inputs.skip_tests }} run: npm run lint - name: Run tests if: ${{ !inputs.skip_tests && !github.event.inputs.skip_tests }} run: npm test - name: Build project run: | echo "Building project..." npm run build # Verify build completed successfully echo "=== Build Verification ===" if [ -d "dist" ]; then echo "✅ dist directory created" if [ -f "dist/src/index.js" ]; then echo "✅ Main entry point built successfully" echo "File size: $(ls -lh dist/src/index.js | awk '{print $5}')" else echo "❌ Main entry point not built" echo "Contents of dist:" ls -la dist/ || echo "dist directory empty" exit 1 fi else echo "❌ Build failed - no dist directory created" exit 1 fi - name: Test MCP server functionality run: | echo "Testing MCP server functionality before publish..." # Use comprehensive MCP server test script ./scripts/test-mcp-server.sh # Also verify the built server can be syntax-checked if node --check dist/src/index.js; then echo "✅ Built server syntax is valid" else echo "❌ Built server has syntax errors - aborting publish" exit 1 fi - name: Verify package.json run: | echo "Verifying package.json for npm publish..." # Check required fields if ! grep -q '"name"' package.json; then echo "❌ Missing package name" exit 1 fi if ! grep -q '"version"' package.json; then echo "❌ Missing package version" exit 1 fi if ! grep -q '"description"' package.json; then echo "❌ Missing package description" exit 1 fi echo "✅ Package.json is valid for publishing" - name: Sync package.json with release version run: | VERSION="${{ steps.version.outputs.version }}" CURRENT_VERSION=$(node -p "require('./package.json').version") echo "Target version: $VERSION" echo "Current package.json version: $CURRENT_VERSION" if [[ "$VERSION" != "$CURRENT_VERSION" ]]; then echo "Updating package.json to version: $VERSION" npm version $VERSION --no-git-tag-version echo "✅ Package.json updated from $CURRENT_VERSION to $VERSION" else echo "✅ Package.json already at correct version: $VERSION" fi echo "NEW_VERSION=$VERSION" >> $GITHUB_ENV - name: Verify distribution package run: | echo "Verifying distribution package..." # Debug: Check what files exist echo "=== Build Output Debug ===" echo "Current directory: $(pwd)" echo "Files in current directory:" ls -la echo "Checking for dist directory:" if [ -d "dist" ]; then echo "✅ dist directory exists" echo "Contents of dist:" ls -la dist/ if [ -d "dist/src" ]; then echo "✅ dist/src directory exists" echo "Contents of dist/src:" ls -la dist/src/ if [ -f "dist/src/index.js" ]; then echo "✅ dist/src/index.js exists" else echo "❌ dist/src/index.js missing" exit 1 fi else echo "❌ dist/src directory missing" exit 1 fi else echo "❌ dist directory missing - build failed" exit 1 fi echo "✅ Distribution package verification complete" - name: Test package installation run: | echo "Testing package installation..." # Test package creation directly from main directory (not npm-package) echo "=== Testing Package Creation ===" npm pack --dry-run # Verify main entry point exists MAIN_ENTRY=$(node -p "require('./package.json').main") echo "Checking for main entry point: $MAIN_ENTRY" if [ ! -f "$MAIN_ENTRY" ]; then echo "❌ Main entry point not found: $MAIN_ENTRY" echo "Available files:" find . -name "*.js" -type f | head -10 exit 1 else echo "✅ Main entry point found: $MAIN_ENTRY" echo "File size: $(ls -lh "$MAIN_ENTRY" | awk '{print $5}')" fi # Test that the entry point is valid JavaScript if node --check "$MAIN_ENTRY"; then echo "✅ Main entry point has valid syntax" else echo "❌ Main entry point has syntax errors" exit 1 fi echo "✅ Package is ready for publishing" - name: Publish to NPM run: | VERSION="${{ steps.version.outputs.version }}" TAG_NAME="${{ steps.version.outputs.tag }}" # Determine npm dist-tag based on version type if [[ "${{ github.event.inputs.version_bump }}" == "prerelease" ]] || [[ "$VERSION" == *"beta"* ]] || [[ "$VERSION" == *"alpha"* ]] || [[ "$VERSION" == *"rc"* ]]; then echo "Publishing prerelease version: $VERSION" npm publish --tag beta PUBLISH_TAG="beta" else echo "Publishing stable version: $VERSION" # Publish with explicit 'latest' tag to ensure it's set correctly npm publish --tag latest PUBLISH_TAG="latest" fi echo "✅ Successfully published to NPM" echo " Version: $VERSION" echo " Tag: $TAG_NAME" echo " NPM dist-tag: $PUBLISH_TAG" echo " Package URL: https://www.npmjs.com/package/mcp-adr-analysis-server/v/$VERSION" echo "NPM_PUBLISH_TAG=$PUBLISH_TAG" >> $GITHUB_ENV echo "NPM_PACKAGE_URL=https://www.npmjs.com/package/mcp-adr-analysis-server/v/$VERSION" >> $GITHUB_ENV env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - name: Verify NPM dist-tags run: | VERSION="${{ steps.version.outputs.version }}" PUBLISH_TAG="${{ env.NPM_PUBLISH_TAG }}" echo "Verifying npm dist-tags..." # Wait a moment for npm registry to update sleep 2 # Check that the version exists if npm view mcp-adr-analysis-server@$VERSION version >/dev/null 2>&1; then echo "✅ Version $VERSION exists on npm" else echo "⚠️ Version $VERSION not yet visible on npm (may need a moment to propagate)" fi # Check dist-tags DIST_TAGS=$(npm view mcp-adr-analysis-server dist-tags --json 2>/dev/null || echo "{}") echo "Current npm dist-tags:" echo "$DIST_TAGS" | jq '.' || echo "$DIST_TAGS" # Verify our tag is set correctly TAG_VERSION=$(npm view mcp-adr-analysis-server@$PUBLISH_TAG version 2>/dev/null || echo "") if [[ "$TAG_VERSION" == "$VERSION" ]]; then echo "✅ NPM dist-tag '$PUBLISH_TAG' correctly points to version $VERSION" else echo "⚠️ NPM dist-tag '$PUBLISH_TAG' points to $TAG_VERSION (expected $VERSION)" fi - name: Update GitHub Release with NPM info if: ${{ steps.version.outputs.source == 'release_drafter' }} run: | RELEASE_ID="${{ needs.create-release.outputs.release-id }}" VERSION="${{ steps.version.outputs.version }}" PUBLISH_TAG="${{ env.NPM_PUBLISH_TAG }}" # Get current release body CURRENT_BODY=$(gh api repos/${{ github.repository }}/releases/$RELEASE_ID --jq '.body') # Create NPM publication info using printf to avoid YAML linter issues NPM_INFO=$(printf '\n\n## 📦 NPM Publication\n\nThis release has been published to NPM:\n\n- **Package**: [`mcp-adr-analysis-server@%s`](https://www.npmjs.com/package/mcp-adr-analysis-server/v/%s)\n- **Install**: `npm install -g mcp-adr-analysis-server@%s`\n- **Tag**: `%s`\n\n---\n🤖 NPM publication completed automatically' "$VERSION" "$VERSION" "$VERSION" "$PUBLISH_TAG") # Combine current body with NPM info UPDATED_BODY="${CURRENT_BODY}${NPM_INFO}" # Update the release gh api repos/${{ github.repository }}/releases/$RELEASE_ID \ --method PATCH \ --field body="$UPDATED_BODY" echo "✅ Updated GitHub release with NPM publication info" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Notify success run: | VERSION="${{ steps.version.outputs.version }}" TAG_NAME="${{ steps.version.outputs.tag }}" SOURCE="${{ steps.version.outputs.source }}" PUBLISH_TAG="${{ env.NPM_PUBLISH_TAG }}" PACKAGE_URL="${{ env.NPM_PACKAGE_URL }}" echo "" echo "================================================" echo "🎉 Successfully published to NPM!" echo "================================================" echo "📦 Package: mcp-adr-analysis-server" echo "🏷️ Version: $VERSION" echo "🔖 Git Tag: $TAG_NAME" echo "📌 NPM dist-tag: $PUBLISH_TAG" echo "📝 Source: $SOURCE" echo "🔗 Package URL: $PACKAGE_URL" echo "📥 Install: npm install -g mcp-adr-analysis-server@$VERSION" echo "================================================"

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tosin2013/mcp-adr-analysis-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server