Add comprehensive GitHub Actions CI/CD workflows and update documentation

This commit is contained in:
yctimlin
2025-10-31 17:00:48 +00:00
parent 4cfe5ce1fc
commit 5d6b8d0033
4 changed files with 360 additions and 22 deletions
+72
View File
@@ -0,0 +1,72 @@
name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]
jobs:
build-and-test:
name: Build and Type Check
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup 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 TypeScript type check
run: npm run type-check
- name: Build project
run: npm run build
- name: Check build artifacts
run: |
echo "Checking if build artifacts exist..."
test -f dist/index.js || (echo "dist/index.js not found" && exit 1)
test -f dist/server.js || (echo "dist/server.js not found" && exit 1)
test -d dist/frontend || (echo "dist/frontend not found" && exit 1)
echo "All build artifacts present!"
- name: Upload build artifacts
if: matrix.node-version == '20.x'
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: |
dist/
retention-days: 7
lint-check:
name: Lint Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Check for TypeScript errors
run: npm run type-check
+140
View File
@@ -0,0 +1,140 @@
name: Docker Build & Push
on:
push:
branches: [ main ]
tags:
- 'v*.*.*'
pull_request:
branches: [ main ]
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME_MCP: ${{ github.repository }}
IMAGE_NAME_CANVAS: ${{ github.repository }}-canvas
jobs:
build-and-push-mcp:
name: Build and Push MCP Server Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for MCP Server
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MCP }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push MCP Server image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
build-and-push-canvas:
name: Build and Push Canvas Server Image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Canvas Server
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_CANVAS }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Canvas Server image
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile.canvas
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
test-docker-images:
name: Test Docker Images
needs: [build-and-push-mcp, build-and-push-canvas]
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
steps:
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Test Canvas Server image
run: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_CANVAS }}:${{ github.ref_name }}
docker run -d -p 3000:3000 --name test-canvas ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_CANVAS }}:${{ github.ref_name }}
sleep 10
curl -f http://localhost:3000/health || exit 1
docker logs test-canvas
docker stop test-canvas
- name: Test MCP Server image
run: |
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME_MCP }}:${{ github.ref_name }}
echo "MCP Server image pulled successfully"
+106
View File
@@ -0,0 +1,106 @@
name: Publish to NPM
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Tag to publish (e.g., latest, beta, next)'
required: true
default: 'latest'
jobs:
publish:
name: Publish to NPM Registry
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run type check
run: npm run type-check
- name: Build project
run: npm run build
- name: Verify build artifacts
run: |
echo "Verifying build artifacts..."
test -f dist/index.js || (echo "ERROR: dist/index.js not found" && exit 1)
test -f dist/server.js || (echo "ERROR: dist/server.js not found" && exit 1)
test -d dist/frontend || (echo "ERROR: dist/frontend not found" && exit 1)
echo "All required artifacts present!"
- name: Get package version
id: package-version
run: echo "version=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
- name: Check if version exists on NPM
id: check-version
run: |
if npm view mcp-excalidraw-server@${{ steps.package-version.outputs.version }} version 2>/dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
echo "Version ${{ steps.package-version.outputs.version }} already exists on NPM"
else
echo "exists=false" >> $GITHUB_OUTPUT
echo "Version ${{ steps.package-version.outputs.version }} does not exist on NPM"
fi
- name: Publish to NPM (Release)
if: github.event_name == 'release' && steps.check-version.outputs.exists == 'false'
run: npm publish --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Publish to NPM (Manual)
if: github.event_name == 'workflow_dispatch' && steps.check-version.outputs.exists == 'false'
run: npm publish --tag ${{ github.event.inputs.tag }} --provenance --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Skip publishing (version exists)
if: steps.check-version.outputs.exists == 'true'
run: |
echo "⚠️ Skipping publish - version ${{ steps.package-version.outputs.version }} already exists on NPM"
echo "Please bump the version in package.json before publishing"
- name: Create GitHub Release Assets
if: github.event_name == 'release'
run: |
tar -czf mcp-excalidraw-server-${{ steps.package-version.outputs.version }}.tar.gz dist/
- name: Upload Release Assets
if: github.event_name == 'release'
uses: softprops/action-gh-release@v1
with:
files: |
mcp-excalidraw-server-${{ steps.package-version.outputs.version }}.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
notify:
name: Publish Notification
needs: publish
runs-on: ubuntu-latest
if: success()
steps:
- name: Success notification
run: |
echo "✅ Package successfully published to NPM!"
echo "View at: https://www.npmjs.com/package/mcp-excalidraw-server"
+42 -22
View File
@@ -1,5 +1,10 @@
# MCP Excalidraw Server: Advanced Live Visual Diagramming with AI Integration
[![CI](https://github.com/yctimlin/mcp_excalidraw/actions/workflows/ci.yml/badge.svg)](https://github.com/yctimlin/mcp_excalidraw/actions/workflows/ci.yml)
[![Docker Build & Push](https://github.com/yctimlin/mcp_excalidraw/actions/workflows/docker.yml/badge.svg)](https://github.com/yctimlin/mcp_excalidraw/actions/workflows/docker.yml)
[![NPM Version](https://img.shields.io/npm/v/mcp-excalidraw-server)](https://www.npmjs.com/package/mcp-excalidraw-server)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
A comprehensive **TypeScript-based** system that combines **Excalidraw's powerful drawing capabilities** with **Model Context Protocol (MCP)** integration, enabling AI agents to create and manipulate diagrams in real-time on a live canvas.
## 🚦 Current Status & Version Information
@@ -149,15 +154,17 @@ http://localhost:3000
#### **Option B: Docker Canvas Server**
1. **Build Docker Image**
**Option B1: Use Pre-built Image from GHCR** (Recommended)
```bash
docker pull ghcr.io/yctimlin/mcp_excalidraw-canvas:latest
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas ghcr.io/yctimlin/mcp_excalidraw-canvas:latest
```
**Option B2: Build Locally**
```bash
git clone https://github.com/yctimlin/mcp_excalidraw.git
cd mcp_excalidraw
docker build -f Dockerfile.canvas -t mcp-excalidraw-canvas .
```
2. **Run Canvas Container**
```bash
docker run -d -p 3000:3000 --name mcp-excalidraw-canvas mcp-excalidraw-canvas
```
@@ -324,13 +331,7 @@ Edit your `claude_desktop_config.json` file:
### **Format 2: Docker MCP Server** ✅ Fully Working
First, build the MCP Docker image:
```bash
cd mcp_excalidraw
docker build -f Dockerfile -t mcp-excalidraw .
```
Then configure:
**Using Pre-built Image from GHCR** (Recommended):
```json
{
"mcpServers": {
@@ -343,13 +344,21 @@ Then configure:
"--network", "host",
"-e", "EXPRESS_SERVER_URL=http://localhost:3000",
"-e", "ENABLE_CANVAS_SYNC=true",
"mcp-excalidraw"
"ghcr.io/yctimlin/mcp_excalidraw:latest"
]
}
}
}
```
**OR Build Locally**:
```bash
cd mcp_excalidraw
docker build -f Dockerfile -t mcp-excalidraw .
```
Then use `mcp-excalidraw` as the image name in the configuration above.
---
## **Configuration for Claude Code**
@@ -377,13 +386,7 @@ Create or edit `.mcp.json` in your project root:
### **Format 2: Docker MCP Server** ✅ Fully Working
First, build the MCP Docker image:
```bash
cd mcp_excalidraw
docker build -f Dockerfile -t mcp-excalidraw .
```
Then configure:
**Using Pre-built Image from GHCR** (Recommended):
```json
{
"mcpServers": {
@@ -396,13 +399,21 @@ Then configure:
"--network", "host",
"-e", "EXPRESS_SERVER_URL=http://localhost:3000",
"-e", "ENABLE_CANVAS_SYNC=true",
"mcp-excalidraw"
"ghcr.io/yctimlin/mcp_excalidraw:latest"
]
}
}
}
```
**OR Build Locally**:
```bash
cd mcp_excalidraw
docker build -f Dockerfile -t mcp-excalidraw .
```
Then use `mcp-excalidraw` as the image name in the configuration above.
### **Alternative: Using Claude CLI**
```bash
@@ -446,6 +457,7 @@ Edit `.cursor/mcp.json`:
### **Format 2: Docker MCP Server** ✅ Fully Working
**Using Pre-built Image from GHCR** (Recommended):
```json
{
"mcpServers": {
@@ -458,13 +470,21 @@ Edit `.cursor/mcp.json`:
"--network", "host",
"-e", "EXPRESS_SERVER_URL=http://localhost:3000",
"-e", "ENABLE_CANVAS_SYNC=true",
"mcp-excalidraw"
"ghcr.io/yctimlin/mcp_excalidraw:latest"
]
}
}
}
```
**OR Build Locally**:
```bash
cd mcp_excalidraw
docker build -f Dockerfile -t mcp-excalidraw .
```
Then use `mcp-excalidraw` as the image name in the configuration above.
---
## **Important Configuration Notes**