Portainer-Deployment: Env-Interpolation statt env_file, lokales Webhook-Test-Skript
- docker-compose.yml: Variablen per Interpolation (lokal aus .env, in Portainer aus Stack-Env) - tools/test-webhook.mjs: signierte Fake-Testzustellung gegen die lokale Instanz - README: Portainer-Anleitung präzisiert (Git-Auth für privates Repo, Pull and redeploy) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -112,20 +112,32 @@ Erwartete Ausgabe:
|
|||||||
|
|
||||||
Dann in Discord: `/ping` → Bot antwortet mit Latenz. 🎉
|
Dann in Discord: `/ping` → Bot antwortet mit Latenz. 🎉
|
||||||
|
|
||||||
|
**Commit-Feed lokal testen** (ohne Gitea — simuliert eine signierte Testzustellung):
|
||||||
|
```
|
||||||
|
node tools/test-webhook.mjs
|
||||||
|
```
|
||||||
|
→ Embed erscheint im Commit-Kanal, Commit landet in der lokalen SQLite (`data/ecobot.db`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Deployment (Docker / Portainer)
|
## Deployment (Docker / Portainer)
|
||||||
|
|
||||||
### Variante A: Portainer-Stack aus Git (empfohlen)
|
### Variante A: Portainer-Stack aus Git (empfohlen)
|
||||||
1. Portainer → **Stacks** → **Add stack**
|
1. Portainer → **Stacks** → **Add stack** → Name: `ecobot`
|
||||||
2. **Repository** wählen:
|
2. Build method: **Repository**
|
||||||
- URL: `https://git.d4rkst3r.de/D4rkst3r/ecobot.git`
|
- Repository URL: `https://git.d4rkst3r.de/D4rkst3r/ecobot`
|
||||||
|
- Repository reference: `refs/heads/main`
|
||||||
- Compose path: `docker-compose.yml`
|
- Compose path: `docker-compose.yml`
|
||||||
3. Unter **Environment variables** die drei Werte aus der `.env` eintragen
|
- Falls das Repo privat ist: **Authentication** aktivieren —
|
||||||
(`DISCORD_TOKEN`, `DISCORD_CLIENT_ID`, `DISCORD_GUILD_ID`)
|
Username: `D4rkst3r`, Password: ein Gitea-Token
|
||||||
— alternativ `env_file` weglassen und die Variablen direkt im Stack setzen
|
(Gitea → Einstellungen → Anwendungen → Token erzeugen, Scope `read:repository`)
|
||||||
|
3. Unter **Environment variables** → **Advanced mode** die Werte aus der lokalen `.env`
|
||||||
|
eintragen (`DISCORD_TOKEN`, `DISCORD_CLIENT_ID`, `DISCORD_GUILD_ID`,
|
||||||
|
`COMMIT_CHANNEL_ID`, `GITEA_WEBHOOK_SECRET`)
|
||||||
4. **Deploy the stack**
|
4. **Deploy the stack**
|
||||||
|
|
||||||
|
Updates später: Stack öffnen → **Pull and redeploy** (holt den neuesten Stand von `main`).
|
||||||
|
|
||||||
### Variante B: Manuell auf dem Server
|
### Variante B: Manuell auf dem Server
|
||||||
```
|
```
|
||||||
git clone git@gitea:D4rkst3r/ecobot.git
|
git clone git@gitea:D4rkst3r/ecobot.git
|
||||||
|
|||||||
+9
-1
@@ -5,7 +5,15 @@ services:
|
|||||||
image: ecobot:latest
|
image: ecobot:latest
|
||||||
container_name: ecobot
|
container_name: ecobot
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
env_file: .env
|
# Werte kommen per Interpolation: lokal aus der .env im Projektordner (liest
|
||||||
|
# docker compose automatisch), in Portainer aus den Stack-Environment-Variables
|
||||||
|
environment:
|
||||||
|
DISCORD_TOKEN: ${DISCORD_TOKEN}
|
||||||
|
DISCORD_CLIENT_ID: ${DISCORD_CLIENT_ID}
|
||||||
|
DISCORD_GUILD_ID: ${DISCORD_GUILD_ID:-}
|
||||||
|
COMMIT_CHANNEL_ID: ${COMMIT_CHANNEL_ID}
|
||||||
|
GITEA_WEBHOOK_SECRET: ${GITEA_WEBHOOK_SECRET}
|
||||||
|
DB_PATH: /app/data/ecobot.db
|
||||||
# HTTP-Endpoint für Gitea-Webhooks + Webinterface
|
# HTTP-Endpoint für Gitea-Webhooks + Webinterface
|
||||||
# NPM leitet bot.d4rkst3r.de → host.docker.internal:3080
|
# NPM leitet bot.d4rkst3r.de → host.docker.internal:3080
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// Simuliert eine Gitea-Testzustellung gegen die lokale Bot-Instanz.
|
||||||
|
// Nutzung: node tools/test-webhook.mjs (Bot muss laufen: npm run dev)
|
||||||
|
import 'dotenv/config';
|
||||||
|
import crypto from 'node:crypto';
|
||||||
|
|
||||||
|
const secret = process.env.GITEA_WEBHOOK_SECRET;
|
||||||
|
if (!secret) {
|
||||||
|
console.error('GITEA_WEBHOOK_SECRET fehlt in der .env');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const port = process.env.HTTP_PORT || 3080;
|
||||||
|
const url = `http://localhost:${port}/webhooks/gitea`;
|
||||||
|
|
||||||
|
const sha = crypto.randomBytes(20).toString('hex'); // zufällige SHA → Dedupe greift nicht
|
||||||
|
const payload = JSON.stringify({
|
||||||
|
ref: 'refs/heads/main',
|
||||||
|
compare_url: 'https://git.d4rkst3r.de/D4rkst3r/EcoGame',
|
||||||
|
repository: {
|
||||||
|
full_name: 'D4rkst3r/EcoGame (Test)',
|
||||||
|
html_url: 'https://git.d4rkst3r.de/D4rkst3r/EcoGame',
|
||||||
|
},
|
||||||
|
pusher: { username: 'D4rkst3r' },
|
||||||
|
sender: { avatar_url: null },
|
||||||
|
commits: [
|
||||||
|
{
|
||||||
|
id: sha,
|
||||||
|
message: 'Testzustellung — wenn du das im Discord siehst, funktioniert der Commit-Feed 🎉',
|
||||||
|
url: `https://git.d4rkst3r.de/D4rkst3r/EcoGame/commit/${sha}`,
|
||||||
|
author: { name: 'D4rkst3r', username: 'D4rkst3r' },
|
||||||
|
timestamp: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
|
||||||
|
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'content-type': 'application/json',
|
||||||
|
'x-gitea-event': 'push',
|
||||||
|
'x-gitea-signature': signature,
|
||||||
|
},
|
||||||
|
body: payload,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`${res.status} →`, await res.json());
|
||||||
Reference in New Issue
Block a user