Some checks failed
CI/CD / lint (push) Successful in 41s
CI/CD / test (push) Successful in 55s
CI/CD / typecheck (push) Successful in 10m52s
CI/CD / build (push) Successful in 1m21s
CI/CD / docker (push) Failing after 21s
CI/CD / publish-rpm (push) Successful in 37s
CI/CD / deploy (push) Has been skipped
No build tool works in the default unprivileged runner container (no Docker socket, no procfs, no FUSE). Run the docker job privileged with the host Docker socket mounted, then use standard docker build/push. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
270 lines
8.2 KiB
YAML
270 lines
8.2 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)
|
|
# No bun.lockb in repo, so --frozen-lockfile is unreliable
|
|
bun install
|
|
# 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'
|
|
container:
|
|
options: --privileged -v /var/run/docker.sock:/var/run/docker.sock
|
|
env:
|
|
REGISTRY: ${{ env.GITEA_REGISTRY }}
|
|
OWNER: ${{ env.GITEA_OWNER }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Login to Gitea container registry
|
|
run: |
|
|
echo "${{ secrets.PACKAGES_TOKEN }}" | docker login \
|
|
--username ${{ env.OWNER }} --password-stdin \
|
|
${{ env.REGISTRY }}
|
|
|
|
- name: Build & push mcpd
|
|
run: |
|
|
docker build -t ${{ env.REGISTRY }}/${{ env.OWNER }}/mcpd:latest \
|
|
-f deploy/Dockerfile.mcpd .
|
|
docker push ${{ env.REGISTRY }}/${{ env.OWNER }}/mcpd:latest
|
|
|
|
- name: Build & push node-runner
|
|
run: |
|
|
docker build -t ${{ env.REGISTRY }}/${{ env.OWNER }}/mcpctl-node-runner:latest \
|
|
-f deploy/Dockerfile.node-runner .
|
|
docker push ${{ env.REGISTRY }}/${{ env.OWNER }}/mcpctl-node-runner:latest
|
|
|
|
- name: Build & push python-runner
|
|
run: |
|
|
docker build -t ${{ env.REGISTRY }}/${{ env.OWNER }}/mcpctl-python-runner:latest \
|
|
-f deploy/Dockerfile.python-runner .
|
|
docker push ${{ env.REGISTRY }}/${{ env.OWNER }}/mcpctl-python-runner:latest
|
|
|
|
- name: Build & push docmost-mcp
|
|
run: |
|
|
docker build -t ${{ env.REGISTRY }}/${{ env.OWNER }}/docmost-mcp:latest \
|
|
-f deploy/Dockerfile.docmost-mcp .
|
|
docker push ${{ env.REGISTRY }}/${{ env.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
|