name: Test Publishing Pipeline
on:
pull_request:
branches: [main]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: npm ci
- name: Run TypeScript type check
run: npm run typecheck
- name: Build package
run: npm run build
- name: Validate package.json
run: |
echo "Validating package.json..."
node -e "
const pkg = require('./package.json');
if (!pkg.name) throw new Error('Missing package name');
if (pkg.name !== 'hn-mcp') throw new Error('Package name should be hn-mcp');
if (!pkg.version) throw new Error('Missing package version');
if (!pkg.description) throw new Error('Missing description');
if (!pkg.main) throw new Error('Missing main field');
if (!pkg.bin) throw new Error('Missing bin field');
console.log('✅ package.json is valid');
console.log(' Name:', pkg.name);
console.log(' Version:', pkg.version);
console.log(' Description:', pkg.description);
"
- name: Validate server.json
run: |
echo "Validating server.json..."
node -e "
const server = require('./server.json');
const required = ['name', 'version', 'description', 'packages'];
for (const field of required) {
if (!server[field]) throw new Error('Missing field: ' + field);
}
if (server.name !== 'io.github.karanb192/hn-mcp') {
throw new Error('Invalid server name: ' + server.name);
}
console.log('✅ server.json is valid');
console.log(' Name:', server.name);
console.log(' Version:', server.version);
"
- name: Validate manifest.json
run: |
echo "Validating manifest.json..."
node -e "
const manifest = require('./manifest.json');
const required = ['manifest_version', 'name', 'version', 'author', 'server'];
for (const field of required) {
if (!manifest[field]) throw new Error('Missing field: ' + field);
}
if (manifest.name !== 'hn-mcp') {
throw new Error('Invalid manifest name: ' + manifest.name);
}
if (!manifest.server.entry_point) {
throw new Error('Missing server.entry_point');
}
console.log('✅ manifest.json is valid');
console.log(' Name:', manifest.name);
console.log(' Version:', manifest.version);
"
- name: Check version consistency
run: |
echo "Checking version consistency..."
node -e "
const pkg = require('./package.json');
const server = require('./server.json');
const manifest = require('./manifest.json');
if (pkg.version !== server.version) {
throw new Error('package.json (' + pkg.version + ') and server.json (' + server.version + ') versions do not match');
}
if (pkg.version !== manifest.version) {
throw new Error('package.json (' + pkg.version + ') and manifest.json (' + manifest.version + ') versions do not match');
}
console.log('✅ All versions match:', pkg.version);
"
- name: Test npm publish (dry-run)
run: npm publish --dry-run
- name: Build .mcpb desktop extension
run: |
chmod +x scripts/build-mcpb.sh
./scripts/build-mcpb.sh
- name: Verify .mcpb file
run: |
if [ ! -f "hn-mcp.mcpb" ]; then
echo "❌ Error: hn-mcp.mcpb not found!"
exit 1
fi
SIZE=$(stat -c%s "hn-mcp.mcpb" 2>/dev/null || stat -f%z "hn-mcp.mcpb" 2>/dev/null)
SIZE_MB=$((SIZE / 1024 / 1024))
echo "✅ hn-mcp.mcpb created successfully"
echo "📦 Size: ${SIZE_MB}MB"
if [ "$SIZE" -lt 1000000 ]; then
echo "⚠️ Warning: .mcpb file is suspiciously small (< 1MB)"
exit 1
fi
if [ "$SIZE" -gt 20000000 ]; then
echo "⚠️ Warning: .mcpb file is very large (> 20MB)"
fi
- name: Test MCP Publisher
run: |
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
ARCH="amd64"
elif [ "$ARCH" = "aarch64" ]; then
ARCH="arm64"
fi
echo "Downloading MCP Publisher for ${ARCH}..."
curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/mcp-publisher_1.2.3_linux_${ARCH}.tar.gz" -o mcp-publisher.tar.gz
if [ ! -f mcp-publisher.tar.gz ] || [ $(stat -c%s mcp-publisher.tar.gz 2>/dev/null || stat -f%z mcp-publisher.tar.gz) -lt 100 ]; then
echo "❌ Failed to download MCP Publisher"
exit 1
fi
tar xzf mcp-publisher.tar.gz
chmod +x ./mcp-publisher
echo "Testing MCP Publisher..."
./mcp-publisher --version
echo "✅ MCP Publisher is working"
- name: Check for sensitive files
run: |
echo "Checking for sensitive files..."
if git ls-files | grep -q "^\.env$"; then
echo "❌ Error: .env file is tracked in git!"
exit 1
fi
echo "✅ No sensitive files detected"
- name: Generate test summary
if: always()
run: |
echo "## 🧪 Publishing Pipeline Test Results" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ✅ Tests Completed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- TypeScript build: ✅" >> $GITHUB_STEP_SUMMARY
echo "- Configuration validation: ✅" >> $GITHUB_STEP_SUMMARY
echo "- Version consistency: ✅" >> $GITHUB_STEP_SUMMARY
echo "- npm publish dry-run: ✅" >> $GITHUB_STEP_SUMMARY
echo "- .mcpb build: ✅" >> $GITHUB_STEP_SUMMARY
echo "- MCP Publisher: ✅" >> $GITHUB_STEP_SUMMARY
echo "- Security checks: ✅" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📦 Package Info" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
VERSION=$(node -e "console.log(require('./package.json').version)")
echo "- **Version**: $VERSION" >> $GITHUB_STEP_SUMMARY
echo "- **Package**: hn-mcp" >> $GITHUB_STEP_SUMMARY
echo "- **MCP Name**: io.github.karanb192/hn-mcp" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ **Ready for publishing!**" >> $GITHUB_STEP_SUMMARY