#!/bin/bash
# Local test script for publishing pipeline
# This simulates what the CI will do without actually publishing
# Run this before pushing to catch errors early!
set -e # Exit on error
echo "🧪 Testing Publishing Pipeline Locally"
echo "======================================"
echo ""
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Test function
test_step() {
echo -n " $1... "
}
pass() {
echo -e "${GREEN}✅${NC}"
}
fail() {
echo -e "${RED}❌${NC}"
echo " Error: $1"
exit 1
}
warn() {
echo -e "${YELLOW}⚠️ $1${NC}"
}
# ============================================
# 1. Check package configuration
# ============================================
echo "📦 1. Checking package configuration"
echo "------------------------------------"
test_step "Checking package.json exists"
if [ -f "package.json" ]; then
pass
else
fail "package.json not found"
fi
test_step "Validating package.json fields"
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');
" 2>/dev/null && pass || fail "Invalid package.json fields"
test_step "Checking server.json exists"
if [ -f "server.json" ]; then
pass
else
fail "server.json not found"
fi
test_step "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);
}
" 2>/dev/null && pass || fail "Invalid server.json"
test_step "Checking manifest.json exists"
if [ -f "manifest.json" ]; then
pass
else
fail "manifest.json not found"
fi
test_step "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');
}
" 2>/dev/null && pass || fail "Invalid manifest.json"
test_step "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 and server.json versions do not match');
}
if (pkg.version !== manifest.version) {
throw new Error('package.json and manifest.json versions do not match');
}
" 2>/dev/null && pass || fail "Version mismatch between files"
echo ""
# ============================================
# 2. Check build
# ============================================
echo "🔨 2. Testing build"
echo "------------------------------------"
test_step "Running TypeScript build"
npm run build > /dev/null 2>&1 && pass || fail "Build failed"
test_step "Checking dist/ directory exists"
if [ -d "dist" ]; then
pass
else
fail "dist directory not found after build"
fi
test_step "Checking dist/index.js exists"
if [ -f "dist/index.js" ]; then
pass
else
fail "dist/index.js not found"
fi
test_step "Checking dist/cli.js exists"
if [ -f "dist/cli.js" ]; then
pass
else
fail "dist/cli.js not found"
fi
echo ""
# ============================================
# 3. Test .mcpb build
# ============================================
echo "📦 3. Testing .mcpb build"
echo "------------------------------------"
test_step "Checking build-mcpb.sh exists"
if [ -f "scripts/build-mcpb.sh" ]; then
pass
else
fail "scripts/build-mcpb.sh not found"
fi
test_step "Building .mcpb file"
./scripts/build-mcpb.sh > /dev/null 2>&1 && pass || fail ".mcpb build failed"
test_step "Checking .mcpb file was created"
if [ -f "hn-mcp.mcpb" ]; then
pass
else
fail "hn-mcp.mcpb not found after build"
fi
test_step "Checking .mcpb size is reasonable"
SIZE=$(stat -f%z "hn-mcp.mcpb" 2>/dev/null || stat -c%s "hn-mcp.mcpb" 2>/dev/null)
if [ "$SIZE" -gt 1000000 ] && [ "$SIZE" -lt 10000000 ]; then
pass
else
warn ".mcpb size is $SIZE bytes (expected 1-10MB)"
fi
echo ""
# ============================================
# 4. Test npm publish (dry-run)
# ============================================
echo "📤 4. Testing npm publish (dry-run)"
echo "------------------------------------"
test_step "Running npm publish --dry-run"
npm publish --dry-run > /dev/null 2>&1 && pass || fail "npm publish dry-run failed"
echo ""
# ============================================
# 5. Check required files
# ============================================
echo "📋 5. Checking required files"
echo "------------------------------------"
REQUIRED_FILES=(
"README.md"
"LICENSE"
"package.json"
"server.json"
"manifest.json"
"tsconfig.json"
"Dockerfile"
".gitignore"
".env.example"
)
for file in "${REQUIRED_FILES[@]}"; do
test_step "Checking $file"
if [ -f "$file" ]; then
pass
else
fail "$file not found"
fi
done
echo ""
# ============================================
# 6. Security checks
# ============================================
echo "🔒 6. Security checks"
echo "------------------------------------"
test_step "Checking for .env file in git"
if git ls-files | grep -q "^\.env$"; then
fail ".env file is tracked in git (should be in .gitignore)"
else
pass
fi
test_step "Checking for sensitive data in package"
if npm pack --dry-run 2>&1 | grep -qi "\.env\|credentials\|secrets"; then
warn "Potential sensitive files in package"
else
pass
fi
echo ""
# ============================================
# 7. Test MCP Publisher (optional)
# ============================================
echo "🚀 7. Testing MCP Publisher (optional)"
echo "------------------------------------"
if command -v curl &> /dev/null; then
test_step "Downloading MCP Publisher"
ARCH=$(uname -m)
if [ "$ARCH" = "x86_64" ]; then
ARCH="amd64"
elif [ "$ARCH" = "aarch64" ]; then
ARCH="arm64"
fi
curl -L "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.0/mcp-publisher_Linux_${ARCH}.tar.gz" -o mcp-publisher.tar.gz 2>/dev/null && pass || warn "Could not download MCP Publisher"
if [ -f "mcp-publisher.tar.gz" ]; then
test_step "Extracting MCP Publisher"
tar xzf mcp-publisher.tar.gz 2>/dev/null && pass || warn "Could not extract"
if [ -f "mcp-publisher" ]; then
test_step "Running MCP Publisher --version"
chmod +x ./mcp-publisher
./mcp-publisher --version > /dev/null 2>&1 && pass || warn "MCP Publisher not working"
rm -f mcp-publisher mcp-publisher.tar.gz
fi
fi
else
warn "curl not found, skipping MCP Publisher test"
fi
echo ""
# ============================================
# Summary
# ============================================
echo "✅ All tests passed!"
echo ""
echo "📝 Next steps:"
echo " 1. Review the changes"
echo " 2. Commit and push to GitHub"
echo " 3. Create a new tag: git tag v<version>"
echo " 4. Push the tag: git push origin v<version>"
echo " 5. GitHub Actions will handle the rest"
echo ""
echo "🚀 Ready to publish!"