Skip to content

Add URL and diff tools #13

Add URL and diff tools

Add URL and diff tools #13

Workflow file for this run

name: Deploy
on:
push:
branches:
- master
workflow_dispatch:
permissions:
contents: read
concurrency:
group: coding-tools-production
cancel-in-progress: false
env:
NODE_VERSION: "24"
jobs:
build:
name: Check and build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- name: Install dependencies
run: npm ci
- name: Build static site
run: npm run build
deploy:
name: Deploy to VPS
needs: build
runs-on: ubuntu-latest
environment: production
steps:
- name: Validate required secrets
env:
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
run: |
if [ -z "${VPS_SSH_KEY}" ]; then
echo "::error::Missing required repository secret: VPS_SSH_KEY"
exit 1
fi
- name: Install SSH key
env:
VPS_SSH_KEY: ${{ secrets.VPS_SSH_KEY }}
run: |
install -m 700 -d ~/.ssh
printf '%s\n' "${VPS_SSH_KEY}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
- name: Trust VPS host key
env:
VPS_HOST: ${{ secrets.VPS_HOST || '35.239.243.94' }}
VPS_PORT: ${{ secrets.VPS_PORT || '22' }}
run: |
mkdir -p ~/.ssh
ssh-keyscan -p "${VPS_PORT}" -H "${VPS_HOST}" >> ~/.ssh/known_hosts
- name: Pull, build, and reload nginx
env:
VPS_HOST: ${{ secrets.VPS_HOST || '35.239.243.94' }}
VPS_USER: ${{ secrets.VPS_USER || 'bylearner' }}
VPS_PORT: ${{ secrets.VPS_PORT || '22' }}
VPS_PATH: ${{ secrets.VPS_PATH || '/home/bylearner/app/CodingTools' }}
WEB_ROOT: ${{ secrets.WEB_ROOT || '/var/www/coding-tools' }}
DEPLOY_REF: ${{ github.sha }}
run: |
ssh -i ~/.ssh/deploy_key -o IdentitiesOnly=yes -p "${VPS_PORT}" "${VPS_USER}@${VPS_HOST}" \
"DEPLOY_REF='${DEPLOY_REF}' VPS_PATH='${VPS_PATH}' WEB_ROOT='${WEB_ROOT}' SERVICE_USER='${VPS_USER}' bash -se" <<'REMOTE'
set -euo pipefail
if [ -f "$HOME/.nvm/nvm.sh" ]; then
. "$HOME/.nvm/nvm.sh"
fi
cd "$VPS_PATH"
git fetch --prune origin master
git reset --hard "$DEPLOY_REF"
npm ci
npm run build
test -f "$VPS_PATH/dist/index.html"
test -f "$VPS_PATH/dist/404.html"
test -f "$VPS_PATH/dist/.well-known/agent-card.json"
npm run a2a:test
NODE_BIN="$(command -v node)"
sudo tee /etc/systemd/system/coding-tools-a2a.service > /dev/null <<EOF
[Unit]
Description=Coding.Tools A2A runtime
After=network.target
[Service]
Type=simple
User=$SERVICE_USER
WorkingDirectory=$VPS_PATH
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=5510
ExecStart=$NODE_BIN server/a2a-runtime.js
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable coding-tools-a2a
sudo systemctl restart coding-tools-a2a
sudo mkdir -p "$WEB_ROOT"
sudo rsync -a --delete --chown=www-data:www-data --chmod=D755,F644 "$VPS_PATH/dist/" "$WEB_ROOT/"
pkill -f '[e]leventy.*serve' 2>/dev/null || true
sudo tee /etc/nginx/sites-available/default > /dev/null <<EOF
server {
listen 80 default_server;
listen [::]:80 default_server;
root $WEB_ROOT;
index index.html;
error_page 404 /404.html;
location = /.well-known/agent-card.json {
expires 5m;
add_header Cache-Control "public, max-age=300";
try_files \$uri =404;
}
location / {
try_files \$uri \$uri/ \$uri.html =404;
}
location = /a2a {
proxy_pass http://127.0.0.1:5510/a2a;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location ^~ /a2a/ {
proxy_pass http://127.0.0.1:5510/a2a/;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location = /mcp {
proxy_pass http://127.0.0.1:5510/mcp;
proxy_http_version 1.1;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto \$scheme;
}
location ~* \.(css|js|svg|png|jpg|jpeg|gif|ico|json|webp|wasm|onnx)$ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files \$uri =404;
}
}
EOF
sudo nginx -t
sudo systemctl reload nginx
curl -fsS -o /dev/null http://localhost:80/
curl -fsS -o /dev/null http://localhost:80/.well-known/agent-card.json
curl -fsS -o /dev/null http://localhost:80/a2a/healthz
curl -fsS -o /dev/null \
-H 'Content-Type: application/a2a+json' \
-H 'A2A-Version: 1.0' \
-d '{"message":{"role":"ROLE_USER","messageId":"deploy-smoke","metadata":{"toolId":"sha256-generator"},"parts":[{"text":"abc"}]}}' \
http://localhost:80/a2a/message:send
curl -fsS -o /dev/null \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2025-06-18' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"sha256-generator","arguments":{"input":"abc"}}}' \
http://localhost:80/mcp
REMOTE
- name: Verify public site
env:
PUBLIC_URL: ${{ secrets.PUBLIC_URL || 'http://35.239.243.94/' }}
run: |
curl -fsS --location --max-time 20 --output /dev/null "${PUBLIC_URL}"