name: CI/CD
on:
push:
branches: [main, develop]
tags:
- "v*"
pull_request:
branches: [main]
permissions:
contents: write
packages: write
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [20.x, 22.x, 24.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Run type checking
run: npm run type-check
- name: Run tests
run: npm test
- name: Validate version consistency
shell: bash
run: |
# Check that all version fields match
PACKAGE_VERSION=$(node -pe "require('./package.json').version")
PACKAGE_LOCK_VERSION=$(node -pe "require('./package-lock.json').version")
PACKAGE_LOCK_PACKAGES_VERSION=$(node -pe "require('./package-lock.json').packages[''].version")
echo "Package.json version: $PACKAGE_VERSION"
echo "Package-lock.json version: $PACKAGE_LOCK_VERSION"
echo "Package-lock.json packages version: $PACKAGE_LOCK_PACKAGES_VERSION"
if [ "$PACKAGE_VERSION" != "$PACKAGE_LOCK_VERSION" ]; then
echo "ERROR: package.json version ($PACKAGE_VERSION) does not match package-lock.json version ($PACKAGE_LOCK_VERSION)"
exit 1
fi
if [ "$PACKAGE_VERSION" != "$PACKAGE_LOCK_PACKAGES_VERSION" ]; then
echo "ERROR: package.json version ($PACKAGE_VERSION) does not match package-lock.json packages version ($PACKAGE_LOCK_PACKAGES_VERSION)"
exit 1
fi
echo "✓ All versions are consistent: $PACKAGE_VERSION"
- name: Test package installation
shell: bash
run: |
npm pack
TARBALL=$(ls zibdie-ssh-mcp-server-*.tgz)
npm install -g "./$TARBALL"
ssh-mcp-server --help || echo "CLI test complete"
create-dxt:
needs: test
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Use Node.js 24
uses: actions/setup-node@v4
with:
node-version: 24
cache: "npm"
- name: Install dependencies
run: npm ci
- name: Validate and use existing version
run: |
VERSION=$(node -pe "require('./package.json').version")
echo "Using version from package.json: $VERSION"
# Validate that if this is a tag, it matches the package.json version
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
TAG_VERSION=${GITHUB_REF_NAME#v}
if [ "$VERSION" != "$TAG_VERSION" ]; then
echo "ERROR: package.json version ($VERSION) does not match git tag ($TAG_VERSION)"
echo "Please update package.json version to match the tag or create a tag that matches package.json"
exit 1
fi
fi
# Add version to manifest.json if it doesn't exist
if ! grep -q '"version"' manifest.json 2>/dev/null; then
sed -i.bak "s/\"name\": \"@zibdie\/ssh-mcp-server\",/\"name\": \"@zibdie\/ssh-mcp-server\",\n \"version\": \"$VERSION\",/" manifest.json
rm -f manifest.json.bak
fi
- name: Install DXT CLI
run: npm install -g @anthropic-ai/dxt
- name: Create DXT package
run: |
COMMIT_HASH=$(git rev-parse --short HEAD)
dxt pack
# Rename the generated DXT file to include commit hash
mv *.dxt "zibdie-ssh-mcp-server-${COMMIT_HASH}.dxt" 2>/dev/null || echo "DXT file created"
- name: Upload DXT package as artifact
uses: actions/upload-artifact@v4
with:
name: dxt-package
path: "zibdie-ssh-mcp-server-*.dxt"
retention-days: 7
publish:
needs: create-dxt
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v4
- name: Use Node.js 24
uses: actions/setup-node@v4
with:
node-version: 24
cache: "npm"
registry-url: "https://registry.npmjs.org"
- name: Install dependencies
run: npm ci
- name: Validate version consistency before publishing
run: |
VERSION=$(node -pe "require('./package.json').version")
TAG_VERSION=${GITHUB_REF_NAME#v}
echo "Package.json version: $VERSION"
echo "Git tag version: $TAG_VERSION"
if [ "$VERSION" != "$TAG_VERSION" ]; then
echo "ERROR: package.json version ($VERSION) does not match git tag ($TAG_VERSION)"
echo "Please update package.json version to match the tag before publishing"
exit 1
fi
# Add version to manifest.json if it doesn't exist
if ! grep -q '"version"' manifest.json 2>/dev/null; then
sed -i.bak "s/\"name\": \"@zibdie\/ssh-mcp-server\",/\"name\": \"@zibdie\/ssh-mcp-server\",\n \"version\": \"$VERSION\",/" manifest.json
rm -f manifest.json.bak
fi
echo "✓ Version validation passed: $VERSION"
- name: Publish to NPM
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npm publish
release:
needs: publish
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v4
- name: Use Node.js 24
uses: actions/setup-node@v4
with:
node-version: 24
- name: Download DXT artifact
uses: actions/download-artifact@v4
with:
name: dxt-package
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(node -pe \"require('./package.json').version\")
# Create release notes from template
sed "s/{{VERSION}}/$VERSION/g" release-notes-template.md > release_notes.md
# Create the release
gh release create $GITHUB_REF_NAME \
--title "v$VERSION" \
--notes-file release_notes.md \
--latest \
zibdie-ssh-mcp-server-*.dxt