gigaclaw 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +237 -0
- package/api/CLAUDE.md +19 -0
- package/api/index.js +265 -0
- package/bin/cli.js +823 -0
- package/bin/local.sh +85 -0
- package/bin/postinstall.js +63 -0
- package/config/index.js +26 -0
- package/config/instrumentation.js +62 -0
- package/drizzle/0000_initial.sql +52 -0
- package/drizzle/0001_nostalgic_sersi.sql +11 -0
- package/drizzle/0002_black_daimon_hellstrom.sql +19 -0
- package/drizzle/0003_rename_code_workspaces.sql +5 -0
- package/drizzle/meta/0000_snapshot.json +321 -0
- package/drizzle/meta/0001_snapshot.json +390 -0
- package/drizzle/meta/0002_snapshot.json +411 -0
- package/drizzle/meta/0003_snapshot.json +419 -0
- package/drizzle/meta/_journal.json +34 -0
- package/lib/actions.js +44 -0
- package/lib/ai/agent.js +86 -0
- package/lib/ai/index.js +342 -0
- package/lib/ai/model.js +180 -0
- package/lib/ai/tools.js +269 -0
- package/lib/ai/web-search.js +42 -0
- package/lib/auth/actions.js +28 -0
- package/lib/auth/config.js +27 -0
- package/lib/auth/edge-config.js +27 -0
- package/lib/auth/index.js +27 -0
- package/lib/auth/middleware.js +62 -0
- package/lib/channels/base.js +56 -0
- package/lib/channels/index.js +15 -0
- package/lib/channels/telegram.js +148 -0
- package/lib/chat/actions.js +579 -0
- package/lib/chat/api.js +140 -0
- package/lib/chat/components/app-sidebar.js +213 -0
- package/lib/chat/components/app-sidebar.jsx +279 -0
- package/lib/chat/components/chat-header.js +192 -0
- package/lib/chat/components/chat-header.jsx +223 -0
- package/lib/chat/components/chat-input.js +236 -0
- package/lib/chat/components/chat-input.jsx +249 -0
- package/lib/chat/components/chat-nav-context.js +11 -0
- package/lib/chat/components/chat-nav-context.jsx +11 -0
- package/lib/chat/components/chat-page.js +99 -0
- package/lib/chat/components/chat-page.jsx +121 -0
- package/lib/chat/components/chat.js +153 -0
- package/lib/chat/components/chat.jsx +199 -0
- package/lib/chat/components/chats-page.js +367 -0
- package/lib/chat/components/chats-page.jsx +394 -0
- package/lib/chat/components/code-mode-toggle.js +132 -0
- package/lib/chat/components/code-mode-toggle.jsx +163 -0
- package/lib/chat/components/crons-page.js +172 -0
- package/lib/chat/components/crons-page.jsx +244 -0
- package/lib/chat/components/greeting.js +11 -0
- package/lib/chat/components/greeting.jsx +16 -0
- package/lib/chat/components/icons.js +805 -0
- package/lib/chat/components/icons.jsx +751 -0
- package/lib/chat/components/index.js +20 -0
- package/lib/chat/components/message.js +363 -0
- package/lib/chat/components/message.jsx +422 -0
- package/lib/chat/components/messages.js +65 -0
- package/lib/chat/components/messages.jsx +74 -0
- package/lib/chat/components/notifications-page.js +56 -0
- package/lib/chat/components/notifications-page.jsx +87 -0
- package/lib/chat/components/page-layout.js +21 -0
- package/lib/chat/components/page-layout.jsx +28 -0
- package/lib/chat/components/pull-requests-page.js +103 -0
- package/lib/chat/components/pull-requests-page.jsx +113 -0
- package/lib/chat/components/settings-layout.js +39 -0
- package/lib/chat/components/settings-layout.jsx +53 -0
- package/lib/chat/components/settings-secrets-page.js +216 -0
- package/lib/chat/components/settings-secrets-page.jsx +264 -0
- package/lib/chat/components/sidebar-history-item.js +138 -0
- package/lib/chat/components/sidebar-history-item.jsx +119 -0
- package/lib/chat/components/sidebar-history.js +167 -0
- package/lib/chat/components/sidebar-history.jsx +220 -0
- package/lib/chat/components/sidebar-user-nav.js +61 -0
- package/lib/chat/components/sidebar-user-nav.jsx +77 -0
- package/lib/chat/components/swarm-page.js +157 -0
- package/lib/chat/components/swarm-page.jsx +210 -0
- package/lib/chat/components/tool-call.js +89 -0
- package/lib/chat/components/tool-call.jsx +107 -0
- package/lib/chat/components/triggers-page.js +153 -0
- package/lib/chat/components/triggers-page.jsx +221 -0
- package/lib/chat/components/ui/combobox.js +98 -0
- package/lib/chat/components/ui/combobox.jsx +114 -0
- package/lib/chat/components/ui/confirm-dialog.js +53 -0
- package/lib/chat/components/ui/confirm-dialog.jsx +57 -0
- package/lib/chat/components/ui/dropdown-menu.js +194 -0
- package/lib/chat/components/ui/dropdown-menu.jsx +215 -0
- package/lib/chat/components/ui/rename-dialog.js +78 -0
- package/lib/chat/components/ui/rename-dialog.jsx +74 -0
- package/lib/chat/components/ui/scroll-area.js +13 -0
- package/lib/chat/components/ui/scroll-area.jsx +17 -0
- package/lib/chat/components/ui/separator.js +21 -0
- package/lib/chat/components/ui/separator.jsx +18 -0
- package/lib/chat/components/ui/sheet.js +75 -0
- package/lib/chat/components/ui/sheet.jsx +95 -0
- package/lib/chat/components/ui/sidebar.js +228 -0
- package/lib/chat/components/ui/sidebar.jsx +246 -0
- package/lib/chat/components/ui/tooltip.js +56 -0
- package/lib/chat/components/ui/tooltip.jsx +66 -0
- package/lib/chat/components/upgrade-dialog.js +151 -0
- package/lib/chat/components/upgrade-dialog.jsx +170 -0
- package/lib/chat/utils.js +11 -0
- package/lib/code/actions.js +153 -0
- package/lib/code/code-page.js +22 -0
- package/lib/code/code-page.jsx +25 -0
- package/lib/code/index.js +1 -0
- package/lib/code/terminal-view.js +201 -0
- package/lib/code/terminal-view.jsx +224 -0
- package/lib/code/ws-proxy.js +80 -0
- package/lib/cron.js +246 -0
- package/lib/db/api-keys.js +163 -0
- package/lib/db/chats.js +168 -0
- package/lib/db/code-workspaces.js +110 -0
- package/lib/db/index.js +52 -0
- package/lib/db/notifications.js +99 -0
- package/lib/db/schema.js +66 -0
- package/lib/db/update-check.js +96 -0
- package/lib/db/users.js +89 -0
- package/lib/paths.js +42 -0
- package/lib/tools/create-job.js +97 -0
- package/lib/tools/docker.js +146 -0
- package/lib/tools/github.js +271 -0
- package/lib/tools/openai.js +35 -0
- package/lib/tools/telegram.js +292 -0
- package/lib/triggers.js +104 -0
- package/lib/utils/render-md.js +111 -0
- package/package.json +118 -0
- package/setup/lib/auth.mjs +81 -0
- package/setup/lib/env.mjs +21 -0
- package/setup/lib/fs-utils.mjs +20 -0
- package/setup/lib/github.mjs +149 -0
- package/setup/lib/prerequisites.mjs +155 -0
- package/setup/lib/prompts.mjs +267 -0
- package/setup/lib/providers.mjs +105 -0
- package/setup/lib/sync.mjs +125 -0
- package/setup/lib/targets.mjs +45 -0
- package/setup/lib/telegram-verify.mjs +63 -0
- package/setup/lib/telegram.mjs +76 -0
- package/setup/setup-cloud.mjs +833 -0
- package/setup/setup-local.mjs +377 -0
- package/setup/setup-telegram.mjs +265 -0
- package/setup/setup.mjs +87 -0
- package/templates/.dockerignore +5 -0
- package/templates/.env.example +104 -0
- package/templates/.github/workflows/auto-merge.yml +117 -0
- package/templates/.github/workflows/notify-job-failed.yml +64 -0
- package/templates/.github/workflows/notify-pr-complete.yml +119 -0
- package/templates/.github/workflows/rebuild-event-handler.yml +121 -0
- package/templates/.github/workflows/run-job.yml +89 -0
- package/templates/.github/workflows/upgrade-event-handler.yml +62 -0
- package/templates/.gitignore.template +45 -0
- package/templates/.pi/extensions/env-sanitizer/index.ts +48 -0
- package/templates/.pi/extensions/env-sanitizer/package.json +5 -0
- package/templates/CLAUDE.md +29 -0
- package/templates/CLAUDE.md.template +308 -0
- package/templates/app/api/[...gigaclaw]/route.js +1 -0
- package/templates/app/api/auth/[...nextauth]/route.js +1 -0
- package/templates/app/chat/[chatId]/page.js +9 -0
- package/templates/app/chats/page.js +7 -0
- package/templates/app/code/[codeWorkspaceId]/page.js +9 -0
- package/templates/app/components/ascii-logo.jsx +12 -0
- package/templates/app/components/login-form.jsx +92 -0
- package/templates/app/components/setup-form.jsx +82 -0
- package/templates/app/components/theme-provider.jsx +11 -0
- package/templates/app/components/theme-toggle.jsx +38 -0
- package/templates/app/components/ui/button.jsx +21 -0
- package/templates/app/components/ui/card.jsx +23 -0
- package/templates/app/components/ui/input.jsx +10 -0
- package/templates/app/components/ui/label.jsx +10 -0
- package/templates/app/crons/page.js +5 -0
- package/templates/app/globals.css +90 -0
- package/templates/app/layout.js +33 -0
- package/templates/app/login/page.js +15 -0
- package/templates/app/notifications/page.js +7 -0
- package/templates/app/page.js +7 -0
- package/templates/app/pull-requests/page.js +7 -0
- package/templates/app/settings/crons/page.js +5 -0
- package/templates/app/settings/layout.js +7 -0
- package/templates/app/settings/page.js +5 -0
- package/templates/app/settings/secrets/page.js +5 -0
- package/templates/app/settings/triggers/page.js +5 -0
- package/templates/app/stream/chat/route.js +1 -0
- package/templates/app/swarm/page.js +7 -0
- package/templates/app/triggers/page.js +5 -0
- package/templates/config/CODE_PLANNING.md +14 -0
- package/templates/config/CRONS.json +56 -0
- package/templates/config/HEARTBEAT.md +3 -0
- package/templates/config/JOB_AGENT.md +30 -0
- package/templates/config/JOB_PLANNING.md +240 -0
- package/templates/config/JOB_SUMMARY.md +130 -0
- package/templates/config/SKILL_BUILDING_GUIDE.md +96 -0
- package/templates/config/SOUL.md +48 -0
- package/templates/config/TRIGGERS.json +58 -0
- package/templates/config/WEB_SEARCH_AVAILABLE.md +5 -0
- package/templates/config/WEB_SEARCH_UNAVAILABLE.md +3 -0
- package/templates/docker/claude-code-job/Dockerfile +34 -0
- package/templates/docker/claude-code-job/entrypoint.sh +149 -0
- package/templates/docker/claude-code-workspace/.tmux.conf +5 -0
- package/templates/docker/claude-code-workspace/Dockerfile +61 -0
- package/templates/docker/claude-code-workspace/entrypoint.sh +51 -0
- package/templates/docker/event-handler/Dockerfile +20 -0
- package/templates/docker/event-handler/ecosystem.config.cjs +7 -0
- package/templates/docker/pi-coding-agent-job/Dockerfile +51 -0
- package/templates/docker/pi-coding-agent-job/entrypoint.sh +164 -0
- package/templates/docker-compose.local.yml +78 -0
- package/templates/docker-compose.yml +64 -0
- package/templates/instrumentation.js +6 -0
- package/templates/middleware.js +23 -0
- package/templates/next.config.mjs +3 -0
- package/templates/postcss.config.mjs +5 -0
- package/templates/public/favicon.ico +0 -0
- package/templates/server.js +25 -0
- package/templates/skills/LICENSE +21 -0
- package/templates/skills/README.md +119 -0
- package/templates/skills/brave-search/SKILL.md +79 -0
- package/templates/skills/brave-search/content.js +86 -0
- package/templates/skills/brave-search/package-lock.json +621 -0
- package/templates/skills/brave-search/package.json +14 -0
- package/templates/skills/brave-search/search.js +199 -0
- package/templates/skills/browser-tools/SKILL.md +196 -0
- package/templates/skills/browser-tools/browser-content.js +103 -0
- package/templates/skills/browser-tools/browser-cookies.js +35 -0
- package/templates/skills/browser-tools/browser-eval.js +53 -0
- package/templates/skills/browser-tools/browser-hn-scraper.js +108 -0
- package/templates/skills/browser-tools/browser-nav.js +44 -0
- package/templates/skills/browser-tools/browser-pick.js +162 -0
- package/templates/skills/browser-tools/browser-screenshot.js +34 -0
- package/templates/skills/browser-tools/browser-start.js +87 -0
- package/templates/skills/browser-tools/package-lock.json +2556 -0
- package/templates/skills/browser-tools/package.json +19 -0
- package/templates/skills/google-docs/SKILL.md +23 -0
- package/templates/skills/google-docs/create.sh +69 -0
- package/templates/skills/google-drive/SKILL.md +47 -0
- package/templates/skills/google-drive/delete.sh +47 -0
- package/templates/skills/google-drive/download.sh +50 -0
- package/templates/skills/google-drive/list.sh +41 -0
- package/templates/skills/google-drive/upload.sh +76 -0
- package/templates/skills/kie-ai/SKILL.md +38 -0
- package/templates/skills/kie-ai/generate-image.sh +77 -0
- package/templates/skills/kie-ai/generate-video.sh +69 -0
- package/templates/skills/llm-secrets/SKILL.md +34 -0
- package/templates/skills/llm-secrets/llm-secrets.js +33 -0
- package/templates/skills/modify-self/SKILL.md +12 -0
- package/templates/skills/youtube-transcript/SKILL.md +41 -0
- package/templates/skills/youtube-transcript/package-lock.json +24 -0
- package/templates/skills/youtube-transcript/package.json +8 -0
- package/templates/skills/youtube-transcript/transcript.js +84 -0
package/setup/setup.mjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TTY Guard — second line of defence against curl|bash stdin hijacking.
|
|
5
|
+
*
|
|
6
|
+
* When `npm run setup` is invoked from a script whose stdin is a pipe
|
|
7
|
+
* (e.g. curl | bash), process.stdin.isTTY is undefined and @clack/prompts
|
|
8
|
+
* exits immediately on the first keypress event (which is EOF).
|
|
9
|
+
*
|
|
10
|
+
* If /dev/tty is accessible we re-open it and reassign process.stdin so
|
|
11
|
+
* that @clack/prompts gets a real terminal regardless of how this script
|
|
12
|
+
* was launched. The primary fix lives in install.sh (exec < /dev/tty),
|
|
13
|
+
* but this guard handles cases where setup.mjs is called directly without
|
|
14
|
+
* going through install.sh.
|
|
15
|
+
*/
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import { Readable } from 'stream';
|
|
18
|
+
|
|
19
|
+
if (!process.stdin.isTTY) {
|
|
20
|
+
try {
|
|
21
|
+
const ttyFd = fs.openSync('/dev/tty', 'r+');
|
|
22
|
+
const ttyStream = new fs.ReadStream(null, { fd: ttyFd, autoClose: true });
|
|
23
|
+
// Monkey-patch the TTY flag so @clack/prompts enables raw mode
|
|
24
|
+
ttyStream.isTTY = true;
|
|
25
|
+
ttyStream.setRawMode = (mode) => {
|
|
26
|
+
try { fs.fstatSync(ttyFd); require('tty').ReadStream.prototype.setRawMode.call(ttyStream, mode); } catch (_) {}
|
|
27
|
+
};
|
|
28
|
+
process.stdin = ttyStream;
|
|
29
|
+
} catch (_) {
|
|
30
|
+
// /dev/tty not available (CI, Docker without TTY, etc.) — fall through;
|
|
31
|
+
// the prompts will still render but keyboard input may not work.
|
|
32
|
+
// In that case the user should run `npm run setup` directly in a terminal.
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
import chalk from 'chalk';
|
|
37
|
+
import * as clack from '@clack/prompts';
|
|
38
|
+
|
|
39
|
+
const logo = `
|
|
40
|
+
_______ ____ __
|
|
41
|
+
/ ____(_)___ _____ _/ __ )____ / /_
|
|
42
|
+
/ / __/ / __ \`/ __ \`/ __ / __ \\/ __/
|
|
43
|
+
/ /_/ / / /_/ / /_/ / /_/ / /_/ / /_
|
|
44
|
+
\\____/_/\\__, /\\__,_/_____/\\____/\\__/
|
|
45
|
+
/____/
|
|
46
|
+
India's Autonomous AI Agent · Powered by Gignaati
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
async function main() {
|
|
50
|
+
console.log(chalk.cyan(logo));
|
|
51
|
+
|
|
52
|
+
clack.intro('GigaBot Setup Wizard');
|
|
53
|
+
|
|
54
|
+
const mode = await clack.select({
|
|
55
|
+
message: 'How do you want to run GigaBot?',
|
|
56
|
+
options: [
|
|
57
|
+
{
|
|
58
|
+
value: 'cloud',
|
|
59
|
+
label: 'Cloud Mode',
|
|
60
|
+
hint: 'GitHub + ngrok + Telegram — full features, internet required',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
value: 'local',
|
|
64
|
+
label: 'Local Mode',
|
|
65
|
+
hint: 'Ollama only — 100% offline, no Telegram or GitHub needed',
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
if (clack.isCancel(mode)) {
|
|
71
|
+
clack.cancel('Setup cancelled.');
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (mode === 'cloud') {
|
|
76
|
+
const { run } = await import('./setup-cloud.mjs');
|
|
77
|
+
await run();
|
|
78
|
+
} else {
|
|
79
|
+
const { run } = await import('./setup-local.mjs');
|
|
80
|
+
await run();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
main().catch((error) => {
|
|
85
|
+
clack.log.error(`Setup failed: ${error.message}`);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# ============================================================
|
|
2
|
+
# Giga Bot Configuration — Powered by Gignaati
|
|
3
|
+
# ============================================================
|
|
4
|
+
# Copy this file to .env and fill in your values.
|
|
5
|
+
# NEVER commit the actual .env file with real secrets!
|
|
6
|
+
# Run the setup wizard to auto-fill most of these:
|
|
7
|
+
# npx gigabot setup
|
|
8
|
+
# ============================================================
|
|
9
|
+
|
|
10
|
+
# ─── Authentication ──────────────────────────────────────────
|
|
11
|
+
# Auth.js secret for session encryption (auto-generated by setup wizard)
|
|
12
|
+
# To generate manually: openssl rand -base64 32
|
|
13
|
+
AUTH_SECRET=
|
|
14
|
+
AUTH_TRUST_HOST=true
|
|
15
|
+
|
|
16
|
+
# ─── App URL ─────────────────────────────────────────────────
|
|
17
|
+
# Public URL for webhooks, Telegram, and Traefik hostname
|
|
18
|
+
# e.g., https://mybot.example.com or https://abc123.ngrok.io
|
|
19
|
+
APP_URL=
|
|
20
|
+
APP_HOSTNAME=
|
|
21
|
+
|
|
22
|
+
# ─── GitHub ──────────────────────────────────────────────────
|
|
23
|
+
# GitHub Personal Access Token (needs repo + workflow scopes)
|
|
24
|
+
# Create at: https://github.com/settings/tokens/new
|
|
25
|
+
GH_TOKEN=ghp_your_token_here
|
|
26
|
+
GH_OWNER=your_github_username
|
|
27
|
+
GH_REPO=your_repo_name
|
|
28
|
+
GH_WEBHOOK_SECRET=
|
|
29
|
+
|
|
30
|
+
# ─── Telegram (Optional) ─────────────────────────────────────
|
|
31
|
+
# Bot token from @BotFather
|
|
32
|
+
TELEGRAM_BOT_TOKEN=
|
|
33
|
+
# Secret for validating Telegram webhooks: openssl rand -hex 32
|
|
34
|
+
TELEGRAM_WEBHOOK_SECRET=
|
|
35
|
+
# Verification code for getting your chat ID
|
|
36
|
+
TELEGRAM_VERIFICATION=
|
|
37
|
+
# Default Telegram chat ID for scheduled notifications
|
|
38
|
+
TELEGRAM_CHAT_ID=
|
|
39
|
+
|
|
40
|
+
# ─── LLM Provider ────────────────────────────────────────────
|
|
41
|
+
# Choose your AI provider. Options:
|
|
42
|
+
# anthropic — Claude (Anthropic) [default]
|
|
43
|
+
# openai — GPT (OpenAI)
|
|
44
|
+
# google — Gemini (Google)
|
|
45
|
+
# pragatigpt — PragatiGPT (Gignaati — India-first, 100% data privacy)
|
|
46
|
+
# ollama — Ollama (Local — zero cloud dependency)
|
|
47
|
+
# custom — Any OpenAI-compatible API endpoint
|
|
48
|
+
LLM_PROVIDER=anthropic
|
|
49
|
+
|
|
50
|
+
# Model name override (optional — uses provider default if not set)
|
|
51
|
+
# LLM_MODEL=
|
|
52
|
+
|
|
53
|
+
# Max tokens for LLM responses (default: 4096)
|
|
54
|
+
# LLM_MAX_TOKENS=4096
|
|
55
|
+
|
|
56
|
+
# ─── Anthropic (Claude) ──────────────────────────────────────
|
|
57
|
+
# Required when LLM_PROVIDER=anthropic
|
|
58
|
+
# Get your key at: https://platform.claude.com/settings/keys
|
|
59
|
+
ANTHROPIC_API_KEY=sk-ant-your_key_here
|
|
60
|
+
|
|
61
|
+
# ─── OpenAI (GPT) ────────────────────────────────────────────
|
|
62
|
+
# Required when LLM_PROVIDER=openai
|
|
63
|
+
# Also used for Whisper voice transcription (optional)
|
|
64
|
+
# Get your key at: https://platform.openai.com/settings/organization/api-keys
|
|
65
|
+
OPENAI_API_KEY=
|
|
66
|
+
|
|
67
|
+
# Optional: Override OpenAI base URL for custom endpoints
|
|
68
|
+
# OPENAI_BASE_URL=
|
|
69
|
+
|
|
70
|
+
# ─── Google (Gemini) ─────────────────────────────────────────
|
|
71
|
+
# Required when LLM_PROVIDER=google
|
|
72
|
+
# Get your key at: https://aistudio.google.com/apikey
|
|
73
|
+
GOOGLE_API_KEY=
|
|
74
|
+
|
|
75
|
+
# ─── PragatiGPT (Gignaati — India-first) ─────────────────────
|
|
76
|
+
# Required when LLM_PROVIDER=pragatigpt
|
|
77
|
+
# India's indigenous SLM — 100% data privacy, no foreign cloud dependency
|
|
78
|
+
# Get your key at: https://www.gignaati.com/pragatigpt
|
|
79
|
+
PRAGATIGPT_API_KEY=
|
|
80
|
+
# Optional: Override PragatiGPT base URL (for on-premise deployment)
|
|
81
|
+
# PRAGATIGPT_BASE_URL=https://api.pragatigpt.in/v1
|
|
82
|
+
|
|
83
|
+
# ─── Ollama (Local — Zero Cloud) ─────────────────────────────
|
|
84
|
+
# Required when LLM_PROVIDER=ollama
|
|
85
|
+
# Install Ollama at: https://ollama.com
|
|
86
|
+
# Then pull a model: ollama pull llama3.2
|
|
87
|
+
# Optional: Override Ollama server URL (default: http://localhost:11434)
|
|
88
|
+
# OLLAMA_BASE_URL=http://localhost:11434
|
|
89
|
+
|
|
90
|
+
# ─── Custom OpenAI-Compatible API ────────────────────────────
|
|
91
|
+
# Required when LLM_PROVIDER=custom
|
|
92
|
+
# OPENAI_BASE_URL=http://localhost:11434/v1
|
|
93
|
+
# CUSTOM_API_KEY=your_api_key_here
|
|
94
|
+
|
|
95
|
+
# ─── Docker & Deployment ─────────────────────────────────────
|
|
96
|
+
# Let's Encrypt email for automatic SSL (docker-compose only, optional)
|
|
97
|
+
# LETSENCRYPT_EMAIL=
|
|
98
|
+
|
|
99
|
+
# Giga Bot version — auto-set by postinstall, used by docker-compose for image tags
|
|
100
|
+
# GIGABOT_VERSION=
|
|
101
|
+
|
|
102
|
+
# Custom Docker images (optional, overrides the default gignaati/gigabot images)
|
|
103
|
+
# EVENT_HANDLER_IMAGE_URL=
|
|
104
|
+
# JOB_IMAGE_URL=
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
name: Auto-Merge Job PR
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened]
|
|
6
|
+
branches: [main]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
auto-merge:
|
|
10
|
+
runs-on: ${{ vars.RUNS_ON || 'ubuntu-latest' }}
|
|
11
|
+
if: startsWith(github.event.pull_request.head.ref, 'job/')
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
pull-requests: write
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Wait for merge check
|
|
18
|
+
id: merge-check
|
|
19
|
+
env:
|
|
20
|
+
GH_TOKEN: ${{ github.token }}
|
|
21
|
+
run: |
|
|
22
|
+
PR_NUMBER="${{ github.event.pull_request.number }}"
|
|
23
|
+
for i in $(seq 1 30); do
|
|
24
|
+
sleep 10
|
|
25
|
+
MERGEABLE=$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json mergeable -q '.mergeable')
|
|
26
|
+
if [ "$MERGEABLE" != "" ] && [ "$MERGEABLE" != "UNKNOWN" ]; then
|
|
27
|
+
echo "mergeable=$MERGEABLE" >> "$GITHUB_OUTPUT"
|
|
28
|
+
echo "Mergeable: $MERGEABLE"
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
echo "Still computing... (attempt $i/30)"
|
|
32
|
+
done
|
|
33
|
+
echo "mergeable=UNKNOWN" >> "$GITHUB_OUTPUT"
|
|
34
|
+
echo "Timed out waiting for merge check"
|
|
35
|
+
|
|
36
|
+
- name: Check AUTO_MERGE setting
|
|
37
|
+
if: steps.merge-check.outputs.mergeable == 'MERGEABLE'
|
|
38
|
+
id: check-setting
|
|
39
|
+
run: |
|
|
40
|
+
AUTO_MERGE="${{ vars.AUTO_MERGE }}"
|
|
41
|
+
if [ "$AUTO_MERGE" = "false" ]; then
|
|
42
|
+
echo "Auto-merge disabled via AUTO_MERGE=false"
|
|
43
|
+
echo "enabled=false" >> "$GITHUB_OUTPUT"
|
|
44
|
+
else
|
|
45
|
+
echo "Auto-merge enabled"
|
|
46
|
+
echo "enabled=true" >> "$GITHUB_OUTPUT"
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
- name: Check ALLOWED_PATHS
|
|
50
|
+
if: steps.merge-check.outputs.mergeable == 'MERGEABLE' && steps.check-setting.outputs.enabled == 'true'
|
|
51
|
+
id: check-paths
|
|
52
|
+
env:
|
|
53
|
+
GH_TOKEN: ${{ github.token }}
|
|
54
|
+
run: |
|
|
55
|
+
ALLOWED_PATHS="${{ vars.ALLOWED_PATHS }}"
|
|
56
|
+
PR_NUMBER="${{ github.event.pull_request.number }}"
|
|
57
|
+
|
|
58
|
+
# Default: only logs allowed
|
|
59
|
+
if [ -z "$ALLOWED_PATHS" ]; then
|
|
60
|
+
ALLOWED_PATHS="/logs"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Normalize: ensure each prefix starts with /
|
|
64
|
+
IFS=',' read -ra RAW_PREFIXES <<< "$ALLOWED_PATHS"
|
|
65
|
+
PREFIXES=()
|
|
66
|
+
for p in "${RAW_PREFIXES[@]}"; do
|
|
67
|
+
trimmed=$(echo "$p" | xargs)
|
|
68
|
+
[ -z "$trimmed" ] && continue
|
|
69
|
+
# Ensure leading /
|
|
70
|
+
[[ "$trimmed" != /* ]] && trimmed="/$trimmed"
|
|
71
|
+
PREFIXES+=("$trimmed")
|
|
72
|
+
done
|
|
73
|
+
|
|
74
|
+
# "/" means everything allowed
|
|
75
|
+
for p in "${PREFIXES[@]}"; do
|
|
76
|
+
if [ "$p" = "/" ]; then
|
|
77
|
+
echo "All paths allowed (ALLOWED_PATHS contains /)"
|
|
78
|
+
echo "allowed=true" >> "$GITHUB_OUTPUT"
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
done
|
|
82
|
+
|
|
83
|
+
# Get changed files
|
|
84
|
+
CHANGED_FILES=$(gh pr diff "$PR_NUMBER" --name-only --repo "${{ github.repository }}")
|
|
85
|
+
if [ -z "$CHANGED_FILES" ]; then
|
|
86
|
+
echo "No changed files"
|
|
87
|
+
echo "allowed=true" >> "$GITHUB_OUTPUT"
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# Check each file against prefixes
|
|
92
|
+
# Strip leading / from prefixes for comparison (git paths are relative)
|
|
93
|
+
ALL_OK=true
|
|
94
|
+
while IFS= read -r file; do
|
|
95
|
+
[ -z "$file" ] && continue
|
|
96
|
+
FILE_OK=false
|
|
97
|
+
for prefix in "${PREFIXES[@]}"; do
|
|
98
|
+
compare="${prefix#/}"
|
|
99
|
+
if [[ "$file" == "$compare"* ]]; then
|
|
100
|
+
FILE_OK=true
|
|
101
|
+
break
|
|
102
|
+
fi
|
|
103
|
+
done
|
|
104
|
+
if [ "$FILE_OK" = "false" ]; then
|
|
105
|
+
echo "BLOCKED: $file"
|
|
106
|
+
ALL_OK=false
|
|
107
|
+
fi
|
|
108
|
+
done <<< "$CHANGED_FILES"
|
|
109
|
+
|
|
110
|
+
echo "allowed=$ALL_OK" >> "$GITHUB_OUTPUT"
|
|
111
|
+
|
|
112
|
+
- name: Merge PR
|
|
113
|
+
if: steps.merge-check.outputs.mergeable == 'MERGEABLE' && steps.check-setting.outputs.enabled == 'true' && steps.check-paths.outputs.allowed == 'true'
|
|
114
|
+
env:
|
|
115
|
+
GH_TOKEN: ${{ github.token }}
|
|
116
|
+
run: |
|
|
117
|
+
gh pr merge ${{ github.event.pull_request.number }} --squash --delete-branch --repo "${{ github.repository }}"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: Notify Job Failed
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: ["Agent Job"]
|
|
6
|
+
types: [completed]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
notify-failure:
|
|
10
|
+
runs-on: ${{ vars.RUNS_ON || 'ubuntu-latest' }}
|
|
11
|
+
if: >
|
|
12
|
+
github.event.workflow_run.conclusion != 'success' &&
|
|
13
|
+
startsWith(github.event.workflow_run.head_branch, 'job/')
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout job branch
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
ref: ${{ github.event.workflow_run.head_branch }}
|
|
22
|
+
|
|
23
|
+
- name: Send failure notification
|
|
24
|
+
env:
|
|
25
|
+
GH_TOKEN: ${{ github.token }}
|
|
26
|
+
run: |
|
|
27
|
+
BRANCH="${{ github.event.workflow_run.head_branch }}"
|
|
28
|
+
JOB_ID="${BRANCH#job/}"
|
|
29
|
+
RUN_ID="${{ github.event.workflow_run.id }}"
|
|
30
|
+
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${RUN_ID}"
|
|
31
|
+
|
|
32
|
+
# Read job description from job.config.json (exists on branch from job creation)
|
|
33
|
+
JOB_CONTENT=""
|
|
34
|
+
if [ -f "logs/${JOB_ID}/job.config.json" ]; then
|
|
35
|
+
JOB_CONTENT=$(jq -r '.job // empty' "logs/${JOB_ID}/job.config.json")
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
COMMIT_SHA=$(git rev-parse HEAD)
|
|
39
|
+
STATUS="${{ github.event.workflow_run.conclusion }}"
|
|
40
|
+
|
|
41
|
+
jq -n \
|
|
42
|
+
--arg job_id "$JOB_ID" \
|
|
43
|
+
--arg branch "$BRANCH" \
|
|
44
|
+
--arg status "$STATUS" \
|
|
45
|
+
--arg job "$JOB_CONTENT" \
|
|
46
|
+
--arg run_url "$RUN_URL" \
|
|
47
|
+
--arg commit_sha "$COMMIT_SHA" \
|
|
48
|
+
'{
|
|
49
|
+
job_id: $job_id,
|
|
50
|
+
branch: $branch,
|
|
51
|
+
status: $status,
|
|
52
|
+
job: $job,
|
|
53
|
+
run_url: $run_url,
|
|
54
|
+
pr_url: "",
|
|
55
|
+
changed_files: [],
|
|
56
|
+
commit_message: "",
|
|
57
|
+
commit_sha: $commit_sha,
|
|
58
|
+
merge_result: ""
|
|
59
|
+
}' > /tmp/payload.json
|
|
60
|
+
|
|
61
|
+
curl -s -X POST "${{ vars.APP_URL }}/api/github/webhook" \
|
|
62
|
+
-H "Content-Type: application/json" \
|
|
63
|
+
-H "X-GitHub-Webhook-Secret-Token: ${{ secrets.GH_WEBHOOK_SECRET }}" \
|
|
64
|
+
-d @/tmp/payload.json
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
name: Notify Event Handler
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: ["Auto-Merge Job PR"]
|
|
6
|
+
types: [completed]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
notify:
|
|
10
|
+
runs-on: ${{ vars.RUNS_ON || 'ubuntu-latest' }}
|
|
11
|
+
if: startsWith(github.event.workflow_run.head_branch, 'job/')
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
pull-requests: read
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Get PR number
|
|
18
|
+
id: pr
|
|
19
|
+
env:
|
|
20
|
+
GH_TOKEN: ${{ github.token }}
|
|
21
|
+
run: |
|
|
22
|
+
BRANCH="${{ github.event.workflow_run.head_branch }}"
|
|
23
|
+
|
|
24
|
+
# Try workflow_run.pull_requests first
|
|
25
|
+
PR_NUMBER=$(echo '${{ toJson(github.event.workflow_run.pull_requests) }}' | jq -r '.[0].number // empty')
|
|
26
|
+
|
|
27
|
+
# Fallback: look up PR by head branch
|
|
28
|
+
if [ -z "$PR_NUMBER" ]; then
|
|
29
|
+
PR_NUMBER=$(gh pr list --head "$BRANCH" --state all --repo "${{ github.repository }}" --json number -q '.[0].number')
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if [ -z "$PR_NUMBER" ]; then
|
|
33
|
+
echo "No PR found for branch $BRANCH"
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
PR_URL=$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json url -q '.url')
|
|
38
|
+
|
|
39
|
+
echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
|
|
40
|
+
echo "url=$PR_URL" >> "$GITHUB_OUTPUT"
|
|
41
|
+
echo "Found PR #$PR_NUMBER"
|
|
42
|
+
|
|
43
|
+
- name: Checkout PR branch
|
|
44
|
+
uses: actions/checkout@v4
|
|
45
|
+
with:
|
|
46
|
+
ref: ${{ github.event.workflow_run.head_sha }}
|
|
47
|
+
|
|
48
|
+
- name: Gather job results and notify
|
|
49
|
+
env:
|
|
50
|
+
GH_TOKEN: ${{ github.token }}
|
|
51
|
+
run: |
|
|
52
|
+
PR_NUMBER="${{ steps.pr.outputs.number }}"
|
|
53
|
+
BRANCH="${{ github.event.workflow_run.head_branch }}"
|
|
54
|
+
JOB_ID="${BRANCH#job/}"
|
|
55
|
+
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}"
|
|
56
|
+
|
|
57
|
+
# Check actual PR merge state
|
|
58
|
+
PR_MERGED=$(gh pr view "$PR_NUMBER" --repo "${{ github.repository }}" --json mergedAt -q '.mergedAt')
|
|
59
|
+
if [ -n "$PR_MERGED" ] && [ "$PR_MERGED" != "null" ]; then
|
|
60
|
+
MERGE_RESULT="merged"
|
|
61
|
+
else
|
|
62
|
+
MERGE_RESULT="not_merged"
|
|
63
|
+
fi
|
|
64
|
+
|
|
65
|
+
# 1. Read job description from job.config.json (on disk after checkout)
|
|
66
|
+
JOB_CONTENT=""
|
|
67
|
+
if [ -f "logs/${JOB_ID}/job.config.json" ]; then
|
|
68
|
+
JOB_CONTENT=$(jq -r '.job // empty' "logs/${JOB_ID}/job.config.json")
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# 2. Get last commit message via gh CLI
|
|
72
|
+
COMMIT_MSG=$(gh pr view "$PR_NUMBER" --json commits --jq '.commits[-1].messageHeadline' --repo "${{ github.repository }}" 2>/dev/null || echo "")
|
|
73
|
+
|
|
74
|
+
# 3. Get changed files (names only)
|
|
75
|
+
CHANGED_FILES=$(gh pr diff "$PR_NUMBER" --name-only --repo "${{ github.repository }}" 2>/dev/null || echo "")
|
|
76
|
+
|
|
77
|
+
# 4. Get PR status
|
|
78
|
+
PR_STATUS=$(gh pr view "$PR_NUMBER" --json state --jq '.state' --repo "${{ github.repository }}" 2>/dev/null || echo "open")
|
|
79
|
+
|
|
80
|
+
# 5. Commit SHA for server-side log fetching
|
|
81
|
+
COMMIT_SHA="${{ github.event.workflow_run.head_sha }}"
|
|
82
|
+
|
|
83
|
+
# Determine status based on merge result and PR state
|
|
84
|
+
if [ "$MERGE_RESULT" = "merged" ]; then
|
|
85
|
+
STATUS="completed"
|
|
86
|
+
else
|
|
87
|
+
STATUS="$PR_STATUS"
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# 6. Build flat JSON payload
|
|
91
|
+
jq -n \
|
|
92
|
+
--arg job_id "$JOB_ID" \
|
|
93
|
+
--arg branch "$BRANCH" \
|
|
94
|
+
--arg status "$STATUS" \
|
|
95
|
+
--arg job "$JOB_CONTENT" \
|
|
96
|
+
--arg run_url "$RUN_URL" \
|
|
97
|
+
--arg pr_url "${{ steps.pr.outputs.url }}" \
|
|
98
|
+
--arg commit_message "$COMMIT_MSG" \
|
|
99
|
+
--arg changed_files "$CHANGED_FILES" \
|
|
100
|
+
--arg commit_sha "$COMMIT_SHA" \
|
|
101
|
+
--arg merge_result "$MERGE_RESULT" \
|
|
102
|
+
'{
|
|
103
|
+
job_id: $job_id,
|
|
104
|
+
branch: $branch,
|
|
105
|
+
status: $status,
|
|
106
|
+
job: $job,
|
|
107
|
+
run_url: $run_url,
|
|
108
|
+
pr_url: $pr_url,
|
|
109
|
+
changed_files: ($changed_files | split("\n") | map(select(length > 0))),
|
|
110
|
+
commit_message: $commit_message,
|
|
111
|
+
commit_sha: $commit_sha,
|
|
112
|
+
merge_result: $merge_result
|
|
113
|
+
}' > /tmp/payload.json
|
|
114
|
+
|
|
115
|
+
# 7. Send to event handler
|
|
116
|
+
curl -s -X POST "${{ vars.APP_URL }}/api/github/webhook" \
|
|
117
|
+
-H "Content-Type: application/json" \
|
|
118
|
+
-H "X-GitHub-Webhook-Secret-Token: ${{ secrets.GH_WEBHOOK_SECRET }}" \
|
|
119
|
+
-d @/tmp/payload.json
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
name: Rebuild Event Handler
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
concurrency:
|
|
8
|
+
group: event-handler-deploy
|
|
9
|
+
cancel-in-progress: false
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
deploy:
|
|
13
|
+
runs-on: self-hosted
|
|
14
|
+
timeout-minutes: 20
|
|
15
|
+
steps:
|
|
16
|
+
- name: Pull latest and detect version change
|
|
17
|
+
id: pull
|
|
18
|
+
run: |
|
|
19
|
+
docker exec gigaclaw-event-handler bash -c '
|
|
20
|
+
export GH_TOKEN=$(grep "^GH_TOKEN=" /app/.env | cut -d= -f2-)
|
|
21
|
+
echo "${GH_TOKEN}" | gh auth login --with-token
|
|
22
|
+
gh auth setup-git
|
|
23
|
+
|
|
24
|
+
git fetch origin main
|
|
25
|
+
CHANGED=$(git diff --name-only HEAD origin/main)
|
|
26
|
+
if ! echo "$CHANGED" | grep -qv "^logs/"; then
|
|
27
|
+
echo "SKIP" > /app/.rebuild-status
|
|
28
|
+
git reset --hard origin/main
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Detect gigaclaw version change from package-lock.json in git
|
|
33
|
+
git show HEAD:package-lock.json > /tmp/old-lock.json 2>/dev/null || echo "{}" > /tmp/old-lock.json
|
|
34
|
+
git show origin/main:package-lock.json > /tmp/new-lock.json
|
|
35
|
+
OLD_TPB=$(node -p "try{require(\"/tmp/old-lock.json\").packages[\"node_modules/gigaclaw\"]?.version||\"\"}catch(e){\"\"}")
|
|
36
|
+
NEW_TPB=$(node -p "try{require(\"/tmp/new-lock.json\").packages[\"node_modules/gigaclaw\"]?.version||\"\"}catch(e){\"\"}")
|
|
37
|
+
rm -f /tmp/old-lock.json /tmp/new-lock.json
|
|
38
|
+
|
|
39
|
+
git reset --hard origin/main
|
|
40
|
+
|
|
41
|
+
if [ -n "$OLD_TPB" ] && [ "$OLD_TPB" != "$NEW_TPB" ]; then
|
|
42
|
+
# Version changed — run gigaclaw init to scaffold new templates
|
|
43
|
+
if echo "$NEW_TPB" | grep -q "-"; then
|
|
44
|
+
npx --yes "gigaclaw@${NEW_TPB}" init
|
|
45
|
+
else
|
|
46
|
+
npx --yes gigaclaw@latest init
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Commit any template changes from init
|
|
50
|
+
git add -A
|
|
51
|
+
if ! git diff --cached --quiet; then
|
|
52
|
+
git commit -m "chore: apply gigaclaw init after upgrade"
|
|
53
|
+
git push origin main
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
# Update GIGACLAW_VERSION in .env so docker compose pulls the right image
|
|
57
|
+
if grep -q "^GIGACLAW_VERSION=" /app/.env; then
|
|
58
|
+
sed -i "s/^GIGACLAW_VERSION=.*/GIGACLAW_VERSION=$NEW_TPB/" /app/.env
|
|
59
|
+
else
|
|
60
|
+
echo "GIGACLAW_VERSION=$NEW_TPB" >> /app/.env
|
|
61
|
+
fi
|
|
62
|
+
echo "VERSION_CHANGED" > /app/.rebuild-status
|
|
63
|
+
else
|
|
64
|
+
npm install --omit=dev
|
|
65
|
+
echo "REBUILD" > /app/.rebuild-status
|
|
66
|
+
fi
|
|
67
|
+
'
|
|
68
|
+
|
|
69
|
+
STATUS=$(docker exec gigaclaw-event-handler cat /app/.rebuild-status)
|
|
70
|
+
docker exec gigaclaw-event-handler rm -f /app/.rebuild-status
|
|
71
|
+
echo "status=$STATUS" >> $GITHUB_OUTPUT
|
|
72
|
+
|
|
73
|
+
- name: Rebuild (no version change)
|
|
74
|
+
if: steps.pull.outputs.status == 'REBUILD'
|
|
75
|
+
run: |
|
|
76
|
+
docker exec gigaclaw-event-handler bash -c '
|
|
77
|
+
rm -rf .next-new .next-old
|
|
78
|
+
NEXT_BUILD_DIR=.next-new npm run build
|
|
79
|
+
|
|
80
|
+
mv .next .next-old 2>/dev/null || true
|
|
81
|
+
mv .next-new .next
|
|
82
|
+
|
|
83
|
+
echo "Rebuild complete, reloading Next.js..."
|
|
84
|
+
npx pm2 reload all
|
|
85
|
+
|
|
86
|
+
rm -rf .next-old
|
|
87
|
+
'
|
|
88
|
+
|
|
89
|
+
- name: Pull new image and restart container
|
|
90
|
+
if: steps.pull.outputs.status == 'VERSION_CHANGED'
|
|
91
|
+
run: |
|
|
92
|
+
HOST_DIR=$(docker inspect gigaclaw-event-handler --format '{{index .Config.Labels "com.docker.compose.project.working_dir"}}')
|
|
93
|
+
docker compose -f /project/docker-compose.yml --project-directory "$HOST_DIR" --env-file /project/.env pull event-handler
|
|
94
|
+
docker stop gigaclaw-event-handler || true
|
|
95
|
+
docker rm gigaclaw-event-handler || true
|
|
96
|
+
docker compose -f /project/docker-compose.yml --project-directory "$HOST_DIR" --env-file /project/.env up -d event-handler
|
|
97
|
+
|
|
98
|
+
- name: Rebuild in new container
|
|
99
|
+
if: steps.pull.outputs.status == 'VERSION_CHANGED'
|
|
100
|
+
run: |
|
|
101
|
+
echo "Waiting for new container..."
|
|
102
|
+
for i in $(seq 1 30); do
|
|
103
|
+
if docker exec gigaclaw-event-handler echo "ready" 2>/dev/null; then
|
|
104
|
+
break
|
|
105
|
+
fi
|
|
106
|
+
sleep 2
|
|
107
|
+
done
|
|
108
|
+
|
|
109
|
+
docker exec gigaclaw-event-handler bash -c '
|
|
110
|
+
npm install --omit=dev
|
|
111
|
+
|
|
112
|
+
rm -rf .next-new .next-old
|
|
113
|
+
NEXT_BUILD_DIR=.next-new npm run build
|
|
114
|
+
|
|
115
|
+
mv .next .next-old 2>/dev/null || true
|
|
116
|
+
mv .next-new .next
|
|
117
|
+
|
|
118
|
+
npx pm2 restart all
|
|
119
|
+
|
|
120
|
+
rm -rf .next-old
|
|
121
|
+
'
|