-
-
Notifications
You must be signed in to change notification settings - Fork 114
464 lines (403 loc) · 18.4 KB
/
Copy pathcd.yml
File metadata and controls
464 lines (403 loc) · 18.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
name: cd
# Triggered when a GitHub Release is published (draft → published or created as
# published). Each job builds one artefact and pushes it to the appropriate
# GitHub registry and DockerHub so that self-hosters can pull pre-built images/packages.
#
# Artefacts produced per release:
# ghcr.io/paca-ai/paca-api:<tag> — Go API service Docker image
# <dockerhub-username>/paca-api:<tag> — Go API service Docker image
# ghcr.io/paca-ai/paca-realtime:<tag> — Node realtime service Docker image
# <dockerhub-username>/paca-realtime:<tag> — Node realtime service Docker image
# ghcr.io/paca-ai/paca-web:<tag> — Web app Docker image (Caddy)
# <dockerhub-username>/paca-web:<tag> — Web app Docker image (Caddy)
# ghcr.io/paca-ai/paca-ai-agent:<tag> — AI Agent service Docker image
# <dockerhub-username>/paca-ai-agent:<tag> — AI Agent service Docker image
# ghcr.io/paca-ai/paca-agent-server:<tag> — Sandbox agent-server image (OpenHands + Paca MCP pre-installed)
# <dockerhub-username>/paca-agent-server:<tag> — Sandbox agent-server image (OpenHands + Paca MCP pre-installed)
# registry.npmjs.org @paca-ai/paca-mcp — MCP server npm package
# registry.npmjs.org @paca-ai/plugin-sdk-react — Plugin frontend SDK npm package
# pypi.org paca-acp-bridge — ACP bridge local daemon Python package
# GitHub Release assets:
# install.sh — one-shot interactive install script
# upgrade.sh — upgrades an existing installation in place
# docker-compose.yml — standalone compose (no source tree required)
# Caddyfile — Caddy gateway configuration
on:
release:
types: [published]
# All jobs need read on contents (checkout) and write on packages (push/publish).
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
# ─────────────────────────────────────────────────────────────────────────────
# API service image
# ─────────────────────────────────────────────────────────────────────────────
jobs:
api-image:
name: Build and push API image
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/paca-api
${{ secrets.DOCKERHUB_USERNAME }}/paca-api
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: services/api
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ─────────────────────────────────────────────────────────────────────────────
# Realtime service image
# ─────────────────────────────────────────────────────────────────────────────
realtime-image:
name: Build and push Realtime image
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/paca-realtime
${{ secrets.DOCKERHUB_USERNAME }}/paca-realtime
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: services/realtime
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ─────────────────────────────────────────────────────────────────────────────
# Web app image
# ─────────────────────────────────────────────────────────────────────────────
# The pre-built image uses relative URLs that work with the Caddy /api
# proxy out of the box, since the API client now derives the base URL
# from window.location.origin at runtime.
web-image:
name: Build and push Web image
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/paca-web
${{ secrets.DOCKERHUB_USERNAME }}/paca-web
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: apps/web
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ─────────────────────────────────────────────────────────────────────────────
# AI Agent service image
# ─────────────────────────────────────────────────────────────────────────────
ai-agent-image:
name: Build and push AI Agent image
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/paca-ai-agent
${{ secrets.DOCKERHUB_USERNAME }}/paca-ai-agent
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: services/ai-agent
file: services/ai-agent/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ─────────────────────────────────────────────────────────────────────────────
# Agent-server sandbox image (OpenHands agent-server + Paca MCP pre-installed)
# ─────────────────────────────────────────────────────────────────────────────
agent-server-image:
name: Build and push Agent Server image
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ env.REGISTRY }}/${{ github.repository_owner }}/paca-agent-server
${{ secrets.DOCKERHUB_USERNAME }}/paca-agent-server
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
- name: Build and push
uses: docker/build-push-action@v6
with:
context: services/agent-server
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ─────────────────────────────────────────────────────────────────────────────
# MCP server npm package → npmjs.com
# ─────────────────────────────────────────────────────────────────────────────
publish-mcp:
name: Publish MCP package
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
id-token: write
defaults:
run:
working-directory: apps/mcp
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: "1.2.23"
- name: Cache Bun packages
uses: actions/cache@v4
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-mcp-${{ hashFiles('apps/mcp/bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-mcp-
- name: Install dependencies
run: bun install --frozen-lockfile
# Strip the leading 'v' from the release tag (v1.2.3 → 1.2.3) so it
# matches npm's semver format, then stamp package.json without a git tag.
# Must run BEFORE build so the version is baked into build/package.json.
- name: Set package version
run: |
VERSION="${{ github.event.release.tag_name }}"
npm version "${VERSION#v}" --no-git-tag-version
- name: Build
run: bun run build
- name: Setup Node.js with npm registry
uses: actions/setup-node@v4
with:
node-version: "24"
registry-url: "https://registry.npmjs.org"
scope: "@paca-ai"
# npm 12.0.0 has a packaging bug: libnpmpublish still requires
# `sigstore`, but the published 12.0.0 tarball is missing that
# module, so `npm publish --provenance` crashes with "Cannot find
# module 'sigstore'". Pin to the 11.x line until a patched 12.x
# ships. See https://github.com/npm/cli/issues/9722.
- name: Upgrade npm
run: npm install -g npm@11
# For prerelease versions (e.g. 1.0.0-alpha.1), npm requires an explicit
# --tag to avoid accidentally tagging as "latest".
- name: Publish to npm
run: |
VERSION="${{ github.event.release.tag_name }}"
CLEAN_VERSION="${VERSION#v}"
if [[ "$CLEAN_VERSION" == *"-"* ]]; then
PRERELEASE_LABEL=$(echo "$CLEAN_VERSION" | sed 's/[^-]*-\([a-zA-Z]*\).*/\1/')
npm publish --provenance --access public --tag "${PRERELEASE_LABEL:-next}"
else
npm publish --provenance --access public
fi
# ─────────────────────────────────────────────────────────────────────────────
# ACP bridge Python package → pypi.org
# ─────────────────────────────────────────────────────────────────────────────
publish-acp-bridge:
name: Publish ACP bridge package
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
# Required for PyPI Trusted Publishing (OIDC) — no stored API token needed.
id-token: write
defaults:
run:
working-directory: apps/acp-bridge
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
python-version: "3.12"
# Strip the leading 'v' from the release tag (v1.2.3 → 1.2.3) so it
# matches PyPI's version format, then stamp pyproject.toml without
# touching uv.lock. Must run BEFORE build so the version is baked
# into the built sdist/wheel.
- name: Set package version
env:
VERSION: ${{ github.event.release.tag_name }}
run: uv version --frozen "${VERSION#v}"
- name: Build sdist and wheel
run: uv build
- name: Publish to PyPI
run: uv publish --trusted-publishing always
# ─────────────────────────────────────────────────────────────────────────────
# Deployment assets → GitHub Release
#
# Uploads four files so that users can run or upgrade Paca without cloning the repo:
# install.sh — interactive setup wizard (download + configure + start)
# upgrade.sh — upgrades an existing installation in place
# docker-compose.yml — standalone compose referencing pre-built DockerHub images
# Caddyfile — Caddy gateway configuration required by the compose file
#
# End-users download and run:
# curl -fsSL https://github.com/Paca-AI/paca/releases/latest/download/install.sh -o install.sh
# bash install.sh
# ─────────────────────────────────────────────────────────────────────────────
release-assets:
name: Upload deployment assets to release
runs-on: ubuntu-latest
needs:
[
api-image,
realtime-image,
web-image,
ai-agent-image,
agent-server-image,
publish-mcp,
publish-acp-bridge,
]
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare assets
run: |
# Rename files to the names end-users will download.
cp deploy/docker-compose.prod.yml docker-compose.yml
cp deploy/caddy/Caddyfile Caddyfile
cp scripts/install.sh install.sh
cp scripts/upgrade.sh upgrade.sh
chmod +x install.sh upgrade.sh
- name: Upload assets to GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload "${{ github.event.release.tag_name }}" \
install.sh \
upgrade.sh \
docker-compose.yml \
Caddyfile \
--clobber