Merge remote-tracking branch 'origin/main'
Build and deploy / deploy (push) Failing after 28s

This commit is contained in:
Valentin ROBIN
2026-07-26 18:08:56 +02:00
10 changed files with 188 additions and 1 deletions
+9
View File
@@ -0,0 +1,9 @@
node_modules
.next
.git
.env*
!.env.local.example
!.env.docker.example
docker
supabase
*.md
+11
View File
@@ -0,0 +1,11 @@
# Le Tribunal — Docker deployment
# --- Domain ---
APP_DOMAIN=acropole.alxczl.fr
# --- Traefik ---
TRAEFIK_NETWORK=proxy
# --- Webhook (auto-deploy on push) ---
# openssl rand -hex 16
WEBHOOK_SECRET=
+35
View File
@@ -0,0 +1,35 @@
name: Build and deploy
run-name: ${{ gitea.actor }} is deploying Le Tribunal
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- name: Build
run: |
npm run build
cp -r .next/static .next/standalone/.next/static
cp -r public .next/standalone/public
env:
NEXT_PUBLIC_SUPABASE_URL: ${{ secrets.SUPABASE_URL }}
NEXT_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }}
- name: Deploy
run: |
tar -czf - -C .next/standalone . | \
curl -sf \
-H "X-Webhook-Secret: ${{ secrets.WEBHOOK_SECRET }}" \
-H "Content-Type: application/octet-stream" \
--data-binary @- \
"${{ secrets.DEPLOY_WEBHOOK }}"
+1
View File
@@ -33,6 +33,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed) # env files (can opt-in for committing if needed)
.env* .env*
!.env.local.example !.env.local.example
!.env.docker.example
# vercel # vercel
.vercel .vercel
+28
View File
@@ -0,0 +1,28 @@
FROM node:22-alpine AS base
WORKDIR /app
FROM base AS deps
COPY package.json package-lock.json ./
RUN npm ci
FROM base AS build
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ARG NEXT_PUBLIC_SUPABASE_URL
ARG NEXT_PUBLIC_SUPABASE_ANON_KEY
ENV NEXT_PUBLIC_SUPABASE_URL=$NEXT_PUBLIC_SUPABASE_URL
ENV NEXT_PUBLIC_SUPABASE_ANON_KEY=$NEXT_PUBLIC_SUPABASE_ANON_KEY
RUN npm run build
FROM base AS runner
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=build /app/public ./public
COPY --from=build --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=build --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
CMD ["node", "server.js"]
+48
View File
@@ -0,0 +1,48 @@
services:
app:
image: node:22-alpine
restart: unless-stopped
working_dir: /app
command: ["/entrypoint.sh"]
environment:
NODE_ENV: production
PORT: 3000
HOSTNAME: 0.0.0.0
volumes:
- app-data:/app
- ./docker/entrypoint.sh:/entrypoint.sh:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.tribunal.rule=Host(`${APP_DOMAIN}`)"
- "traefik.http.routers.tribunal.entrypoints=https"
- "traefik.http.routers.tribunal.tls.certresolver=letsencrypt"
- "traefik.http.routers.tribunal.middlewares=compression@file,hsts-headers@file"
- "traefik.http.services.tribunal.loadbalancer.server.port=3000"
networks:
- proxy
webhook:
build: ./docker/webhook
restart: unless-stopped
environment:
WEBHOOK_SECRET: ${WEBHOOK_SECRET}
volumes:
- app-data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.tribunal-webhook.rule=Host(`containers01.lan.alxczl.fr`) && PathPrefix(`/tribunal-webhook`)"
- "traefik.http.routers.tribunal-webhook.tls.certresolver=voidca"
- "traefik.http.routers.tribunal-webhook.entrypoints=https"
- "traefik.http.routers.tribunal-webhook.middlewares=hsts-headers@file,tribunal-webhook-strip"
- "traefik.http.middlewares.tribunal-webhook-strip.stripprefix.prefixes=/tribunal-webhook"
- "traefik.http.services.tribunal-webhook.loadbalancer.server.port=9000"
networks:
- proxy
volumes:
app-data:
networks:
proxy:
external: true
name: ${TRAEFIK_NETWORK}
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
while [ ! -f /app/server.js ]; do sleep 2; done
while true; do
STAMP=$(cat /app/.deploy-timestamp 2>/dev/null)
node /app/server.js &
PID=$!
while [ "$(cat /app/.deploy-timestamp 2>/dev/null)" = "$STAMP" ]; do
sleep 2
done
kill $PID
wait $PID 2>/dev/null
done
+3
View File
@@ -0,0 +1,3 @@
FROM python:3-alpine
COPY receive.py /receive.py
CMD ["python", "/receive.py"]
+34
View File
@@ -0,0 +1,34 @@
from http.server import HTTPServer, BaseHTTPRequestHandler
import os, tarfile, io, shutil, time
SECRET = os.environ["WEBHOOK_SECRET"]
class Handler(BaseHTTPRequestHandler):
def do_POST(self):
if self.headers.get("X-Webhook-Secret") != SECRET:
self.send_response(401)
self.end_headers()
return
body = self.rfile.read(int(self.headers["Content-Length"]))
for item in os.listdir("/data"):
path = os.path.join("/data", item)
if os.path.isdir(path):
shutil.rmtree(path)
else:
os.remove(path)
with tarfile.open(fileobj=io.BytesIO(body), mode="r:gz") as tar:
tar.extractall("/data", filter="data")
with open("/data/.deploy-timestamp", "w") as f:
f.write(str(time.time()))
self.send_response(200)
self.end_headers()
self.wfile.write(b"OK")
HTTPServer(("0.0.0.0", 9000), Handler).serve_forever()
+6 -1
View File
@@ -1,11 +1,16 @@
import type { NextConfig } from "next"; import type { NextConfig } from "next";
const supabaseHostname = process.env.NEXT_PUBLIC_SUPABASE_URL
? new URL(process.env.NEXT_PUBLIC_SUPABASE_URL).hostname
: "localhost";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
output: "standalone",
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
protocol: "https", protocol: "https",
hostname: "kuichrzrbdwydixbdfon.supabase.co", hostname: supabaseHostname,
pathname: "/storage/v1/object/public/**", pathname: "/storage/v1/object/public/**",
}, },
], ],