name: Package Release Manager
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g., 1.2.3)"
required: true
type: string
permissions:
contents: write
packages: write
jobs:
validate-release:
name: Validate Release
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get version
id: get_version
env:
EVENT_NAME: ${{ github.event_name }}
RELEASE_TAG: ${{ github.event.release.tag_name }}
INPUT_VERSION: ${{ github.event.inputs.version }}
run: |
if [ "$EVENT_NAME" == "release" ]; then
VERSION="$RELEASE_TAG"
VERSION="${VERSION#v}"
else
VERSION="$INPUT_VERSION"
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Validate version format
run: |
VERSION="${{ steps.get_version.outputs.version }}"
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?$ ]]; then
echo "Error: Invalid version format: $VERSION"
exit 1
fi
publish-npm:
name: Publish to NPM Registry
runs-on: ubuntu-latest
needs: validate-release
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
registry-url: "https://registry.npmjs.org"
scope: "@lerianstudio"
- name: Verify package version
run: |
PACKAGE_VERSION=$(node -p "require('./package.json').version")
EXPECTED_VERSION="${{ needs.validate-release.outputs.version }}"
echo "Package version: $PACKAGE_VERSION"
echo "Expected version: $EXPECTED_VERSION"
if [ "$PACKAGE_VERSION" != "$EXPECTED_VERSION" ]; then
echo "Warning: Package version ($PACKAGE_VERSION) doesn't match expected version ($EXPECTED_VERSION)"
echo "This might be expected if the package.json wasn't updated yet"
fi
- name: Install dependencies
run: npm ci
- name: Build package
run: npm run build
- name: Run tests
run: npm test
- name: Check NPM publish status
id: check_npm
run: |
if npm view @lerianstudio/lerian-mcp-server@${{ needs.validate-release.outputs.version }} version 2>/dev/null; then
echo "Package already published"
echo "already_published=true" >> $GITHUB_OUTPUT
else
echo "Package not yet published"
echo "already_published=false" >> $GITHUB_OUTPUT
fi
- name: Publish to NPM
if: steps.check_npm.outputs.already_published == 'false'
run: |
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Verify NPM publication
if: steps.check_npm.outputs.already_published == 'false'
run: |
echo "Waiting for NPM registry to update..."
sleep 10
# Try to verify the package, but don't fail if it's not found immediately
if npm view @lerianstudio/lerian-mcp-server@${{ needs.validate-release.outputs.version }} >/dev/null 2>&1; then
echo "✅ Package successfully published and available!"
npm view @lerianstudio/lerian-mcp-server@${{ needs.validate-release.outputs.version }}
else
echo "⚠️ Package not immediately available, but this is normal for new packages"
echo "It may take a few minutes for NPM to propagate the package"
fi
publish-github-packages:
name: Publish to GitHub Packages
runs-on: ubuntu-latest
needs: validate-release
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "18"
registry-url: "https://npm.pkg.github.com"
scope: "@lerianstudio"
- name: Install dependencies
run: npm ci
- name: Build package
run: npm run build
- name: Configure package for GitHub
run: |
# Create a modified package.json for GitHub Packages
node -e "
const pkg = require('./package.json');
pkg.publishConfig = {
registry: 'https://npm.pkg.github.com',
access: 'public'
};
require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));
"
- name: Publish to GitHub Packages
run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
create-release-notes:
name: Update Release Notes
runs-on: ubuntu-latest
needs: [validate-release, publish-npm, publish-github-packages]
if: github.event_name == 'release'
steps:
- name: Update release notes
uses: actions/github-script@v7
with:
script: |
const version = '${{ needs.validate-release.outputs.version }}';
const releaseId = context.payload.release.id;
const currentBody = context.payload.release.body || '';
const additionalNotes = `
## 📦 Installation
### NPM
\`\`\`bash
npm install -g @lerianstudio/lerian-mcp-server@${version}
# or
npx @lerianstudio/lerian-mcp-server@${version}
\`\`\`
### GitHub Packages
\`\`\`bash
npm install -g @lerianstudio/lerian-mcp-server@${version} --registry=https://npm.pkg.github.com
\`\`\`
`;
await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: releaseId,
body: currentBody + additionalNotes
});