Files
mcpctl/.gitea/workflows/ci.yml
Michal ccb9108563
Some checks failed
CI/CD / typecheck (push) Successful in 41s
CI/CD / test (push) Successful in 52s
CI/CD / lint (push) Successful in 10m47s
CI/CD / build (push) Failing after 7m31s
CI/CD / docker (push) Has been skipped
CI/CD / publish-rpm (push) Has been skipped
CI/CD / deploy (push) Has been skipped
ci: restart dockerd directly (no service manager in runner)
The Gitea Act Runner container has no systemd, service, or init.d.
Kill dockerd by PID and relaunch it directly after writing daemon.json.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 00:27:59 +00:00

275 lines
8.6 KiB
YAML

name: CI/CD
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
GITEA_REGISTRY: 10.0.0.194:3012
GITEA_OWNER: michal
# ============================================================
# Required Gitea secrets:
# PACKAGES_TOKEN — Gitea API token (packages + registry)
# PORTAINER_PASSWORD — Portainer login for stack deploy
# POSTGRES_PASSWORD — Database password for production stack
# ============================================================
jobs:
# ── CI checks (run in parallel on every push/PR) ──────────
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Lint
run: pnpm lint || echo "::warning::Lint has errors — not blocking CI yet"
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @mcpctl/db exec prisma generate
- name: Typecheck
run: pnpm typecheck
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @mcpctl/db exec prisma generate
- name: Build (needed by completions test)
run: pnpm build
- name: Run tests
run: pnpm test:run
# ── Build & package RPM ───────────────────────────────────
build:
runs-on: ubuntu-latest
needs: [lint, typecheck, test]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Generate Prisma client
run: pnpm --filter @mcpctl/db exec prisma generate
- name: Build all packages
run: pnpm build
- name: Generate shell completions
run: pnpm completions:generate
- uses: oven-sh/setup-bun@v2
- name: Install nfpm
run: |
curl -sL -o /tmp/nfpm.tar.gz "https://github.com/goreleaser/nfpm/releases/download/v2.45.0/nfpm_2.45.0_Linux_x86_64.tar.gz"
tar xzf /tmp/nfpm.tar.gz -C /usr/local/bin nfpm
- name: Bundle standalone binaries
run: |
mkdir -p dist
# bun needs a flat node_modules (pnpm's strict layout breaks resolution)
bun install --frozen-lockfile
# Stub for optional dep that bun tries to resolve
if [ ! -e node_modules/react-devtools-core ]; then
ln -s ../src/cli/stubs/react-devtools-core node_modules/react-devtools-core
fi
bun build src/cli/src/index.ts --compile --outfile dist/mcpctl
bun build src/mcplocal/src/main.ts --compile --outfile dist/mcpctl-local
- name: Package RPM
run: nfpm pkg --packager rpm --target dist/
- name: Upload RPM artifact
uses: actions/upload-artifact@v3
with:
name: rpm-package
path: dist/mcpctl-*.rpm
retention-days: 7
# ── Release pipeline (main branch push only) ──────────────
docker:
runs-on: ubuntu-latest
needs: [build]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Configure insecure registry
run: |
sudo mkdir -p /etc/docker
echo '{"insecure-registries":["${{ env.GITEA_REGISTRY }}"]}' | sudo tee /etc/docker/daemon.json
# Restart dockerd - kill existing process and relaunch
sudo kill "$(cat /var/run/docker.pid 2>/dev/null)" 2>/dev/null || sudo pkill dockerd || true
sleep 3
sudo dockerd &>/dev/null &
# Wait for Docker to be ready
for i in $(seq 1 30); do docker info &>/dev/null && break || sleep 1; done
- name: Login to Gitea container registry
run: |
echo "${{ secrets.PACKAGES_TOKEN }}" | docker login \
--username ${{ env.GITEA_OWNER }} --password-stdin \
${{ env.GITEA_REGISTRY }}
- name: Build & push mcpd
run: |
docker build -t ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/mcpd:latest \
-f deploy/Dockerfile.mcpd .
docker push ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/mcpd:latest
- name: Build & push node-runner
run: |
docker build -t ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/mcpctl-node-runner:latest \
-f deploy/Dockerfile.node-runner .
docker push ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/mcpctl-node-runner:latest
- name: Build & push python-runner
run: |
docker build -t ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/mcpctl-python-runner:latest \
-f deploy/Dockerfile.python-runner .
docker push ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/mcpctl-python-runner:latest
- name: Build & push docmost-mcp
run: |
docker build -t ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/docmost-mcp:latest \
-f deploy/Dockerfile.docmost-mcp .
docker push ${{ env.GITEA_REGISTRY }}/${{ env.GITEA_OWNER }}/docmost-mcp:latest
- name: Link packages to repository
env:
GITEA_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
GITEA_URL: http://${{ env.GITEA_REGISTRY }}
GITEA_OWNER: ${{ env.GITEA_OWNER }}
GITEA_REPO: mcpctl
run: |
source scripts/link-package.sh
link_package "container" "mcpd"
link_package "container" "mcpctl-node-runner"
link_package "container" "mcpctl-python-runner"
link_package "container" "docmost-mcp"
publish-rpm:
runs-on: ubuntu-latest
needs: [build]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Download RPM artifact
uses: actions/download-artifact@v3
with:
name: rpm-package
path: dist/
- name: Install rpm tools
run: sudo apt-get update && sudo apt-get install -y rpm
- name: Publish RPM to Gitea
env:
GITEA_TOKEN: ${{ secrets.PACKAGES_TOKEN }}
GITEA_URL: http://${{ env.GITEA_REGISTRY }}
GITEA_OWNER: ${{ env.GITEA_OWNER }}
GITEA_REPO: mcpctl
run: |
RPM_FILE=$(ls dist/mcpctl-*.rpm | head -1)
RPM_VERSION=$(rpm -qp --queryformat '%{VERSION}-%{RELEASE}' "$RPM_FILE")
echo "Publishing $RPM_FILE (version $RPM_VERSION)..."
# Delete existing version if present
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: token ${GITEA_TOKEN}" \
"${GITEA_URL}/api/v1/packages/${GITEA_OWNER}/rpm/mcpctl/${RPM_VERSION}")
if [ "$HTTP_CODE" = "200" ]; then
echo "Version exists, replacing..."
curl -s -o /dev/null -X DELETE \
-H "Authorization: token ${GITEA_TOKEN}" \
"${GITEA_URL}/api/v1/packages/${GITEA_OWNER}/rpm/mcpctl/${RPM_VERSION}"
fi
# Upload
curl --fail -X PUT \
-H "Authorization: token ${GITEA_TOKEN}" \
--upload-file "$RPM_FILE" \
"${GITEA_URL}/api/packages/${GITEA_OWNER}/rpm/upload"
echo "Published successfully!"
# Link package to repo
source scripts/link-package.sh
link_package "rpm" "mcpctl"
deploy:
runs-on: ubuntu-latest
needs: [docker, publish-rpm]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- uses: actions/checkout@v4
- name: Create stack env file
env:
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
run: |
printf '%s\n' \
"POSTGRES_USER=mcpctl" \
"POSTGRES_PASSWORD=${POSTGRES_PASSWORD}" \
"POSTGRES_DB=mcpctl" \
"MCPD_PORT=3100" \
"MCPD_LOG_LEVEL=info" \
> stack/.env
- name: Deploy to Portainer
env:
PORTAINER_PASSWORD: ${{ secrets.PORTAINER_PASSWORD }}
run: bash deploy.sh