feat: Migrer génération PDF de PDFMonkey vers Gotenberg

- Remplacer PDFMonkey par Gotenberg (auto-hébergé sur VPS)
- Créer template Handlebars pour contrats (lib/templates/contract.hbs)
- Créer formateur de données (lib/contract-data-formatter.ts)
- Ajouter helpers Handlebars pour conditions et transformations
- Mettre à jour API route generate-pdf pour utiliser Gotenberg
- Ajouter GOTENBERG_URL dans .env.local (http://localhost:3001 pour dev)
- Créer script tunnel-gotenberg.sh pour dev local
- Ajouter documentation MIGRATION_GOTENBERG.md

Avantages:
- Souveraineté des données (pas d'API externe)
- Performance (génération locale)
- Coût (0€ vs abonnement PDFMonkey)
- Sécurité (Gotenberg non exposé publiquement)
This commit is contained in:
odentas 2025-12-27 22:22:45 +01:00
parent c6faceb038
commit 04e9d54292
16 changed files with 2111 additions and 139 deletions

29
.coolifyignore Normal file
View file

@ -0,0 +1,29 @@
# Fichiers spécifiques à Vercel - inutiles sur Coolify
vercel.json
.vercel/
# Fichiers de développement et tests
*.md
!README.md
.DS_Store
.env.*
!.env.example
.vscode/
.github/
# Logs et temporaires
*.log
tmp/
test-signature-output/
# CSV et données tests
*.csv
*.xlsx
# Scripts de dev
scripts/
dev-with-network.sh
fix-eslint.sh
test-*.sh
test-*.js
test-*.mjs

View file

@ -1,4 +1,5 @@
# Variables publiques (exposées au client)
NEXT_PUBLIC_SITE_URL=https://your-domain.com
NEXT_PUBLIC_API_BASE=https://your-api-gateway.amazonaws.com/default
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

29
.env.local.gotenberg-test Normal file
View file

@ -0,0 +1,29 @@
# Configuration pour test Gotenberg avec Coolify
# ========================================
# URL de Gotenberg
# ========================================
# Option A : Domaine Coolify (RECOMMANDÉ pour production)
# 1. Dans Coolify, configurer un domaine pour Gotenberg
# 2. Exemple : gotenberg.odnt.fr
# GOTENBERG_URL=https://gotenberg.odnt.fr
# Option B : Tunnel SSH (pour test local uniquement)
# 1. Ouvrir un terminal et lancer : ssh -L 3001:gotenberg:3000 renaud@144.91.113.70 -N
# 2. Laisser le tunnel ouvert
# 3. Utiliser cette URL :
GOTENBERG_URL=http://localhost:3001
# ========================================
# VPS Info (pour référence)
# ========================================
# VPS IP: 144.91.113.70
# SSH: ssh renaud@144.91.113.70
# Gotenberg interne: http://gotenberg:3000 (réseau Docker Coolify)
# ========================================
# Configuration Supabase (déjà présente dans .env.local)
# ========================================
# NEXT_PUBLIC_SUPABASE_URL=https://...
# SUPABASE_SERVICE_ROLE_KEY=eyJ...

View file

@ -12,6 +12,19 @@ Le projet utilise un Dockerfile multi-stage optimisé pour Next.js en mode stand
## 📋 Variables d'environnement requises
### Application (CRITIQUE)
```
NEXT_PUBLIC_SITE_URL=https://paie.odnt.fr
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1
```
**Important** : `NEXT_PUBLIC_SITE_URL` remplace `VERCEL_URL` et est utilisé pour :
- Génération des liens dans les emails
- Callbacks d'authentification Supabase
- Webhooks DocuSeal
- Tokens d'auto-déclaration
### Supabase
```
NEXT_PUBLIC_SUPABASE_URL=
@ -63,12 +76,26 @@ LAMBDA_PDF_CONVERTER_URL=
### Autres
```
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1
JWT_SECRET=
ENCRYPTION_KEY=
```
## ⚙️ Configuration Supabase
**Important** : Ajouter les URLs de redirection dans Supabase Dashboard → Authentication → URL Configuration :
**Site URL** :
```
https://paie.odnt.fr
```
**Redirect URLs** (whitelist) :
```
https://paie.odnt.fr/**
https://paie.odnt.fr/auth/callback
https://paie.odnt.fr/auto-declaration/**
```
## 🚀 Configuration dans Coolify
1. **Créer un nouveau projet** dans Coolify
@ -107,13 +134,45 @@ Coolify détectera automatiquement le changement et redéployera l'application.
## ✅ Vérifications post-déploiement
1. Vérifier que toutes les variables d'environnement sont configurées
2. Tester l'accès à l'application
3. Vérifier les logs dans Coolify
4. Tester les fonctionnalités critiques :
- Authentification
- Génération de contrats
- Signature électronique
- Upload de documents
2. **Vérifier `NEXT_PUBLIC_SITE_URL=https://paie.odnt.fr`** (critique)
3. Vérifier les Redirect URLs dans Supabase Dashboard
4. Tester l'accès à l'application
5. Vérifier les logs dans Coolify
6. Tester les fonctionnalités critiques :
- Authentification (connexion/déconnexion)
- Emails (OTP, invitations)
- Génération de contrats PDF
- Signature électronique (DocuSeal)
- Upload de documents (AWS S3)
- Auto-déclaration congés spectacles
## 🔧 Cron Jobs
Le cron défini dans `vercel.json` ne fonctionne pas sur Coolify. Configuration manuelle nécessaire :
**Option A** : Créer un service Coolify séparé
- Type : Scheduled Task
- Commande : `curl -f https://paie.odnt.fr/api/cron/send-csp-report`
- Schedule : `0 9 * * *` (tous les jours à 9h)
**Option B** : Utiliser cron système sur le serveur hôte
```bash
0 9 * * * curl -f https://paie.odnt.fr/api/cron/send-csp-report
```
## 📊 Différences Vercel vs Coolify
| Fonctionnalité | Vercel | Coolify |
|----------------|--------|---------|
| **Build** | Vercel Build System | Docker multi-stage |
| **Région** | cdg1 (Paris - `vercel.json`) | Votre serveur |
| **Crons** | `vercel.json` | Service séparé ou cron système |
| **Headers conditionnels** | `vercel.json` | `middleware.ts` (déjà géré) |
| **Edge Functions** | Oui | Non (Next.js standard) |
| **Serverless** | Oui | Non (conteneur permanent) |
| **Variables d'env** | `VERCEL_URL` (automatique) | `NEXT_PUBLIC_SITE_URL` (manuel) |
Le middleware Next.js gère déjà les headers et le mode démo, donc pas de régression fonctionnelle.
## 📝 Notes

View file

@ -0,0 +1,48 @@
# Configuration Gotenberg avec tunnel SSH vers VPS Coolify
## Option A : Exposer Gotenberg dans Coolify (RECOMMANDÉ)
1. Dans Coolify, aller dans votre service Gotenberg
2. Aller dans l'onglet "Domains"
3. Ajouter un domaine : `gotenberg.odnt.fr` (ou un autre)
4. Coolify va automatiquement configurer Nginx + Let's Encrypt
5. Utiliser l'URL : `https://gotenberg.odnt.fr`
Ensuite dans `.env.local` :
```bash
GOTENBERG_URL=https://gotenberg.odnt.fr
```
## Option B : Tunnel SSH pour test local (TEMPORAIRE)
Si vous voulez tester sans exposer Gotenberg publiquement :
```bash
# Créer un tunnel SSH qui forward le port local 3001 vers gotenberg:3000 sur le VPS
ssh -L 3001:gotenberg:3000 renaud@144.91.113.70 -N
# Laisser cette commande tourner dans un terminal
# Dans un autre terminal :
echo "GOTENBERG_URL=http://localhost:3001" >> .env.local
```
## Vérification de la configuration Coolify
SSH dans le VPS et vérifier que Gotenberg tourne :
```bash
ssh renaud@144.91.113.70
# Vérifier que le container existe
docker ps | grep gotenberg
# Tester depuis le VPS (réseau interne)
docker exec $(docker ps -q -f name=gotenberg) curl -s http://localhost:3000/health
# Ou si vous avez curl sur le VPS
curl http://gotenberg:3000/health
```
## Quelle option choisir ?
- **Option A** : Si vous voulez utiliser Gotenberg en production → Exposer via domaine
- **Option B** : Pour tests rapides uniquement → Tunnel SSH

117
MIGRATION_GOTENBERG.md Normal file
View file

@ -0,0 +1,117 @@
# Migration de PDFMonkey vers Gotenberg
## Résumé des changements
Le bouton "Créer PDF" sur la page `staff/contrats/[id]` utilise désormais **Gotenberg** (auto-hébergé sur le VPS) au lieu de PDFMonkey.
## Fichiers modifiés
### 1. API Route
- **Fichier**: `app/api/contrats/[id]/generate-pdf/route.ts`
- **Changements**:
- Remplacement de l'appel à PDFMonkey par Gotenberg
- Utilisation de templates Handlebars au lieu de Liquid
- Suppression de la fonction de polling
- Génération PDF instantanée
### 2. Nouveaux fichiers créés
#### Template Handlebars
- **Fichier**: `lib/templates/contract.hbs`
- **Description**: Template HTML/CSS pour générer les contrats de travail
- **Format**: Handlebars (conversion depuis Liquid)
#### Helpers Handlebars
- **Fichier**: `lib/handlebars-helpers.ts` (déjà existant, mis à jour)
- **Description**: Helpers personnalisés pour les conditions et transformations
#### Formateur de données
- **Fichier**: `lib/contract-data-formatter.ts`
- **Description**: Prépare et formate les données du contrat avant génération
#### Scripts
- **Fichier**: `tunnel-gotenberg.sh`
- **Description**: Script pour créer un tunnel SSH vers Gotenberg (dev local)
## Dépendances ajoutées
```bash
npm install handlebars
npm install --save-dev @types/handlebars
```
## Configuration
### Variables d'environnement
#### Développement local (.env.local)
```bash
GOTENBERG_URL=http://localhost:3001
```
#### Production (Coolify / VPS)
```bash
GOTENBERG_URL=http://gotenberg:3000
```
> **Note**: En production, l'app Next.js et Gotenberg sont sur le même réseau Docker `coolify`, donc `gotenberg:3000` fonctionne directement.
## Utilisation en développement
1. **Créer un tunnel SSH vers Gotenberg**:
```bash
./tunnel-gotenberg.sh
```
Ou manuellement :
```bash
ssh -L 3001:gotenberg:3000 renaud@144.91.113.70 -N
```
2. **Lancer le serveur Next.js**:
```bash
npm run dev
```
3. **Tester la génération**:
- Aller sur `staff/contrats/[id]`
- Cliquer sur "Créer PDF"
- Le PDF est généré via Gotenberg et uploadé sur S3
## Flux de génération
1. **Frontend** : Clic sur "Créer PDF"
2. **API Route** : Récupère les données du contrat depuis Supabase
3. **Formatter** : Formate les données pour le template
4. **Template** : Compile le template Handlebars avec les données
5. **Gotenberg** : Convertit le HTML en PDF
6. **S3** : Upload du PDF généré
7. **Supabase** : Mise à jour du contrat avec l'URL du PDF
## Avantages
- **Souveraineté des données** : Aucune donnée ne sort du VPS
- **Performance** : Génération locale, pas de latence réseau
- **Coût** : 0€ (vs abonnement PDFMonkey)
- **Sécurité** : Gotenberg n'est pas exposé publiquement
## Déploiement
Le code s'auto-déploie sur Coolify lors d'un push. En production :
- `GOTENBERG_URL=http://gotenberg:3000` est déjà configuré
- Pas besoin de tunnel, tout communique via le réseau Docker interne
## Rollback (si nécessaire)
Pour revenir à PDFMonkey en cas de problème :
1. Restaurer `app/api/contrats/[id]/generate-pdf/route.ts` depuis le commit précédent
2. Remettre `PDFMONKEY_URL` et `PDFMONKEY_API_KEY` dans les variables d'environnement
## Support
- **Guide complet** : Voir `gotenberg-integration-guide.md`
- **Documentation Gotenberg** : https://gotenberg.dev/
- **Logs Gotenberg** : `sudo docker logs gotenberg` (sur le VPS)
---
Date de migration : 27 décembre 2025

View file

@ -7,6 +7,9 @@ import { PROFESSIONS_ARTISTE, ProfessionOption } from "@/components/constants/Pr
import { parseDateString } from "@/lib/dateFormatter";
import { promises as fs } from "fs";
import path from "path";
import Handlebars from "handlebars";
import { registerHandlebarsHelpers } from "@/lib/handlebars-helpers";
import { formatContractData } from "@/lib/contract-data-formatter";
// Type pour les féminisations
type ProfessionFeminisation = {
@ -107,42 +110,6 @@ function formatDate(dateStr: string | null): string {
return `${dd}/${mm}/${yyyy}`;
}
// Fonction de polling pour vérifier le statut du document PDFMonkey
async function pollDocumentStatus(documentId: string, pdfMonkeyUrl: string, pdfMonkeyApiKey: string) {
const url = `${pdfMonkeyUrl}/${documentId}`;
let attempts = 0;
const maxAttempts = 10;
let status = "pending";
while (status !== "success" && attempts < maxAttempts) {
console.log(`Polling PDFMonkey (tentative ${attempts + 1}/${maxAttempts})...`);
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${pdfMonkeyApiKey}`
}
});
if (!response.ok) {
throw new Error(`Erreur PDFMonkey: ${response.status} ${response.statusText}`);
}
const data = await response.json();
status = data.document.status;
console.log("Statut du document:", status);
if (status === "success") {
return data.document;
}
await new Promise(resolve => setTimeout(resolve, 3000));
attempts++;
}
return { status, attempts };
}
// Fonction pour formater un texte de dates brutes en texte PDFMonkey formaté
function formatDateFieldIfNeeded(dateText: string | null | undefined, yearContext: string): string {
if (!dateText || !dateText.trim()) return "";
@ -192,12 +159,11 @@ export async function POST(
}
// Variables d'environnement
const pdfMonkeyUrl = process.env.PDFMONKEY_URL;
const pdfMonkeyApiKey = process.env.PDFMONKEY_API_KEY;
const gotenbergUrl = process.env.GOTENBERG_URL || 'http://gotenberg:3000';
if (!pdfMonkeyUrl || !pdfMonkeyApiKey) {
if (!gotenbergUrl) {
return NextResponse.json(
{ error: "Configuration PDFMonkey manquante" },
{ error: "Configuration Gotenberg manquante" },
{ status: 500 }
);
}
@ -351,7 +317,7 @@ export async function POST(
console.log(`Jours de travail (jours_travail): "${contract.jours_travail}"`);
console.log(`Jours de travail non-artiste (jours_travail_non_artiste): "${contract.jours_travail_non_artiste}"`);
// Construction du payload pour PDFMonkey selon le mapping CSV
// Construction du payload pour Gotenberg selon le mapping CSV
const dataPayload = {
structure_name: organization?.name || orgDetails.structure || "",
structure_adresse: orgDetails.adresse || "",
@ -458,114 +424,93 @@ export async function POST(
hasDataPrefix: orgDetails.logo?.startsWith('data:') || false
});
const pdfPayload = {
document_template_id: "736E1A5F-BBA1-4D3E-91ED-A6184479B58D",
payload: dataPayload,
status: "pending",
filename: filename
};
// Formater les données du contrat pour Handlebars
const formattedData = formatContractData(dataPayload);
console.log("Payload envoyé à PDFMonkey:", JSON.stringify(pdfPayload, null, 2));
console.log("Données formatées pour Gotenberg:", JSON.stringify(formattedData, null, 2));
// Envoi du payload vers PDFMonkey
const pdfResponse = await fetch(pdfMonkeyUrl, {
// Enregistrer les helpers Handlebars
registerHandlebarsHelpers();
// Charger et compiler le template Handlebars
const templatePath = path.join(process.cwd(), 'lib', 'templates', 'contract.hbs');
const templateHTML = await fs.readFile(templatePath, 'utf8');
const template = Handlebars.compile(templateHTML);
// Générer le HTML à partir du template
const html = template(formattedData);
console.log("HTML généré (premiers 500 caractères):", html.substring(0, 500));
// Envoyer le HTML à Gotenberg pour conversion en PDF
const formData = new FormData();
formData.append('files', new Blob([html], { type: 'text/html' }), 'index.html');
console.log("Envoi à Gotenberg:", `${gotenbergUrl}/forms/chromium/convert/html`);
const gotenbergResponse = await fetch(`${gotenbergUrl}/forms/chromium/convert/html`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${pdfMonkeyApiKey}`
},
body: JSON.stringify(pdfPayload)
body: formData,
});
if (!pdfResponse.ok) {
const errorText = await pdfResponse.text();
console.error("Erreur PDFMonkey:", pdfResponse.status, errorText);
if (!gotenbergResponse.ok) {
const errorText = await gotenbergResponse.text();
console.error("Erreur Gotenberg:", gotenbergResponse.status, errorText);
return NextResponse.json(
{ error: `Erreur PDFMonkey: ${pdfResponse.status}` },
{ error: `Erreur Gotenberg: ${gotenbergResponse.status}` },
{ status: 500 }
);
}
const pdfData = await pdfResponse.json();
console.log("Réponse initiale de PDFMonkey:", JSON.stringify(pdfData));
const pdfBuffer = Buffer.from(await gotenbergResponse.arrayBuffer());
console.log("PDF généré par Gotenberg, taille:", pdfBuffer.length, "octets");
// Récupération de l'ID du document
const documentId = pdfData.document?.id;
if (!documentId) {
throw new Error("Aucun ID de document retourné par PDFMonkey");
}
// Upload vers S3
const s3Key = `unsigned-contracts/${filename}`;
console.log("Upload du fichier dans S3 sous la clé:", s3Key);
console.log("ID du document PDFMonkey:", documentId);
const uploadCommand = new PutObjectCommand({
Bucket: (process.env.AWS_S3_BUCKET || "odentas-docs").trim(),
Key: s3Key,
Body: pdfBuffer,
ContentType: "application/pdf",
});
// Polling pour vérifier le statut jusqu'à "success"
const finalDocumentData = await pollDocumentStatus(documentId, pdfMonkeyUrl, pdfMonkeyApiKey);
console.log("Document final:", JSON.stringify(finalDocumentData));
await s3Client.send(uploadCommand);
console.log("Fichier PDF uploadé sur S3 avec succès.");
if (finalDocumentData.download_url) {
console.log("Téléchargement du PDF depuis:", finalDocumentData.download_url);
// Télécharger le PDF depuis PDFMonkey
const pdfResponse = await fetch(finalDocumentData.download_url);
if (!pdfResponse.ok) {
throw new Error("Impossible de télécharger le PDF depuis PDFMonkey");
}
const pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
// Upload vers S3
const s3Key = `unsigned-contracts/${filename}`;
console.log("Upload du fichier dans S3 sous la clé:", s3Key);
const uploadCommand = new PutObjectCommand({
Bucket: (process.env.AWS_S3_BUCKET || "odentas-docs").trim(),
Key: s3Key,
Body: pdfBuffer,
ContentType: "application/pdf",
});
await s3Client.send(uploadCommand);
console.log("Fichier PDF uploadé sur S3 avec succès.");
// URL S3 pour accéder au fichier
const bucketName = (process.env.AWS_S3_BUCKET || "odentas-docs").trim();
const s3Url = `https://${bucketName}.s3.eu-west-3.amazonaws.com/${s3Key}`;
// Mettre à jour le contrat avec l'URL du PDF
console.log("Mise à jour du contrat avec:", {
// URL S3 pour accéder au fichier
const bucketName = (process.env.AWS_S3_BUCKET || "odentas-docs").trim();
const s3Url = `https://${bucketName}.s3.eu-west-3.amazonaws.com/${s3Key}`;
// Mettre à jour le contrat avec l'URL du PDF
console.log("Mise à jour du contrat avec:", {
contract_pdf_url: s3Url,
contract_pdf_filename: filename
});
const { error: updateError } = await sb
.from("cddu_contracts")
.update({
contract_pdf_url: s3Url,
contract_pdf_filename: filename
});
const { error: updateError } = await sb
.from("cddu_contracts")
.update({
contract_pdf_url: s3Url,
contract_pdf_filename: filename
})
.eq("id", params.id);
if (updateError) {
console.error("Erreur lors de la mise à jour du contrat:", updateError);
} else {
console.log("Contrat mis à jour avec succès");
}
return NextResponse.json({
success: true,
message: "PDF créé et sauvegardé avec succès",
documentId: documentId,
filename: filename,
s3Url: s3Url,
pdfMonkeyResponse: finalDocumentData
});
})
.eq("id", params.id);
if (updateError) {
console.error("Erreur lors de la mise à jour du contrat:", updateError);
} else {
return NextResponse.json(
{ error: "Aucun URL de téléchargement disponible" },
{ status: 500 }
);
console.log("Contrat mis à jour avec succès");
}
return NextResponse.json({
success: true,
message: "PDF créé et sauvegardé avec succès",
filename: filename,
contract_pdf_url: s3Url,
contract_pdf_filename: filename
});
} catch (error) {
console.error("Erreur lors de la génération du PDF:", error);
return NextResponse.json(

View file

@ -0,0 +1,60 @@
// app/api/debug/env-check/route.ts
export const dynamic = "force-dynamic";
import { NextResponse } from "next/server";
/**
* Route de debug pour vérifier les variables d'environnement critiques
* NE PAS UTILISER EN PRODUCTION (sauf temporairement)
*/
export async function GET() {
const envCheck = {
// Variables publiques
NEXT_PUBLIC_SUPABASE_URL: {
exists: !!process.env.NEXT_PUBLIC_SUPABASE_URL,
value: process.env.NEXT_PUBLIC_SUPABASE_URL ? `${process.env.NEXT_PUBLIC_SUPABASE_URL.substring(0, 30)}...` : 'MANQUANT',
},
NEXT_PUBLIC_SUPABASE_ANON_KEY: {
exists: !!process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
length: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY?.length || 0,
preview: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ? `${process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY.substring(0, 20)}...` : 'MANQUANT',
},
NEXT_PUBLIC_SITE_URL: {
exists: !!process.env.NEXT_PUBLIC_SITE_URL,
value: process.env.NEXT_PUBLIC_SITE_URL || 'MANQUANT',
},
// Variables privées (ne pas afficher les valeurs)
SUPABASE_SERVICE_ROLE_KEY: {
exists: !!process.env.SUPABASE_SERVICE_ROLE_KEY,
length: process.env.SUPABASE_SERVICE_ROLE_KEY?.length || 0,
},
SUPABASE_URL: {
exists: !!process.env.SUPABASE_URL,
value: process.env.SUPABASE_URL ? `${process.env.SUPABASE_URL.substring(0, 30)}...` : 'MANQUANT',
},
// Environnement
NODE_ENV: process.env.NODE_ENV || 'MANQUANT',
VERCEL_URL: process.env.VERCEL_URL || 'non défini (normal sur Coolify)',
// Résumé
summary: {
allPublicVarsPresent: !!(
process.env.NEXT_PUBLIC_SUPABASE_URL &&
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY &&
process.env.NEXT_PUBLIC_SITE_URL
),
allPrivateVarsPresent: !!(
process.env.SUPABASE_SERVICE_ROLE_KEY &&
process.env.SUPABASE_URL
),
}
};
return NextResponse.json(envCheck, {
status: 200,
headers: {
'Cache-Control': 'no-store, no-cache, must-revalidate',
}
});
}

View file

@ -0,0 +1,787 @@
2025-Dec-27 15:06:51.478048 Starting deployment of https://<REDACTED>/renaud/espace-paie-odentas.git:main to localhost.
2025-Dec-27 15:06:51.721843 Preparing container with helper image: ghcr.io/coollabsio/coolify-helper:1.0.12
2025-Dec-27 15:06:51.910952 [CMD]: docker stop -t 30 swko0o00o8c8ooc8g84oowk4
2025-Dec-27 15:06:51.910952 Error response from daemon: No such container: swko0o00o8c8ooc8g84oowk4
2025-Dec-27 15:06:52.112206 [CMD]: docker run -d --network coolify --name swko0o00o8c8ooc8g84oowk4 --rm -v /var/run/docker.sock:/var/run/docker.sock ghcr.io/coollabsio/coolify-helper:1.0.12
2025-Dec-27 15:06:52.112206 b653d3151d53cf8101a3a9bc3ecb89c4ee997e793d5c3738d1ad75a5a3aa0fc9
2025-Dec-27 15:06:53.446257 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git ls-remote https://<REDACTED>/renaud/espace-paie-odentas.git refs/heads/main'
2025-Dec-27 15:06:53.446257 6e02b6970c79ca5304973aba9a5412ea8835eeb5 refs/heads/main
2025-Dec-27 15:06:53.471608 ----------------------------------------
2025-Dec-27 15:06:53.484451 Importing https://<REDACTED>/renaud/espace-paie-odentas.git:main (commit sha 6e02b6970c79ca5304973aba9a5412ea8835eeb5) to /artifacts/swko0o00o8c8ooc8g84oowk4.
2025-Dec-27 15:06:53.896563 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'mkdir -p /root/.ssh' && docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'echo 'LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFNd0FBQUF0emMyZ3RaVwpReU5UVXhPUUFBQUNBY241UWlTcUR2cnZqZjlXQmJLNlU0MlNLNzdPdjhLTENUN0JDT1RkWm1XQUFBQUtBb2wxSi9LSmRTCmZ3QUFBQXR6YzJndFpXUXlOVFV4T1FBQUFDQWNuNVFpU3FEdnJ2amY5V0JiSzZVNDJTSzc3T3Y4S0xDVDdCQ09UZFptV0EKQUFBRUJsKzM0elVjZVhuYkpnYWhwL2hVQW5pRjNKbytUais4TzBuM09zSjU5QUhoeWZsQ0pLb08rdStOLzFZRnNycFRqWgpJcnZzNi93b3NKUHNFSTVOMW1aWUFBQUFGM0JvY0hObFkyeHBZaTFuWlc1bGNtRjBaV1F0YTJWNUFRSURCQVVHCi0tLS0tRU5EIE9QRU5TU0ggUFJJVkFURSBLRVktLS0tLQo=' | base64 -d | tee /root/.ssh/id_rsa > /dev/null' && docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'chmod 600 /root/.ssh/id_rsa' && docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'GIT_SSH_COMMAND="ssh -o ConnectTimeout=30 -p 22 -o Port=22 -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i /root/.ssh/id_rsa" git clone --depth=1 --recurse-submodules --shallow-submodules -b 'main' 'https://<REDACTED>/renaud/espace-paie-odentas.git' '/artifacts/swko0o00o8c8ooc8g84oowk4' && cd '/artifacts/swko0o00o8c8ooc8g84oowk4' && if [ -f .gitmodules ]; then git submodule sync && GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git submodule update --init --recursive --depth=1; fi && cd '/artifacts/swko0o00o8c8ooc8g84oowk4' && GIT_SSH_COMMAND="ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" git lfs pull'
2025-Dec-27 15:06:53.896563 Cloning into '/artifacts/swko0o00o8c8ooc8g84oowk4'...
2025-Dec-27 15:06:55.619848 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'cd /artifacts/swko0o00o8c8ooc8g84oowk4 && git log -1 6e02b6970c79ca5304973aba9a5412ea8835eeb5 --pretty=%B'
2025-Dec-27 15:06:55.619848 fix: Forcer consistance de la casse et corriger commande build Docker
2025-Dec-27 15:06:55.787930 Image not found (p4s0ckckss0kscks0084ow4s:6e02b6970c79ca5304973aba9a5412ea8835eeb5). Building new image.
2025-Dec-27 15:06:56.609271 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'cat /artifacts/swko0o00o8c8ooc8g84oowk4/Dockerfile'
2025-Dec-27 15:06:56.609271 # Dockerfile pour Espace Paie - Optimisé pour Coolify
2025-Dec-27 15:06:56.609271 FROM node:18-alpine AS base
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Installer les dépendances système nécessaires
2025-Dec-27 15:06:56.609271 RUN apk add --no-cache libc6-compat
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # === ÉTAPE 1 : Dependencies ===
2025-Dec-27 15:06:56.609271 FROM base AS deps
2025-Dec-27 15:06:56.609271 WORKDIR /app
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Copier les fichiers de dépendances
2025-Dec-27 15:06:56.609271 COPY package.json package-lock.json* ./
2025-Dec-27 15:06:56.609271 RUN npm ci
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # === ÉTAPE 2 : Build ===
2025-Dec-27 15:06:56.609271 FROM base AS builder
2025-Dec-27 15:06:56.609271 WORKDIR /app
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Copier les dépendances depuis l'étape précédente
2025-Dec-27 15:06:56.609271 COPY --from=deps /app/node_modules ./node_modules
2025-Dec-27 15:06:56.609271 COPY . .
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Variables d'environnement pour le build
2025-Dec-27 15:06:56.609271 ENV NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:56.609271 ENV NODE_ENV=production
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Debug: Vérifier que components existe
2025-Dec-27 15:06:56.609271 RUN ls -la components/ && ls -la components/ui/ || echo "components manquant!"
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Nettoyer complètement le cache pour éviter les problèmes de casse sur Linux
2025-Dec-27 15:06:56.609271 RUN rm -rf .next node_modules/.cache
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Build Next.js en mode standalone
2025-Dec-27 15:06:56.609271 RUN npm run build
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # === ÉTAPE 3 : Production ===
2025-Dec-27 15:06:56.609271 FROM base AS runner
2025-Dec-27 15:06:56.609271 WORKDIR /app
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 ENV NODE_ENV=production
2025-Dec-27 15:06:56.609271 ENV NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Créer un utilisateur non-root
2025-Dec-27 15:06:56.609271 RUN addgroup --system --gid 1001 nodejs
2025-Dec-27 15:06:56.609271 RUN adduser --system --uid 1001 nextjs
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Copier les fichiers nécessaires
2025-Dec-27 15:06:56.609271 COPY --from=builder /app/public ./public
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Copier le build standalone
2025-Dec-27 15:06:56.609271 COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
2025-Dec-27 15:06:56.609271 COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Utiliser l'utilisateur non-root
2025-Dec-27 15:06:56.609271 USER nextjs
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Exposer le port
2025-Dec-27 15:06:56.609271 EXPOSE 3000
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 ENV PORT=3000
2025-Dec-27 15:06:56.609271 ENV HOSTNAME="0.0.0.0"
2025-Dec-27 15:06:56.609271
2025-Dec-27 15:06:56.609271 # Démarrer l'application
2025-Dec-27 15:06:56.609271 CMD ["node", "server.js"]
2025-Dec-27 15:06:57.046046 Creating build-time .env file in /artifacts (outside Docker context).
2025-Dec-27 15:06:57.488591 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'cat /artifacts/build-time.env'
2025-Dec-27 15:06:57.488591 COOLIFY_URL='http://p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io'
2025-Dec-27 15:06:57.488591 COOLIFY_FQDN='p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io'
2025-Dec-27 15:06:57.488591 COOLIFY_BRANCH='main'
2025-Dec-27 15:06:57.488591 COOLIFY_RESOURCE_UUID='p4s0ckckss0kscks0084ow4s'
2025-Dec-27 15:06:57.488591 AUTH_BYPASS="1"
2025-Dec-27 15:06:57.488591 AWS_ACCESS_KEY_ID="<REDACTED>"
2025-Dec-27 15:06:57.488591 AWS_REGION="eu-west-3"
2025-Dec-27 15:06:57.488591 AWS_S3_BUCKET="odentas-docs"
2025-Dec-27 15:06:57.488591 AWS_SECRET_ACCESS_KEY=<REDACTED>
2025-Dec-27 15:06:57.488591 AWS_SES_FROM="Odentas <<REDACTED>>"
2025-Dec-27 15:06:57.488591 CLOUDINARY_API_KEY="265234555873541"
2025-Dec-27 15:06:57.488591 CLOUDINARY_API_SECRET=<REDACTED>
2025-Dec-27 15:06:57.488591 CLOUDINARY_CLOUD_NAME="duecox5va"
2025-Dec-27 15:06:57.488591 DOCUSEAL_API_BASE="https://api.docuseal.eu"
2025-Dec-27 15:06:57.488591 DOCUSEAL_TOKEN="s1fDVPiie3HYq2dEYvBX6od5k9p7JMB7VtvihoS8X77"
2025-Dec-27 15:06:57.488591 GOCARDLESS_ACCESS_TOKEN="live_iMcKO4hM4Bezk25GN-owkb52jAI47NlxdjoL4dB_"
2025-Dec-27 15:06:57.488591 GOCARDLESS_ENVIRONMENT="live"
2025-Dec-27 15:06:57.488591 LAMBDA_API_KEY=<REDACTED>
2025-Dec-27 15:06:57.488591 LAMBDA_PDF_TO_IMAGES_URL="https://poy3opxqfkc7x335apqy56ytlu0facdx.lambda-url.eu-west-3.on.aws/"
2025-Dec-27 15:06:57.488591 NEXT_PUBLIC_API_BASE="https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default"
2025-Dec-27 15:06:57.488591 NEXT_PUBLIC_AUTH_BYPASS="1"
2025-Dec-27 15:06:57.488591 NEXT_PUBLIC_FORCE_ANIMATIONS="1"
2025-Dec-27 15:06:57.488591 NEXT_PUBLIC_SUPABASE_ANON_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1"
2025-Dec-27 15:06:57.488591 NEXT_PUBLIC_SUPABASE_URL="https://fusqtpjififcmgbhmosq.supabase.co"
2025-Dec-27 15:06:57.488591 NEXT_TELEMETRY_DISABLED="1"
2025-Dec-27 15:06:57.488591 NODE_ENV="production"
2025-Dec-27 15:06:57.488591 ODENTAS_SIGN_BUCKET="odentas-sign"
2025-Dec-27 15:06:57.488591 PDFMONKEY_API_KEY=<REDACTED>
2025-Dec-27 15:06:57.488591 PDFMONKEY_URL="https://api.pdfmonkey.io/api/v1/documents"
2025-Dec-27 15:06:57.488591 S3_BUCKET_NAME="odentas-docs"
2025-Dec-27 15:06:57.488591 S3_BUCKET_NAME_EMAILS="stockage-logs-emails"
2025-Dec-27 15:06:57.488591 SUPABASE_SERVICE_ROLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1c3F0"
2025-Dec-27 15:06:57.488591 SUPABASE_URL="https://fusqtpjififcmgbhmosq.supabase.co"
2025-Dec-27 15:06:57.488591 UPSTREAM_API_BASE="https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default"
2025-Dec-27 15:06:57.634459 ----------------------------------------
2025-Dec-27 15:06:57.650642 ⚠️ Build-time environment variable warning: NODE_ENV=production
2025-Dec-27 15:06:57.666543 Affects: Node.js/npm/yarn/bun/pnpm
2025-Dec-27 15:06:57.676581 Issue: Skips devDependencies installation which are often required for building (webpack, typescript, etc.)
2025-Dec-27 15:06:57.691746 Recommendation: Uncheck "Available at Buildtime" or use "development" during build
2025-Dec-27 15:06:57.705575
2025-Dec-27 15:06:57.718339 💡 Tips to resolve build issues:
2025-Dec-27 15:06:57.734741 1. Set these variables as "Runtime only" in the environment variables settings
2025-Dec-27 15:06:57.754545 2. Use different values for build-time (e.g., NODE_ENV=development for build)
2025-Dec-27 15:06:57.767424 3. Consider using multi-stage Docker builds to separate build and runtime environments
2025-Dec-27 15:06:57.997951 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'cat /artifacts/swko0o00o8c8ooc8g84oowk4/Dockerfile'
2025-Dec-27 15:06:57.997951 # Dockerfile pour Espace Paie - Optimisé pour Coolify
2025-Dec-27 15:06:57.997951 FROM node:18-alpine AS base
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Installer les dépendances système nécessaires
2025-Dec-27 15:06:57.997951 RUN apk add --no-cache libc6-compat
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # === ÉTAPE 1 : Dependencies ===
2025-Dec-27 15:06:57.997951 FROM base AS deps
2025-Dec-27 15:06:57.997951 WORKDIR /app
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Copier les fichiers de dépendances
2025-Dec-27 15:06:57.997951 COPY package.json package-lock.json* ./
2025-Dec-27 15:06:57.997951 RUN npm ci
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # === ÉTAPE 2 : Build ===
2025-Dec-27 15:06:57.997951 FROM base AS builder
2025-Dec-27 15:06:57.997951 WORKDIR /app
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Copier les dépendances depuis l'étape précédente
2025-Dec-27 15:06:57.997951 COPY --from=deps /app/node_modules ./node_modules
2025-Dec-27 15:06:57.997951 COPY . .
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Variables d'environnement pour le build
2025-Dec-27 15:06:57.997951 ENV NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:57.997951 ENV NODE_ENV=production
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Debug: Vérifier que components existe
2025-Dec-27 15:06:57.997951 RUN ls -la components/ && ls -la components/ui/ || echo "components manquant!"
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Nettoyer complètement le cache pour éviter les problèmes de casse sur Linux
2025-Dec-27 15:06:57.997951 RUN rm -rf .next node_modules/.cache
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Build Next.js en mode standalone
2025-Dec-27 15:06:57.997951 RUN npm run build
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # === ÉTAPE 3 : Production ===
2025-Dec-27 15:06:57.997951 FROM base AS runner
2025-Dec-27 15:06:57.997951 WORKDIR /app
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 ENV NODE_ENV=production
2025-Dec-27 15:06:57.997951 ENV NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Créer un utilisateur non-root
2025-Dec-27 15:06:57.997951 RUN addgroup --system --gid 1001 nodejs
2025-Dec-27 15:06:57.997951 RUN adduser --system --uid 1001 nextjs
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Copier les fichiers nécessaires
2025-Dec-27 15:06:57.997951 COPY --from=builder /app/public ./public
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Copier le build standalone
2025-Dec-27 15:06:57.997951 COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
2025-Dec-27 15:06:57.997951 COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Utiliser l'utilisateur non-root
2025-Dec-27 15:06:57.997951 USER nextjs
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Exposer le port
2025-Dec-27 15:06:57.997951 EXPOSE 3000
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 ENV PORT=3000
2025-Dec-27 15:06:57.997951 ENV HOSTNAME="0.0.0.0"
2025-Dec-27 15:06:57.997951
2025-Dec-27 15:06:57.997951 # Démarrer l'application
2025-Dec-27 15:06:57.997951 CMD ["node", "server.js"]
2025-Dec-27 15:06:58.163932 Final Dockerfile:
2025-Dec-27 15:06:58.621562 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'cat /artifacts/swko0o00o8c8ooc8g84oowk4/Dockerfile'
2025-Dec-27 15:06:58.621562 # Dockerfile pour Espace Paie - Optimisé pour Coolify
2025-Dec-27 15:06:58.621562 FROM node:18-alpine AS base
2025-Dec-27 15:06:58.621562 ARG AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG AWS_ACCESS_KEY_ID=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_REGION=eu-west-3
2025-Dec-27 15:06:58.621562 ARG AWS_S3_BUCKET=odentas-docs
2025-Dec-27 15:06:58.621562 ARG AWS_SECRET_ACCESS_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_SES_FROM=Odentas <<REDACTED>>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_KEY=265234555873541
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_SECRET=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_CLOUD_NAME=duecox5va
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_API_BASE=https://api.docuseal.eu
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_TOKEN=s1fDVPiie3HYq2dEYvBX6od5k9p7JMB7VtvihoS8X77
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ACCESS_TOKEN=live_iMcKO4hM4Bezk25GN-owkb52jAI47NlxdjoL4dB_
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ENVIRONMENT=live
2025-Dec-27 15:06:58.621562 ARG LAMBDA_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG LAMBDA_PDF_TO_IMAGES_URL=https://poy3opxqfkc7x335apqy56ytlu0facdx.lambda-url.eu-west-3.on.aws/
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_FORCE_ANIMATIONS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:58.621562 ARG NODE_ENV=production
2025-Dec-27 15:06:58.621562 ARG ODENTAS_SIGN_BUCKET=odentas-sign
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_URL=https://api.pdfmonkey.io/api/v1/documents
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME=odentas-docs
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME_EMAILS=stockage-logs-emails
2025-Dec-27 15:06:58.621562 ARG SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1c3F0
2025-Dec-27 15:06:58.621562 ARG SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG UPSTREAM_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG COOLIFY_URL=http://p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_FQDN=p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_BRANCH=main
2025-Dec-27 15:06:58.621562 ARG COOLIFY_RESOURCE_UUID=p4s0ckckss0kscks0084ow4s
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Installer les dépendances système nécessaires
2025-Dec-27 15:06:58.621562 RUN apk add --no-cache libc6-compat
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # === ÉTAPE 1 : Dependencies ===
2025-Dec-27 15:06:58.621562 FROM base AS deps
2025-Dec-27 15:06:58.621562 ARG AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG AWS_ACCESS_KEY_ID=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_REGION=eu-west-3
2025-Dec-27 15:06:58.621562 ARG AWS_S3_BUCKET=odentas-docs
2025-Dec-27 15:06:58.621562 ARG AWS_SECRET_ACCESS_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_SES_FROM=Odentas <<REDACTED>>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_KEY=265234555873541
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_SECRET=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_CLOUD_NAME=duecox5va
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_API_BASE=https://api.docuseal.eu
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_TOKEN=s1fDVPiie3HYq2dEYvBX6od5k9p7JMB7VtvihoS8X77
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ACCESS_TOKEN=live_iMcKO4hM4Bezk25GN-owkb52jAI47NlxdjoL4dB_
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ENVIRONMENT=live
2025-Dec-27 15:06:58.621562 ARG LAMBDA_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG LAMBDA_PDF_TO_IMAGES_URL=https://poy3opxqfkc7x335apqy56ytlu0facdx.lambda-url.eu-west-3.on.aws/
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_FORCE_ANIMATIONS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:58.621562 ARG NODE_ENV=production
2025-Dec-27 15:06:58.621562 ARG ODENTAS_SIGN_BUCKET=odentas-sign
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_URL=https://api.pdfmonkey.io/api/v1/documents
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME=odentas-docs
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME_EMAILS=stockage-logs-emails
2025-Dec-27 15:06:58.621562 ARG SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1c3F0
2025-Dec-27 15:06:58.621562 ARG SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG UPSTREAM_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG COOLIFY_URL=http://p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_FQDN=p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_BRANCH=main
2025-Dec-27 15:06:58.621562 ARG COOLIFY_RESOURCE_UUID=p4s0ckckss0kscks0084ow4s
2025-Dec-27 15:06:58.621562 WORKDIR /app
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Copier les fichiers de dépendances
2025-Dec-27 15:06:58.621562 COPY package.json package-lock.json* ./
2025-Dec-27 15:06:58.621562 RUN npm ci
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # === ÉTAPE 2 : Build ===
2025-Dec-27 15:06:58.621562 FROM base AS builder
2025-Dec-27 15:06:58.621562 ARG AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG AWS_ACCESS_KEY_ID=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_REGION=eu-west-3
2025-Dec-27 15:06:58.621562 ARG AWS_S3_BUCKET=odentas-docs
2025-Dec-27 15:06:58.621562 ARG AWS_SECRET_ACCESS_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_SES_FROM=Odentas <<REDACTED>>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_KEY=265234555873541
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_SECRET=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_CLOUD_NAME=duecox5va
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_API_BASE=https://api.docuseal.eu
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_TOKEN=s1fDVPiie3HYq2dEYvBX6od5k9p7JMB7VtvihoS8X77
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ACCESS_TOKEN=live_iMcKO4hM4Bezk25GN-owkb52jAI47NlxdjoL4dB_
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ENVIRONMENT=live
2025-Dec-27 15:06:58.621562 ARG LAMBDA_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG LAMBDA_PDF_TO_IMAGES_URL=https://poy3opxqfkc7x335apqy56ytlu0facdx.lambda-url.eu-west-3.on.aws/
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_FORCE_ANIMATIONS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:58.621562 ARG NODE_ENV=production
2025-Dec-27 15:06:58.621562 ARG ODENTAS_SIGN_BUCKET=odentas-sign
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_URL=https://api.pdfmonkey.io/api/v1/documents
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME=odentas-docs
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME_EMAILS=stockage-logs-emails
2025-Dec-27 15:06:58.621562 ARG SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1c3F0
2025-Dec-27 15:06:58.621562 ARG SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG UPSTREAM_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG COOLIFY_URL=http://p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_FQDN=p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_BRANCH=main
2025-Dec-27 15:06:58.621562 ARG COOLIFY_RESOURCE_UUID=p4s0ckckss0kscks0084ow4s
2025-Dec-27 15:06:58.621562 WORKDIR /app
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Copier les dépendances depuis l'étape précédente
2025-Dec-27 15:06:58.621562 COPY --from=deps /app/node_modules ./node_modules
2025-Dec-27 15:06:58.621562 COPY . .
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Variables d'environnement pour le build
2025-Dec-27 15:06:58.621562 ENV NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:58.621562 ENV NODE_ENV=production
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Debug: Vérifier que components existe
2025-Dec-27 15:06:58.621562 RUN ls -la components/ && ls -la components/ui/ || echo "components manquant!"
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Nettoyer complètement le cache pour éviter les problèmes de casse sur Linux
2025-Dec-27 15:06:58.621562 RUN rm -rf .next node_modules/.cache
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Build Next.js en mode standalone
2025-Dec-27 15:06:58.621562 RUN npm run build
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # === ÉTAPE 3 : Production ===
2025-Dec-27 15:06:58.621562 FROM base AS runner
2025-Dec-27 15:06:58.621562 ARG AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG AWS_ACCESS_KEY_ID=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_REGION=eu-west-3
2025-Dec-27 15:06:58.621562 ARG AWS_S3_BUCKET=odentas-docs
2025-Dec-27 15:06:58.621562 ARG AWS_SECRET_ACCESS_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG AWS_SES_FROM=Odentas <<REDACTED>>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_KEY=265234555873541
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_API_SECRET=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG CLOUDINARY_CLOUD_NAME=duecox5va
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_API_BASE=https://api.docuseal.eu
2025-Dec-27 15:06:58.621562 ARG DOCUSEAL_TOKEN=s1fDVPiie3HYq2dEYvBX6od5k9p7JMB7VtvihoS8X77
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ACCESS_TOKEN=live_iMcKO4hM4Bezk25GN-owkb52jAI47NlxdjoL4dB_
2025-Dec-27 15:06:58.621562 ARG GOCARDLESS_ENVIRONMENT=live
2025-Dec-27 15:06:58.621562 ARG LAMBDA_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG LAMBDA_PDF_TO_IMAGES_URL=https://poy3opxqfkc7x335apqy56ytlu0facdx.lambda-url.eu-west-3.on.aws/
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_AUTH_BYPASS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_FORCE_ANIMATIONS=1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1
2025-Dec-27 15:06:58.621562 ARG NEXT_PUBLIC_SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:58.621562 ARG NODE_ENV=production
2025-Dec-27 15:06:58.621562 ARG ODENTAS_SIGN_BUCKET=odentas-sign
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_API_KEY=<REDACTED>
2025-Dec-27 15:06:58.621562 ARG PDFMONKEY_URL=https://api.pdfmonkey.io/api/v1/documents
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME=odentas-docs
2025-Dec-27 15:06:58.621562 ARG S3_BUCKET_NAME_EMAILS=stockage-logs-emails
2025-Dec-27 15:06:58.621562 ARG SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZ1c3F0
2025-Dec-27 15:06:58.621562 ARG SUPABASE_URL=https://fusqtpjififcmgbhmosq.supabase.co
2025-Dec-27 15:06:58.621562 ARG UPSTREAM_API_BASE=https://0rryyjj6vh.execute-api.eu-west-3.amazonaws.com/default
2025-Dec-27 15:06:58.621562 ARG COOLIFY_URL=http://p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_FQDN=p4s0ckckss0kscks0084ow4s.144.91.113.70.sslip.io
2025-Dec-27 15:06:58.621562 ARG COOLIFY_BRANCH=main
2025-Dec-27 15:06:58.621562 ARG COOLIFY_RESOURCE_UUID=p4s0ckckss0kscks0084ow4s
2025-Dec-27 15:06:58.621562 WORKDIR /app
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 ENV NODE_ENV=production
2025-Dec-27 15:06:58.621562 ENV NEXT_TELEMETRY_DISABLED=1
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Créer un utilisateur non-root
2025-Dec-27 15:06:58.621562 RUN addgroup --system --gid 1001 nodejs
2025-Dec-27 15:06:58.621562 RUN adduser --system --uid 1001 nextjs
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Copier les fichiers nécessaires
2025-Dec-27 15:06:58.621562 COPY --from=builder /app/public ./public
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Copier le build standalone
2025-Dec-27 15:06:58.621562 COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
2025-Dec-27 15:06:58.621562 COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Utiliser l'utilisateur non-root
2025-Dec-27 15:06:58.621562 USER nextjs
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Exposer le port
2025-Dec-27 15:06:58.621562 EXPOSE 3000
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 ENV PORT=3000
2025-Dec-27 15:06:58.621562 ENV HOSTNAME="0.0.0.0"
2025-Dec-27 15:06:58.621562
2025-Dec-27 15:06:58.621562 # Démarrer l'application
2025-Dec-27 15:06:58.621562 CMD ["node", "server.js"]
2025-Dec-27 15:06:58.631344 ----------------------------------------
2025-Dec-27 15:06:58.649016 Building docker image started.
2025-Dec-27 15:06:58.660300 To check the current progress, click on Show Debug Logs.
2025-Dec-27 15:06:59.068553 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'cat /artifacts/build.sh'
2025-Dec-27 15:06:59.068553 cd /artifacts/swko0o00o8c8ooc8g84oowk4 && set -a && source /artifacts/build-time.env && set +a && docker build --add-host coolify:10.0.1.5 --add-host coolify-db:10.0.1.2 --add-host coolify-realtime:10.0.1.3 --add-host coolify-redis:10.0.1.4 --add-host forgejo:10.0.1.7 --network host -f /artifacts/swko0o00o8c8ooc8g84oowk4/Dockerfile --build-arg COOLIFY_URL --build-arg COOLIFY_FQDN --build-arg COOLIFY_BRANCH --build-arg COOLIFY_RESOURCE_UUID --build-arg AUTH_BYPASS --build-arg AWS_ACCESS_KEY_ID --build-arg AWS_REGION --build-arg AWS_S3_BUCKET --build-arg AWS_SECRET_ACCESS_KEY --build-arg AWS_SES_FROM --build-arg CLOUDINARY_API_KEY --build-arg CLOUDINARY_API_SECRET --build-arg CLOUDINARY_CLOUD_NAME --build-arg DOCUSEAL_API_BASE --build-arg DOCUSEAL_TOKEN --build-arg GOCARDLESS_ACCESS_TOKEN --build-arg GOCARDLESS_ENVIRONMENT --build-arg LAMBDA_API_KEY --build-arg LAMBDA_PDF_TO_IMAGES_URL --build-arg NEXT_PUBLIC_API_BASE --build-arg NEXT_PUBLIC_AUTH_BYPASS --build-arg NEXT_PUBLIC_FORCE_ANIMATIONS --build-arg NEXT_PUBLIC_SUPABASE_ANON_KEY --build-arg NEXT_PUBLIC_SUPABASE_URL --build-arg NEXT_TELEMETRY_DISABLED --build-arg NODE_ENV --build-arg ODENTAS_SIGN_BUCKET --build-arg PDFMONKEY_API_KEY --build-arg PDFMONKEY_URL --build-arg S3_BUCKET_NAME --build-arg S3_BUCKET_NAME_EMAILS --build-arg SUPABASE_SERVICE_ROLE_KEY --build-arg SUPABASE_URL --build-arg UPSTREAM_API_BASE --build-arg COOLIFY_BUILD_SECRETS_HASH=13c2bf68ac3cbbc82dd8baef3b84d865687d44098aadf1f6a345429180ea3cc3 --build-arg 'COOLIFY_URL' --build-arg 'COOLIFY_FQDN' --build-arg 'COOLIFY_BRANCH' --build-arg 'COOLIFY_RESOURCE_UUID' --progress plain -t p4s0ckckss0kscks0084ow4s:6e02b6970c79ca5304973aba9a5412ea8835eeb5 /artifacts/swko0o00o8c8ooc8g84oowk4
2025-Dec-27 15:06:59.687798 [CMD]: docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'bash /artifacts/build.sh'
2025-Dec-27 15:06:59.687798 #0 building with "default" instance using docker driver
2025-Dec-27 15:06:59.687798
2025-Dec-27 15:06:59.687798 #1 [internal] load build definition from Dockerfile
2025-Dec-27 15:06:59.687798 #1 transferring dockerfile: 8.87kB done
2025-Dec-27 15:06:59.687798 #1 DONE 0.0s
2025-Dec-27 15:06:59.687798
2025-Dec-27 15:06:59.687798 #2 [internal] load metadata for docker.io/library/node:18-alpine
2025-Dec-27 15:07:00.213982 #2 DONE 0.7s
2025-Dec-27 15:07:00.317613 #3 [internal] load .dockerignore
2025-Dec-27 15:07:00.317613 #3 transferring context: 782B done
2025-Dec-27 15:07:00.317613 #3 DONE 0.0s
2025-Dec-27 15:07:00.317613
2025-Dec-27 15:07:00.317613 #4 [base 1/2] FROM docker.io/library/node:18-alpine@sha256:8d6421d663b4c28fd3ebc498332f249011d118945588d0a35cb9bc4b8ca09d9e
2025-Dec-27 15:07:00.317613 #4 DONE 0.0s
2025-Dec-27 15:07:00.317613
2025-Dec-27 15:07:00.317613 #5 [base 2/2] RUN apk add --no-cache libc6-compat
2025-Dec-27 15:07:00.317613 #5 CACHED
2025-Dec-27 15:07:00.317613
2025-Dec-27 15:07:00.317613 #6 [deps 1/3] WORKDIR /app
2025-Dec-27 15:07:00.317613 #6 CACHED
2025-Dec-27 15:07:00.317613
2025-Dec-27 15:07:00.317613 #7 [runner 2/6] RUN addgroup --system --gid 1001 nodejs
2025-Dec-27 15:07:00.317613 #7 CACHED
2025-Dec-27 15:07:00.317613
2025-Dec-27 15:07:00.317613 #8 [runner 3/6] RUN adduser --system --uid 1001 nextjs
2025-Dec-27 15:07:00.317613 #8 CACHED
2025-Dec-27 15:07:00.317613
2025-Dec-27 15:07:00.317613 #9 [internal] load build context
2025-Dec-27 15:07:00.570552 #9 transferring context: 10.72MB 0.3s done
2025-Dec-27 15:07:00.778010 #9 DONE 0.3s
2025-Dec-27 15:07:00.778010
2025-Dec-27 15:07:00.778010 #10 [deps 2/3] COPY package.json package-lock.json* ./
2025-Dec-27 15:07:00.778010 #10 CACHED
2025-Dec-27 15:07:00.778010
2025-Dec-27 15:07:00.778010 #11 [deps 3/3] RUN npm ci
2025-Dec-27 15:07:00.778010 #11 CACHED
2025-Dec-27 15:07:00.778010
2025-Dec-27 15:07:00.778010 #12 [builder 2/6] COPY --from=deps /app/node_modules ./node_modules
2025-Dec-27 15:07:00.778010 #12 CACHED
2025-Dec-27 15:07:00.778010
2025-Dec-27 15:07:00.778010 #13 [builder 3/6] COPY . .
2025-Dec-27 15:07:00.886385 #13 DONE 0.3s
2025-Dec-27 15:07:00.992926 #14 [builder 4/6] RUN ls -la components/ && ls -la components/ui/ || echo "components manquant!"
2025-Dec-27 15:07:00.992926 #14 0.088 total 392
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 9 root root 4096 Dec 27 15:06 .
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 1 root root 4096 Dec 27 15:07 ..
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 1316 Dec 27 15:06 AccessDeniedCard.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 11011 Dec 27 15:06 Breadcrumb.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 9930 Dec 27 15:06 BugReporter.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 12726 Dec 27 15:06 Calculator.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 335 Dec 27 15:06 CompanyNameSync.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 3721 Dec 27 15:06 ConfirmableForm.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 958 Dec 27 15:06 ConsentManager.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 11935 Dec 27 15:06 DatePickerCalendar.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 21415 Dec 27 15:06 DatesQuantityModal.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 1491 Dec 27 15:06 DemoBanner.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 5969 Dec 27 15:06 DocumentPreviewModal.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 3649 Dec 27 15:06 DocumentViewModal.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 29758 Dec 27 15:06 GlobalSearchOverlay.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 14699 Dec 27 15:06 Header.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 4502 Dec 27 15:06 InviteForm.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 4090 Dec 27 15:06 LogoutButton.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 7473 Dec 27 15:06 MaintenanceButton.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 6088 Dec 27 15:06 MessageCard.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 3381 Dec 27 15:06 MobileSidebarOverlay.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 8081 Dec 27 15:06 NotesSection.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 3534 Dec 27 15:06 OrganizationSwitcher.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 760 Dec 27 15:06 PageTitle.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 5996 Dec 27 15:06 PopupAnalyticsConsent.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 4613 Dec 27 15:06 PopupInfoSuivi.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 1365 Dec 27 15:06 PostHogIdentifier.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 696 Dec 27 15:06 PostHogPageView.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 1846 Dec 27 15:06 PostHogProvider.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 1885 Dec 27 15:06 ProgressBar.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 6343 Dec 27 15:06 PromoBanner.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 648 Dec 27 15:06 Providers.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 5235 Dec 27 15:06 RichTextEditor.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 4491 Dec 27 15:06 SaveConfirmationModal.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 3063 Dec 27 15:06 SearchableInput.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 35941 Dec 27 15:06 Sidebar.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 946 Dec 27 15:06 SidebarMenu.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 1561 Dec 27 15:06 StaffOrgBadge.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 18342 Dec 27 15:06 StatusEditModal.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 7182 Dec 27 15:06 TicketConversation.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 7304 Dec 27 15:06 TicketTimeline.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 461 Dec 27 15:06 UserInitializer.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 auth
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 constants
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 contrats
2025-Dec-27 15:07:00.992926 #14 0.088 -rw-r--r-- 1 root root 3855 Dec 27 15:06 debug-salarie-api.tsx
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 simulateur
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 8 root root 4096 Dec 27 15:06 staff
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 surveys
2025-Dec-27 15:07:00.992926 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 ui
2025-Dec-27 15:07:00.992926 #14 0.090 total 68
2025-Dec-27 15:07:00.992926 #14 0.090 drwxr-xr-x 2 root root 4096 Dec 27 15:06 .
2025-Dec-27 15:07:00.992926 #14 0.090 drwxr-xr-x 9 root root 4096 Dec 27 15:06 ..
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 2297 Dec 27 15:06 Sidebar.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 936 Dec 27 15:06 badge.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 1924 Dec 27 15:06 button.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 909 Dec 27 15:06 card.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 2342 Dec 27 15:06 confirmation-modal.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 3872 Dec 27 15:06 dialog.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 453 Dec 27 15:06 input.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 567 Dec 27 15:06 label.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 1644 Dec 27 15:06 loading-modal.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 3137 Dec 27 15:06 select.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 718 Dec 27 15:06 separator.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 3539 Dec 27 15:06 sheet.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 1826 Dec 27 15:06 tabs.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 494 Dec 27 15:06 textarea.tsx
2025-Dec-27 15:07:00.992926 #14 0.090 -rw-r--r-- 1 root root 3869 Dec 27 15:06 tooltip.tsx
2025-Dec-27 15:07:00.992926 #14 DONE 0.1s
2025-Dec-27 15:07:01.093037 #15 [builder 5/6] RUN rm -rf .next node_modules/.cache
2025-Dec-27 15:07:01.093037 #15 DONE 0.1s
2025-Dec-27 15:07:01.246054 #16 [builder 6/6] RUN npm run build
2025-Dec-27 15:07:02.153267 #16 1.055
2025-Dec-27 15:07:02.153267 #16 1.055 > odentas-espace-paie@0.1.0 build
2025-Dec-27 15:07:02.153267 #16 1.055 > next build
2025-Dec-27 15:07:02.153267 #16 1.055
2025-Dec-27 15:07:03.583617 #16 2.485 ▲ Next.js 14.2.33
2025-Dec-27 15:07:03.683637 #16 2.487 - Experiments (use with caution):
2025-Dec-27 15:07:03.683637 #16 2.487 · missingSuspenseWithCSRBailout
2025-Dec-27 15:07:03.683637 #16 2.487
2025-Dec-27 15:07:03.683637 #16 2.589 Creating an optimized production build ...
2025-Dec-27 15:08:13.977751 #16 72.88 <w> [webpack.cache.PackFileCacheStrategy] Serializing big strings (118kiB) impacts deserialization performance (consider using Buffer instead and decode when needed)
2025-Dec-27 15:08:14.151904 #16 73.06 Failed to compile.
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.151904 #16 73.06 Module not found: Can't resolve '@/components/NotesSection'
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.151904 #16 73.06 Module not found: Can't resolve '@/components/ui/button'
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.151904 #16 73.06 Module not found: Can't resolve '@/components/ui/confirmation-modal'
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.151904 #16 73.06 Module not found: Can't resolve '@/components/ui/loading-modal'
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.151904 #16 73.06 Module not found: Can't resolve '@/components/contrats/DocumentsCard'
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.151904 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.151904 #16 73.06
2025-Dec-27 15:08:14.306101 #16 73.06
2025-Dec-27 15:08:14.306101 #16 73.06 > Build failed because of webpack errors
2025-Dec-27 15:08:14.363192 #16 73.27 npm notice
2025-Dec-27 15:08:14.363192 #16 73.27 npm notice New major version of npm available! 10.8.2 -> 11.7.0
2025-Dec-27 15:08:14.363192 #16 73.27 npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.7.0
2025-Dec-27 15:08:14.363192 #16 73.27 npm notice To update run: npm install -g npm@11.7.0
2025-Dec-27 15:08:14.363192 #16 73.27 npm notice
2025-Dec-27 15:08:14.562512 #16 ERROR: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
2025-Dec-27 15:08:14.599937 ------
2025-Dec-27 15:08:14.599937 > [builder 6/6] RUN npm run build:
2025-Dec-27 15:08:14.599937 73.06
2025-Dec-27 15:08:14.599937 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.599937 73.06
2025-Dec-27 15:08:14.599937 73.06
2025-Dec-27 15:08:14.599937 73.06 > Build failed because of webpack errors
2025-Dec-27 15:08:14.599937 73.27 npm notice
2025-Dec-27 15:08:14.599937 73.27 npm notice New major version of npm available! 10.8.2 -> 11.7.0
2025-Dec-27 15:08:14.599937 73.27 npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.7.0
2025-Dec-27 15:08:14.599937 73.27 npm notice To update run: npm install -g npm@11.7.0
2025-Dec-27 15:08:14.599937 73.27 npm notice
2025-Dec-27 15:08:14.599937 ------
2025-Dec-27 15:08:14.605392 Dockerfile:136
2025-Dec-27 15:08:14.605392 --------------------
2025-Dec-27 15:08:14.605392 134 |
2025-Dec-27 15:08:14.605392 135 | # Build Next.js en mode standalone
2025-Dec-27 15:08:14.605392 136 | >>> RUN npm run build
2025-Dec-27 15:08:14.605392 137 |
2025-Dec-27 15:08:14.605392 138 | # === ÉTAPE 3 : Production ===
2025-Dec-27 15:08:14.605392 --------------------
2025-Dec-27 15:08:14.605392 ERROR: failed to build: failed to solve: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
2025-Dec-27 15:08:14.612076 exit status 1
2025-Dec-27 15:08:14.715285 ========================================
2025-Dec-27 15:08:14.733450 Deployment failed: Command execution failed (exit code 1): docker exec swko0o00o8c8ooc8g84oowk4 bash -c 'bash /artifacts/build.sh'
2025-Dec-27 15:08:14.733450 Error: #0 building with "default" instance using docker driver
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #1 [internal] load build definition from Dockerfile
2025-Dec-27 15:08:14.733450 #1 transferring dockerfile: 8.87kB done
2025-Dec-27 15:08:14.733450 #1 DONE 0.0s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #2 [internal] load metadata for docker.io/library/node:18-alpine
2025-Dec-27 15:08:14.733450 #2 DONE 0.7s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #3 [internal] load .dockerignore
2025-Dec-27 15:08:14.733450 #3 transferring context: 782B done
2025-Dec-27 15:08:14.733450 #3 DONE 0.0s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #4 [base 1/2] FROM docker.io/library/node:18-alpine@sha256:8d6421d663b4c28fd3ebc498332f249011d118945588d0a35cb9bc4b8ca09d9e
2025-Dec-27 15:08:14.733450 #4 DONE 0.0s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #5 [base 2/2] RUN apk add --no-cache libc6-compat
2025-Dec-27 15:08:14.733450 #5 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #6 [deps 1/3] WORKDIR /app
2025-Dec-27 15:08:14.733450 #6 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #7 [runner 2/6] RUN addgroup --system --gid 1001 nodejs
2025-Dec-27 15:08:14.733450 #7 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #8 [runner 3/6] RUN adduser --system --uid 1001 nextjs
2025-Dec-27 15:08:14.733450 #8 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #9 [internal] load build context
2025-Dec-27 15:08:14.733450 #9 transferring context: 10.72MB 0.3s done
2025-Dec-27 15:08:14.733450 #9 DONE 0.3s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #10 [deps 2/3] COPY package.json package-lock.json* ./
2025-Dec-27 15:08:14.733450 #10 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #11 [deps 3/3] RUN npm ci
2025-Dec-27 15:08:14.733450 #11 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #12 [builder 2/6] COPY --from=deps /app/node_modules ./node_modules
2025-Dec-27 15:08:14.733450 #12 CACHED
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #13 [builder 3/6] COPY . .
2025-Dec-27 15:08:14.733450 #13 DONE 0.3s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #14 [builder 4/6] RUN ls -la components/ && ls -la components/ui/ || echo "components manquant!"
2025-Dec-27 15:08:14.733450 #14 0.088 total 392
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 9 root root 4096 Dec 27 15:06 .
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 1 root root 4096 Dec 27 15:07 ..
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 1316 Dec 27 15:06 AccessDeniedCard.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 11011 Dec 27 15:06 Breadcrumb.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 9930 Dec 27 15:06 BugReporter.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 12726 Dec 27 15:06 Calculator.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 335 Dec 27 15:06 CompanyNameSync.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 3721 Dec 27 15:06 ConfirmableForm.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 958 Dec 27 15:06 ConsentManager.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 11935 Dec 27 15:06 DatePickerCalendar.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 21415 Dec 27 15:06 DatesQuantityModal.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 1491 Dec 27 15:06 DemoBanner.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 5969 Dec 27 15:06 DocumentPreviewModal.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 3649 Dec 27 15:06 DocumentViewModal.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 29758 Dec 27 15:06 GlobalSearchOverlay.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 14699 Dec 27 15:06 Header.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 4502 Dec 27 15:06 InviteForm.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 4090 Dec 27 15:06 LogoutButton.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 7473 Dec 27 15:06 MaintenanceButton.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 6088 Dec 27 15:06 MessageCard.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 3381 Dec 27 15:06 MobileSidebarOverlay.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 8081 Dec 27 15:06 NotesSection.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 3534 Dec 27 15:06 OrganizationSwitcher.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 760 Dec 27 15:06 PageTitle.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 5996 Dec 27 15:06 PopupAnalyticsConsent.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 4613 Dec 27 15:06 PopupInfoSuivi.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 1365 Dec 27 15:06 PostHogIdentifier.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 696 Dec 27 15:06 PostHogPageView.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 1846 Dec 27 15:06 PostHogProvider.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 1885 Dec 27 15:06 ProgressBar.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 6343 Dec 27 15:06 PromoBanner.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 648 Dec 27 15:06 Providers.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 5235 Dec 27 15:06 RichTextEditor.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 4491 Dec 27 15:06 SaveConfirmationModal.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 3063 Dec 27 15:06 SearchableInput.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 35941 Dec 27 15:06 Sidebar.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 946 Dec 27 15:06 SidebarMenu.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 1561 Dec 27 15:06 StaffOrgBadge.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 18342 Dec 27 15:06 StatusEditModal.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 7182 Dec 27 15:06 TicketConversation.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 7304 Dec 27 15:06 TicketTimeline.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 461 Dec 27 15:06 UserInitializer.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 auth
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 constants
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 contrats
2025-Dec-27 15:08:14.733450 #14 0.088 -rw-r--r-- 1 root root 3855 Dec 27 15:06 debug-salarie-api.tsx
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 simulateur
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 8 root root 4096 Dec 27 15:06 staff
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 surveys
2025-Dec-27 15:08:14.733450 #14 0.088 drwxr-xr-x 2 root root 4096 Dec 27 15:06 ui
2025-Dec-27 15:08:14.733450 #14 0.090 total 68
2025-Dec-27 15:08:14.733450 #14 0.090 drwxr-xr-x 2 root root 4096 Dec 27 15:06 .
2025-Dec-27 15:08:14.733450 #14 0.090 drwxr-xr-x 9 root root 4096 Dec 27 15:06 ..
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 2297 Dec 27 15:06 Sidebar.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 936 Dec 27 15:06 badge.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 1924 Dec 27 15:06 button.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 909 Dec 27 15:06 card.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 2342 Dec 27 15:06 confirmation-modal.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 3872 Dec 27 15:06 dialog.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 453 Dec 27 15:06 input.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 567 Dec 27 15:06 label.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 1644 Dec 27 15:06 loading-modal.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 3137 Dec 27 15:06 select.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 718 Dec 27 15:06 separator.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 3539 Dec 27 15:06 sheet.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 1826 Dec 27 15:06 tabs.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 494 Dec 27 15:06 textarea.tsx
2025-Dec-27 15:08:14.733450 #14 0.090 -rw-r--r-- 1 root root 3869 Dec 27 15:06 tooltip.tsx
2025-Dec-27 15:08:14.733450 #14 DONE 0.1s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #15 [builder 5/6] RUN rm -rf .next node_modules/.cache
2025-Dec-27 15:08:14.733450 #15 DONE 0.1s
2025-Dec-27 15:08:14.733450
2025-Dec-27 15:08:14.733450 #16 [builder 6/6] RUN npm run build
2025-Dec-27 15:08:14.733450 #16 1.055
2025-Dec-27 15:08:14.733450 #16 1.055 > odentas-espace-paie@0.1.0 build
2025-Dec-27 15:08:14.733450 #16 1.055 > next build
2025-Dec-27 15:08:14.733450 #16 1.055
2025-Dec-27 15:08:14.733450 #16 2.485 ▲ Next.js 14.2.33
2025-Dec-27 15:08:14.733450 #16 2.487 - Experiments (use with caution):
2025-Dec-27 15:08:14.733450 #16 2.487 · missingSuspenseWithCSRBailout
2025-Dec-27 15:08:14.733450 #16 2.487
2025-Dec-27 15:08:14.733450 #16 2.589 Creating an optimized production build ...
2025-Dec-27 15:08:14.733450 #16 72.88 <w> [webpack.cache.PackFileCacheStrategy] Serializing big strings (118kiB) impacts deserialization performance (consider using Buffer instead and decode when needed)
2025-Dec-27 15:08:14.733450 #16 73.06 Failed to compile.
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.733450 #16 73.06 Module not found: Can't resolve '@/components/NotesSection'
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.733450 #16 73.06 Module not found: Can't resolve '@/components/ui/button'
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.733450 #16 73.06 Module not found: Can't resolve '@/components/ui/confirmation-modal'
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.733450 #16 73.06 Module not found: Can't resolve '@/components/ui/loading-modal'
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 ./app/(app)/contrats-multi/[id]/page.tsx
2025-Dec-27 15:08:14.733450 #16 73.06 Module not found: Can't resolve '@/components/contrats/DocumentsCard'
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06
2025-Dec-27 15:08:14.733450 #16 73.06 > Build failed because of webpack errors
2025-Dec-27 15:08:14.733450 #16 73.27 npm notice
2025-Dec-27 15:08:14.733450 #16 73.27 npm notice New major version of npm available! 10.8.2 -> 11.7.0
2025-Dec-27 15:08:14.733450 #16 73.27 npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.7.0
2025-Dec-27 15:08:14.733450 #16 73.27 npm notice To update run: npm install -g npm@11.7.0
2025-Dec-27 15:08:14.733450 #16 73.27 npm notice
2025-Dec-27 15:08:14.733450 #16 ERROR: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
2025-Dec-27 15:08:14.733450 ------
2025-Dec-27 15:08:14.733450 > [builder 6/6] RUN npm run build:
2025-Dec-27 15:08:14.733450 73.06
2025-Dec-27 15:08:14.733450 73.06 https://nextjs.org/docs/messages/module-not-found
2025-Dec-27 15:08:14.733450 73.06
2025-Dec-27 15:08:14.733450 73.06
2025-Dec-27 15:08:14.733450 73.06 > Build failed because of webpack errors
2025-Dec-27 15:08:14.733450 73.27 npm notice
2025-Dec-27 15:08:14.733450 73.27 npm notice New major version of npm available! 10.8.2 -> 11.7.0
2025-Dec-27 15:08:14.733450 73.27 npm notice Changelog: https://github.com/npm/cli/releases/tag/v11.7.0
2025-Dec-27 15:08:14.733450 73.27 npm notice To update run: npm install -g npm@11.7.0
2025-Dec-27 15:08:14.733450 73.27 npm notice
2025-Dec-27 15:08:14.733450 ------
2025-Dec-27 15:08:14.733450 Dockerfile:136
2025-Dec-27 15:08:14.733450 --------------------
2025-Dec-27 15:08:14.733450 134 |
2025-Dec-27 15:08:14.733450 135 | # Build Next.js en mode standalone
2025-Dec-27 15:08:14.733450 136 | >>> RUN npm run build
2025-Dec-27 15:08:14.733450 137 |
2025-Dec-27 15:08:14.733450 138 | # === ÉTAPE 3 : Production ===
2025-Dec-27 15:08:14.733450 --------------------
2025-Dec-27 15:08:14.733450 ERROR: failed to build: failed to solve: process "/bin/sh -c npm run build" did not complete successfully: exit code: 1
2025-Dec-27 15:08:14.733450 exit status 1
2025-Dec-27 15:08:14.746079 Error type: RuntimeException
2025-Dec-27 15:08:14.760558 Error code: 0
2025-Dec-27 15:08:14.773674 Location: /var/www/html/app/Traits/ExecuteRemoteCommand.php:243
2025-Dec-27 15:08:14.788485 Stack trace (first 5 lines):
2025-Dec-27 15:08:14.805684 #0 /var/www/html/app/Traits/ExecuteRemoteCommand.php(104): App\Jobs\ApplicationDeploymentJob->executeCommandWithProcess()
2025-Dec-27 15:08:14.820656 #1 /var/www/html/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php(271): App\Jobs\ApplicationDeploymentJob->{closure:App\Traits\ExecuteRemoteCommand::execute_remote_command():71}()
2025-Dec-27 15:08:14.840053 #2 /var/www/html/app/Traits/ExecuteRemoteCommand.php(71): Illuminate\Support\Collection->each()
2025-Dec-27 15:08:14.859130 #3 /var/www/html/app/Jobs/ApplicationDeploymentJob.php(3154): App\Jobs\ApplicationDeploymentJob->execute_remote_command()
2025-Dec-27 15:08:14.878240 #4 /var/www/html/app/Jobs/ApplicationDeploymentJob.php(861): App\Jobs\ApplicationDeploymentJob->build_image()
2025-Dec-27 15:08:14.896156 ========================================
2025-Dec-27 15:08:14.915662 Deployment failed. Removing the new version of your application.
2025-Dec-27 15:08:15.505970 Gracefully shutting down build container: swko0o00o8c8ooc8g84oowk4
2025-Dec-27 15:08:15.932602 [CMD]: docker stop -t 30 swko0o00o8c8ooc8g84oowk4
2025-Dec-27 15:08:15.932602 swko0o00o8c8ooc8g84oowk4

View file

@ -0,0 +1,165 @@
export function formatContractData(rawData: any) {
const data = { ...rawData };
// Formater le lieu de naissance
const cob_sans_le = data.employee_cob?.replace(/^Le /, '');
if (data.employee_cob?.startsWith('Le ')) {
data.employee_cob_formatted = `au ${cob_sans_le}`;
} else {
data.employee_cob_formatted = `à ${data.employee_cob}`;
}
// Formater la ville
const ville_sans_le = data.structure_ville?.replace(/^Le /, '');
if (data.structure_ville?.startsWith('Le ')) {
data.ville_formatted = `Au ${ville_sans_le}`;
} else {
data.ville_formatted = `À ${data.structure_ville}`;
}
// Formater la CCN
if (Array.isArray(data.CCN)) {
data.CCN_formatted = data.CCN.join(', ');
} else {
data.CCN_formatted = data.CCN;
}
// Générer le texte de durée d'engagement
data.duree_engagement_text = generateDureeEngagementText(data);
// Générer le texte des lieux d'engagement
data.lieux_engagement_text = generateLieuxEngagementText(data);
// Générer le texte d'absence maladie
data.absence_maladie_text = generateAbsenceMaladieText(data);
// Générer le texte d'exclusivité
data.exclusivite_text = generateExclusiviteText(data);
data.exclusivite_prevenu_text = generateExclusivitePrevenuText(data);
// Générer le texte d'assurances
data.assurances_text = generateAssurancesText(data);
return data;
}
function generateDureeEngagementText(data: any): string {
let text = '';
if (data.date_debut === data.date_fin) {
text = `Le présent engagement couvre la journée du ${data.date_debut}, pour `;
} else {
if (data.dates_travaillees) {
text = `Le présent engagement couvre la période du ${data.date_debut} au ${data.date_fin} pour les dates travaillées suivantes :\n<ul>`;
const dates = data.dates_travaillees.split(';');
dates.forEach((date: string, index: number) => {
text += `<li>- ${date.trim()}${index < dates.length - 1 ? ' ;' : ''}</li>`;
});
text += '</ul>\nPour ';
} else {
text = `Le présent engagement couvre la période du ${data.date_debut} au ${data.date_fin}. Pour `;
}
}
// Ajouter les cachets
if (data.employee_catpro === 'Artiste') {
if (data.cachets.representations >= 1 && data.cachets.repetitions >= 1) {
text += `un total de ${data.cachets.representations} ${data.cachets.representations === 1 ? 'cachet' : 'cachets'} de représentation et ${data.cachets.repetitions} ${data.cachets.repetitions === 1 ? 'service' : 'services'} de répétition.`;
} else if (data.cachets.representations >= 1 && data.cachets.repetitions === 0) {
text += `un total de ${data.cachets.representations} ${data.cachets.representations === 1 ? 'cachet' : 'cachets'}`;
if (data.CCN?.includes('Convention Collective Nationale de la Production Audiovisuelle') || data.CCN?.includes("Convention Collective Nationale de l'Édition")) {
text += " d'enregistrement.";
} else {
text += ' de représentation.';
}
} else if (data.cachets.representations === 0 && data.cachets.repetitions >= 1) {
text += `${data.cachets.repetitions} ${data.cachets.repetitions === 1 ? 'service' : 'services'} de répétition.`;
}
} else if (data.employee_catpro === 'Technicien') {
text += `un total de ${data.cachets.heures} heures de travail`;
if (data.cachets.heuresparjour === 0) {
text += '.';
} else if (data.cachets.heuresparjour >= 1) {
text += `, à raison de ${data.cachets.heuresparjour} heures par jour de travail.`;
}
} else if (data.employee_catpro === 'Metteur en scène') {
if (data.cachets.representations >= 1 && data.cachets.heures > 0) {
text += `un total de ${data.cachets.representations} ${data.cachets.representations === 1 ? 'cachet' : 'cachets'} de représentation et ${data.cachets.heures} heures de travail.`;
} else if (data.cachets.representations === 0) {
text += `un total de ${data.cachets.heures} heures de travail.`;
} else if (data.cachets.representations >= 1 && data.cachets.heures === 0) {
text += `un total de ${data.cachets.representations} ${data.cachets.representations === 1 ? 'cachet' : 'cachets'} de représentation.`;
}
}
// Ajouter les détails des répétitions
if (data.cachets.repetitions >= 1) {
text += `\n\nLa durée totale des répétitions sera de ${data.cachets.heures} heures`;
if (data.cachets.heuresparjour === 0) {
text += '.';
} else if (data.cachets.heuresparjour >= 1) {
text += `, à raison de ${data.cachets.heuresparjour} heures par journée de répétition.`;
}
}
return text;
}
function generateLieuxEngagementText(data: any): string {
if (data.CCN?.includes('Convention Collective Nationale de la Production Audiovisuelle') || data.CCN?.includes("Convention Collective Nationale de l'Édition")) {
return 'de travail';
} else if (data.cachets.representations >= 1 && data.cachets.repetitions === 0) {
return 'des représentations';
} else if (data.cachets.representations === 0 && data.cachets.repetitions >= 1) {
return 'des répétitions';
} else if (data.employee_catpro === 'Technicien') {
return "d'engagement";
} else if (data.cachets.representations >= 1 && data.cachets.repetitions >= 1) {
return 'des répétitions et des représentations';
} else if (data.employee_catpro === 'Metteur en scène' && data.cachets.representations === 0) {
return "d'exercice de sa fonction";
}
return "d'engagement";
}
function generateAbsenceMaladieText(data: any): string {
if (data.employee_catpro === 'Metteur en scène') {
return 'ses missions de mise en scène';
} else if (data.CCN?.includes('Convention Collective Nationale de la Production Audiovisuelle')) {
return `ses missions de ${data.employee_profession}`;
} else if (data.CCN?.includes("Convention Collective Nationale de l'Édition")) {
return 'un enregistrement';
}
return 'une répétition ou une représentation';
}
function generateExclusiviteText(data: any): string {
if (data.employee_catpro === 'Metteur en scène') {
return 'sur ses lieux de travail et aux répétitions';
} else if (data.CCN?.includes('Convention Collective Nationale de la Production Audiovisuelle')) {
return 'sur les lieux de production';
} else if (data.CCN?.includes("Convention Collective Nationale de l'Édition")) {
return "sur les lieux d'enregistrement";
}
return 'à une répétition ou à une représentation';
}
function generateExclusivitePrevenuText(data: any): string {
if (data.employee_catpro === 'Metteur en scène') {
return "de ses horaires et jours de travail et de l'existence de répétitons";
} else if (data.CCN?.includes('Convention Collective Nationale de la Production Audiovisuelle')) {
return 'de ses horaires, jours et lieux de travail';
} else if (data.CCN?.includes("Convention Collective Nationale de l'Édition")) {
return "de cet session d'enregistrement";
}
return "de l'existence de cette répétition ou représentation";
}
function generateAssurancesText(data: any): string {
if (data.CCN?.includes('Convention Collective Nationale de la Production Audiovisuelle')) {
return ' à la production audiovisuelle';
} else if (data.CCN?.includes("Convention Collective Nationale de l'Édition")) {
return " à l'édition phonographique";
}
return ' aux représentations du spectacle';
}

334
lib/templates/contract.hbs Normal file
View file

@ -0,0 +1,334 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Contrat de Travail</title>
<style>
body {
font-family: Verdana, sans-serif;
font-size: 12px;
padding: 0 50px;
}
h1 {
text-align: center;
margin-bottom: 30px;
}
h2 {
font-size: 14px;
}
p {
margin-bottom: 0;
text-align: justify;
}
.bold {
font-weight: bold;
}
.section {
margin-bottom: 30px;
page-break-inside: avoid;
}
.section-objet {
margin-bottom: 20px;
}
.section_protection {
margin-bottom: 30px;
}
.section-title {
font-weight: bold;
margin-bottom: 10px;
}
ul {
list-style-type: none;
padding-left: 0;
margin-left: 0;
}
li {
margin-bottom: 5px;
}
.info-paragraph {
display: flex;
flex-direction: column;
}
.info-signature {
font-size: 80px;
color: white;
}
.info-row {
display: flex;
flex-direction: column;
margin-bottom: 10px;
}
.info-label {
font-weight: bold;
}
.info-value {
text-align: left;
}
.info-delegation {
text-align: left;
font-style: italic;
}
</style>
</head>
<body>
{{#if imageUrl}}
<div style="display: flex; justify-content: center;">
<img src="{{imageUrl}}" style="width: 180px;" />
</div>
{{/if}}
<h1>CONTRAT D'ENGAGEMENT
{{#if (eq employee_catpro "Artiste")}}ARTISTE
{{else if (and (eq employee_civ "Madame") (eq employee_catpro "Technicien"))}}TECHNICIENNE
{{else if (and (eq employee_civ "Monsieur") (eq employee_catpro "Technicien"))}}TECHNICIEN
{{else if (and (eq employee_civ "Madame") (eq employee_catpro "Metteur·se en scène"))}}ARTISTE CADRE
{{else}}ARTISTE CADRE
{{/if}}
</h1>
<p class="bold">Entre les {{#if (eq employee_civ "Monsieur")}}soussignés{{else}}soussignées{{/if}} :</p>
<ul>
<li class="bold">{{structure_name}}</li>
<li>{{forme_juridique}}</li>
<li>{{structure_adresse}}</li>
<li>{{structure_cpville}} {{structure_ville}}</li>
<li>SIRET : {{structure_siret}}</li>
{{#if (ne structure_licence "n/a")}}
<li>Licence d'entrepreneur de spectacles : {{structure_licence}}</li>
{{/if}}
<li>représentée par {{structure_signataire}}, en sa qualité {{#if (eq structure_signatairequalite "Administrateur")}}d'{{else}}de {{/if}}{{structure_signatairequalite}}{{#if (eq delegation "Oui")}}, pour le représentant légal et par délégation{{else}}.{{/if}}</li>
</ul>
<p class="bold">d'une part,</p>
<p class="bold">et :</p>
<ul>
<li class="bold">{{employee_civ}} {{employee_firstname}} {{employee_lastname}}{{#if (ne employee_birthname employee_lastname)}}{{#if (eq employee_civ "Monsieur")}}, né {{employee_birthname}}{{else if (eq employee_civ "Madame")}}, née {{employee_birthname}}{{/if}}{{/if}}{{#if (ne employee_pseudo "n/a")}}, {{#if (eq employee_civ "Monsieur")}}dit{{else}}dite{{/if}} "{{employee_pseudo}}"{{/if}}</li>
<li>{{#if (eq employee_civ "Monsieur")}}{{else}}née{{/if}} le {{employee_dob}} {{employee_cob_formatted}}</li>
<li>demeurant {{employee_address}}</li>
{{#if (or (eq employee_ss 0) (eq employee_ss ""))}}
<li>Le numéro de Sécurité Sociale du salarié est en cours d'attribution.</li>
{{else}}
<li>N° de Sécurité Sociale : {{employee_ss}}</li>
{{/if}}
<li>N° Congés Spectacles : {{employee_cs}}</li>
{{#if (eq mineur1618 "Oui")}}
<li>dont {{#if (eq representant_civ "Monsieur")}}le représentant légal{{else if (eq representant_civ "Madame")}}la représentante légale{{/if}} est {{representant_civ}} {{representant_nom}}, {{#if (eq representant_civ "Monsieur")}}{{else if (eq representant_civ "Madame")}}née{{/if}} le {{representant_dob}} à {{representant_cob}}, demeurant {{representant_adresse}}.</li>
{{/if}}
</ul>
<p class="bold">d'autre part.</p>
<p>
Le présent contrat est conclu dans le cadre de la législation du travail, des usages en vigueur dans la
profession, de l'article L. 1242-2° du Code du travail et de l'accord interbranche sur le recours au
contrat à durée déterminée d'usage dans le spectacle du 12/10/1998. Il est, en outre, régi par les
dispositions de la {{CCN_formatted}}{{#if (contains CCN "Convention Collective Nationale de l'Édition")}} et de ses annexes afférentes à l'Édition Phonographique{{/if}}.
</p>
<p>
Il a été convenu et arrêté ce qui suit :
</p>
<div class="section">
<h2 class="section-title">OBJET</h2>
{{employee_civ}} {{employee_firstname}} {{employee_lastname}} est {{#if (eq employee_civ "Monsieur")}}engagé{{else}}engagée{{/if}} selon l'objet suivant :
<ul>
<li><b>Profession</b> : {{employee_profession}}</li>
<li><b>Code emploi</b> : {{employee_codeprofession}}</li>
<li>
{{#if (and (eq structure_spectacle "Oui") (ne type_numobjet "Administratif"))}}
<b>Spectacle</b> : {{spectacle}}
{{else if (or (contains CCN "Convention Collective Nationale de la Production Audiovisuelle") (contains CCN "Convention Collective Nationale de l'Édition"))}}
<b>Production</b> : {{spectacle}}
{{/if}}
</li>
<li>{{#if numobjet}}<b>Numéro d'objet</b> : {{numobjet}}{{else}}Le <b>numéro d'objet</b> de cette production est en cours d'attribution.{{/if}}</li>
</ul>
</div>
<div class="section-objet">
<h2 class="section-title">DURÉE DE L'ENGAGEMENT</h2>
<p>
{{duree_engagement_text}}
</p>
{{#if autreprecision_duree}}
<p>{{autreprecision_duree}}</p>
{{/if}}
</div>
<div class="section">
Il ne nous sera, en aucun cas, fait obligation de proroger le présent engagement à expiration. La fin de la période d'engagement prévue
aux présentes, prorogée éventuellement de la durée de dépassement, en constitue le terme. Il n'y a lieu à aucun préavis.
</div>
<div class="section">
<h2 class="section-title">LIEUX D'ENGAGEMENT ET HORAIRES DE TRAVAIL</h2>
<p>
{{structure_name}} communiquera à {{employee_firstname}} {{employee_lastname}} les lieux {{lieux_engagement_text}}, ainsi que ses horaires de travail.
</p>
</div>
<div class="section">
<h2 class="section-title">RÉMUNÉRATION</h2>
<p>
Il sera alloué à {{employee_firstname}} {{employee_lastname}} à titre de salaire la somme de {{salaire_brut}} euros bruts.
</p>
{{#if precisions_salaire}}
<p>
À titre informatif, la répartition de ce salaire brut est la suivante : {{precisions_salaire}}.
</p>
{{/if}}
{{#if (and panierrepas hebergement)}}
<p>{{employee_firstname}} {{employee_lastname}} percevra {{panierrepas}}
{{#if (eq panierrepas "1")}}panier repas principal{{else}}paniers repas principaux,{{/if}} et {{hebergement}} {{#if (eq hebergement "1")}}indemnité{{else}}indemnités{{/if}} d'hébergement et petit-déjeuner,
{{#if (and (eq panierrepasccn "Oui") (eq hebergementccn "Oui"))}} selon les conditions prévues par la Convention Collective.
{{else if (and (eq panierrepasccn "Non") (eq hebergementccn "Oui"))}} à hauteur de {{montantpanierrepas}} euros par panier repas principal, et selon les conditions prévues par la Convention Collective pour l'indemnité hébergement et petit-déjeuner.
{{else if (and (eq panierrepasccn "Oui") (eq hebergementccn "Non"))}} selon les conditions prévues par la Convention Collective pour les paniers repas principaux, et à hauteur de {{montanthebergement}} euros par indemnité hébergement et petit-déjeuner.
{{else if (and (eq panierrepasccn "Non") (eq hebergementccn "Non"))}} à hauteur de {{montantpanierrepas}} euros par panier repas principal et à hauteur de {{montanthebergement}} euros par indemnité hébergement et petit-déjeuner.
{{/if}}</p>
{{/if}}
{{#if autreprecision_salaire}}
<p>{{autreprecision_salaire}}</p>
{{/if}}
</div>
<div class="section">
<h2 class="section-title">RETRAITE ET CONGÉS PAYÉS</h2>
<p>
Les cotisations de retraite seront versées à AUDIENS - 7 rue Jean Bleuzen - 92177 VANVES Cedex. L'employeur acquittera ses
contributions à la caisse des Congés Spectacles conformément à la législation et dans la limite des plafonds applicables en vigueur.
</p>
</div>
<div class="section">
<h2 class="section-title">ABSENCE-MALADIE</h2>
<p>
En cas de maladie ou d'empêchement d'assurer {{absence_maladie_text}}, {{employee_firstname}} {{employee_lastname}} sera {{#if (eq employee_civ "Monsieur")}}tenu{{else}}tenue{{/if}}
d'en aviser {{structure_name}} dans un délai de 24 heures en précisant la durée probable de son absence. En cas de prolongation d'arrêt de travail,
{{employee_firstname}} {{employee_lastname}} devra transmettre à {{structure_name}}, dans les plus brefs délais, le certificat médical
justifiant de cette prolongation. En tout état de cause, les parties conviennent expressément qu'en cas de maladie de {{employee_firstname}} {{employee_lastname}},
le présent contrat pourra être résilié de plein droit par {{structure_name}} et ce, dans le respect des dispositions de la convention collective applicable.
</p>
</div>
<div class="section">
<h2 class="section-title">DROIT DE PRIORITÉ ET D'EXCLUSIVITÉ</h2>
<p>
Le présent contrat donne à {{structure_name}} une priorité absolue sur tous les autres engagements que pourrait conclure par ailleurs {{employee_firstname}} {{employee_lastname}}, sur la période de l'engagement.
La dérogation éventuelle à cette clause devra faire l'objet d'un accord écrit de {{structure_name}}.
</p>
<p>
{{employee_firstname}} {{employee_lastname}} ne pourra en aucun cas refuser sa présence {{exclusivite_text}} pour cause
d'engagement extérieur, à quelque moment qu'il·elle ait été prévenu {{exclusivite_prevenu_text}}.
</p>
</div>
<div class="section">
<h2 class="section-title">MÉDECINE DU TRAVAIL</h2>
<p>
{{employee_firstname}} {{employee_lastname}} déclare avoir satisfait aux obligations relatives à la Médecine du travail et communiquera
à {{structure_name}} l'attestation annuelle qui lui a été délivrée par cet organisme.
</p>
</div>
<div class="section">
<h2 class="section-title">ASSURANCES</h2>
<p>
{{employee_firstname}} {{employee_lastname}} est {{#if (eq employee_civ "Monsieur")}}tenu{{else}}tenue{{/if}} d'assurer contre tous les risques tous les objets lui appartenant. {{structure_name}}
déclare avoir souscrit les assurances nécessaires à la couverture des risques liés{{assurances_text}}.
</p>
</div>
<div class="section">
<h2 class="section-title">LITIGES</h2>
<p>
En cas de litige portant sur l'interprétation ou l'application du présent contrat, les parties conviennent de s'en remettre à l'appréciation des
tribunaux compétents, mais seulement après épuisement des voies amiables (conciliation, arbitrage).
</p>
</div>
<div class="section">
<h2 class="section-title">PROTECTION DES DONNÉES PERSONNELLES</h2>
<p>
Aux fins de gestion du personnel et de traitement des rémunérations, nous sommes amenés à solliciter des données personnelles vous concernant
à l'occasion de la conclusion, l'exécution et le cas échéant, la rupture de votre contrat de travail.
</p>
<p>
La signature du présent contrat vaut autorisation pour la société de collecter, d'enregistrer et de stocker les données nécessaires.
</p>
<p>
Outre les services internes de {{structure_name}}, les destinataires de ces données sont, à ce jour, les organismes de sécurité sociale,
les caisses de retraite et de prévoyance, la mutuelle, France Travail Spectacle, les services des impôts, le service de médecine du travail, les organismes conventionnels et la société
Odentas Media SAS, notre prestataire de gestion de la paie.
</p>
<p>
Ces informations sont réservées à l'usage des services concernés et ne peuvent être communiquées qu'à ces destinataires.
</p>
<p>
Vous bénéficiez notamment d'un droit d'accès, de rectification et d'effacement des informations vous concernant, que vous pouvez exercer
en adressant directement une demande au responsable de ces traitements : {{nom_responsable_traitement}}, {{qualite_responsable_traitement}}, {{email_responsable_traitement}}.
</p>
</div>
<div class="section">
<p>
Fait en double exemplaire,
</p>
<p>
{{ville_formatted}}, le {{date_signature}}.
</p>
</div>
<div class="info-paragraph">
<div class="info-row">
<div class="info-label">{{#if (eq employee_civ "Monsieur")}}Le salarié :{{else}}La salariée :{{/if}}</div>
<div class="info-value">{{employee_civ}} {{employee_firstname}} {{employee_lastname}}</div>
<br><br><br>
<div style="border-top: 1px solid #000; width: 200px; margin-top: 40px;"></div>
<div style="font-size: 10px; margin-top: 5px;">Signature du salarié</div>
</div>
{{#if (eq mineur1618 "Oui")}}
<br><br>
<div class="info-row">
<div class="info-label">{{#if (eq representant_civ "Monsieur")}}Le représentant légal{{else if (eq representant_civ "Madame")}}La représentante légale{{/if}}{{#if (eq employee_civ "Madame")}} de la salariée :{{else if (eq employee_civ "Monsieur")}} du salarié :{{/if}}</div>
<div class="info-value">{{representant_civ}} {{representant_nom}}</div>
<br><br><br>
<div style="border-top: 1px solid #000; width: 200px; margin-top: 40px;"></div>
<div style="font-size: 10px; margin-top: 5px;">Signature du représentant légal</div>
</div>
{{/if}}
<br><br>
<div class="info-row">
<div class="info-label">L'employeur:</div>
<div class="info-value">Pour {{structure_name}},</div>
{{#if (eq delegation "Oui")}}
<div class="info-delegation">Pour le représentant légal et par délégation,</div>
{{/if}}
<div class="info-value">{{structure_signataire}},</div>
<div class="info-value">{{structure_signatairequalite}}.</div>
<br><br><br>
<div style="border-top: 1px solid #000; width: 200px; margin-top: 40px;"></div>
<div style="font-size: 10px; margin-top: 5px;">Signature de l'employeur</div>
</div>
</div>
</body>
</html>

8
package-lock.json generated
View file

@ -60,6 +60,7 @@
},
"devDependencies": {
"@types/canvas-confetti": "^1.9.0",
"@types/handlebars": "^4.0.40",
"@types/js-cookie": "^3.0.6",
"@types/node": "24.3.1",
"@types/pako": "^2.0.4",
@ -4494,6 +4495,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/handlebars": {
"version": "4.0.40",
"resolved": "https://registry.npmjs.org/@types/handlebars/-/handlebars-4.0.40.tgz",
"integrity": "sha512-sGWNtsjNrLOdKha2RV1UeF8+UbQnPSG7qbe5wwbni0mw4h2gHXyPFUMOC+xwGirIiiydM/HSqjDO4rk6NFB18w==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/js-cookie": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz",

View file

@ -65,6 +65,7 @@
},
"devDependencies": {
"@types/canvas-confetti": "^1.9.0",
"@types/handlebars": "^4.0.40",
"@types/js-cookie": "^3.0.6",
"@types/node": "24.3.1",
"@types/pako": "^2.0.4",

328
test-gotenberg-local.js Normal file
View file

@ -0,0 +1,328 @@
/**
* Script de test pour Gotenberg sur VPS
* Usage: node test-gotenberg-local.js
*/
const fs = require('fs');
const path = require('path');
// ========================================
// CONFIGURATION - À ADAPTER
// ========================================
const CONFIG = {
// URL de Gotenberg
// Option A : Domaine Coolify (production) → https://gotenberg.odnt.fr
// Option B : Tunnel SSH (test local) → http://localhost:3001
gotenbergUrl: process.env.GOTENBERG_URL || 'http://localhost:3001',
// URL de votre Next.js local
nextjsUrl: 'http://localhost:3000',
// ID de contrat de test
testContractId: 'test-' + Date.now(),
};
console.log('🧪 Test Gotenberg - Configuration:');
console.log(' Gotenberg:', CONFIG.gotenbergUrl);
console.log(' Next.js:', CONFIG.nextjsUrl);
console.log('');
// ========================================
// TEST 1 : Vérifier que Gotenberg est accessible
// ========================================
async function testGotenbergHealth() {
console.log('📡 Test 1: Connexion à Gotenberg...');
try {
const response = await fetch(`${CONFIG.gotenbergUrl}/health`);
if (response.ok) {
const data = await response.json();
console.log('✅ Gotenberg est accessible et fonctionne');
console.log(' Status:', data.status || 'up');
return true;
} else {
console.error('❌ Gotenberg répond avec une erreur:', response.status);
return false;
}
} catch (error) {
console.error('❌ Impossible de contacter Gotenberg');
console.error(' Erreur:', error.message);
console.error('');
console.error('💡 Solutions possibles:');
console.error(' 1. Vérifier que Gotenberg tourne sur le VPS:');
console.error(' ssh votre-vps "docker ps | grep gotenberg"');
console.error(' 2. Vérifier que le port est ouvert:');
console.error(' ssh votre-vps "sudo ufw status | grep 3001"');
console.error(' 3. Vérifier la configuration dans .env.local');
return false;
}
}
// ========================================
// TEST 2 : Conversion HTML → PDF directe avec Gotenberg
// ========================================
async function testGotenbergDirect() {
console.log('');
console.log('📄 Test 2: Conversion HTML → PDF direct...');
const htmlContent = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
body {
font-family: Arial, sans-serif;
padding: 40px;
max-width: 800px;
margin: 0 auto;
}
h1 {
color: #4f46e5;
border-bottom: 3px solid #4f46e5;
padding-bottom: 10px;
}
.info-box {
background: #f3f4f6;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
}
.success {
color: #10b981;
font-weight: bold;
}
</style>
</head>
<body>
<h1>Test Gotenberg - ${new Date().toLocaleString('fr-FR')}</h1>
<div class="info-box">
<p class="success"> Gotenberg fonctionne correctement !</p>
<p>Ce PDF a été généré depuis votre machine locale en utilisant Gotenberg sur le VPS.</p>
<p><strong>Configuration:</strong></p>
<ul>
<li>Gotenberg URL: ${CONFIG.gotenbergUrl}</li>
<li>Test ID: ${CONFIG.testContractId}</li>
</ul>
</div>
</body>
</html>
`;
try {
// Créer le FormData manuellement
const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substr(2);
const bodyParts = [];
bodyParts.push(`--${boundary}\r\n`);
bodyParts.push(`Content-Disposition: form-data; name="files"; filename="index.html"\r\n`);
bodyParts.push(`Content-Type: text/html\r\n\r\n`);
bodyParts.push(`${htmlContent}\r\n`);
bodyParts.push(`--${boundary}--\r\n`);
const body = bodyParts.join('');
const response = await fetch(`${CONFIG.gotenbergUrl}/forms/chromium/convert/html`, {
method: 'POST',
headers: {
'Content-Type': `multipart/form-data; boundary=${boundary}`,
},
body: body,
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Erreur ${response.status}: ${errorText}`);
}
const pdfBuffer = Buffer.from(await response.arrayBuffer());
const outputPath = path.join(__dirname, 'test-gotenberg-output.pdf');
fs.writeFileSync(outputPath, pdfBuffer);
console.log('✅ PDF généré avec succès');
console.log(' Fichier:', outputPath);
console.log(' Taille:', (pdfBuffer.length / 1024).toFixed(2), 'KB');
return true;
} catch (error) {
console.error('❌ Erreur lors de la conversion PDF');
console.error(' Erreur:', error.message);
return false;
}
}
// ========================================
// TEST 3 : Générer un PDF via l'API Next.js
// ========================================
async function testNextjsApiRoute() {
console.log('');
console.log('🚀 Test 3: API Next.js /api/generate-contract-pdf...');
// Données de test pour un contrat CDDU
const contractData = {
structure_name: "Association Test Gotenberg",
structure_adresse: "123 Rue de Test",
structure_cpville: "75001",
structure_ville: "Paris",
structure_siret: "123 456 789 00012",
structure_licence: "TEST-2024",
structure_signataire: "Jean TESTEUR",
structure_signatairequalite: "Directeur",
structure_spectacle: "Oui",
delegation: "Non",
mineur1618: "Non",
employee_civ: "Monsieur",
employee_firstname: "Pierre",
employee_lastname: "DURAND",
employee_birthname: "DURAND",
employee_dob: "15/03/1990",
employee_cob: "Lyon",
employee_address: "456 Avenue Test, 69000 LYON",
employee_ss: "190037500123456",
employee_cs: "T123456",
employee_profession: "Comédien",
employee_codeprofession: "COM010",
employee_catpro: "Artiste",
employee_pseudo: "n/a",
spectacle: "Pièce de Test",
numobjet: "TEST-2024-001",
type_numobjet: "Spectacle",
date_debut: "01/01/2024",
date_fin: "31/01/2024",
dates_travaillees: "01/01/2024; 15/01/2024; 31/01/2024",
details_cachets: "",
salaire_brut: "2500,00",
date_signature: new Date().toLocaleDateString('fr-FR'),
CCN: ["Convention Collective Nationale des Entreprises Artistiques et Culturelles"],
precisions_salaire: "",
panierrepas: "",
panierrepasccn: "Non",
montantpanierrepas: "",
hebergement: "",
hebergementccn: "Non",
montanthebergement: "",
autreprecision_duree: "Test de génération via Gotenberg",
autreprecision_salaire: "",
cachets: {
representations: 3,
repetitions: 2,
heures: 40,
heuresparjour: 8
},
forme_juridique: "Association Loi 1901",
nom_responsable_traitement: "Jean TESTEUR",
qualite_responsable_traitement: "Directeur",
email_responsable_traitement: "test@example.com",
// Logo en base64 minimal (pixel transparent)
imageUrl: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
};
try {
console.log(' Envoi de la requête...');
const response = await fetch(`${CONFIG.nextjsUrl}/api/generate-contract-pdf`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contractId: CONFIG.testContractId,
contractType: 'cddu',
data: contractData
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`Erreur ${response.status}: ${JSON.stringify(errorData)}`);
}
const result = await response.json();
console.log('✅ API Next.js a répondu avec succès');
console.log(' Success:', result.success);
console.log(' Filename:', result.fileName);
console.log(' PDF URL:', result.pdfUrl);
if (result.pdfUrl) {
console.log('');
console.log('🎉 Le PDF est disponible sur Supabase Storage');
console.log(' Vous pouvez l\'ouvrir dans votre navigateur:');
console.log(' ', result.pdfUrl);
}
return true;
} catch (error) {
console.error('❌ Erreur lors de l\'appel à l\'API Next.js');
console.error(' Erreur:', error.message);
console.error('');
console.error('💡 Vérifications:');
console.error(' 1. Next.js est-il démarré ? (npm run dev)');
console.error(' 2. Le template existe-t-il ? templates-contrats/cddu-handlebars.html');
console.error(' 3. Les helpers sont-ils chargés ? lib/handlebars-helpers.ts');
console.error(' 4. La variable GOTENBERG_URL est-elle définie dans .env.local ?');
return false;
}
}
// ========================================
// EXÉCUTION DES TESTS
// ========================================
async function runAllTests() {
console.log('╔════════════════════════════════════════════════════════════╗');
console.log('║ TEST GOTENBERG - MIGRATION PDFMONKEY → GOTENBERG ║');
console.log('╚════════════════════════════════════════════════════════════╝');
console.log('');
let allPassed = true;
// Test 1: Santé de Gotenberg
const test1 = await testGotenbergHealth();
if (!test1) {
allPassed = false;
console.log('');
console.log('⚠️ Impossible de continuer sans accès à Gotenberg');
process.exit(1);
}
// Test 2: Conversion directe
const test2 = await testGotenbergDirect();
if (!test2) {
allPassed = false;
}
// Test 3: API Next.js
const test3 = await testNextjsApiRoute();
if (!test3) {
allPassed = false;
}
// Résumé
console.log('');
console.log('═══════════════════════════════════════════════════════════');
if (allPassed) {
console.log('✅ TOUS LES TESTS SONT PASSÉS AVEC SUCCÈS !');
console.log('');
console.log('🎯 Prochaines étapes:');
console.log(' 1. Modifier ContractEditor.tsx pour utiliser la nouvelle API');
console.log(' 2. Tester dans l\'interface staff/contrats/[id]');
console.log(' 3. Migrer les autres templates (RG, Avenants)');
} else {
console.log('⚠️ CERTAINS TESTS ONT ÉCHOUÉ');
console.log('');
console.log('Consultez les messages d\'erreur ci-dessus pour plus de détails.');
}
console.log('═══════════════════════════════════════════════════════════');
}
// Lancer les tests
runAllTests().catch(error => {
console.error('💥 Erreur fatale:', error);
process.exit(1);
});

47
test-gotenberg-tunnel.sh Executable file
View file

@ -0,0 +1,47 @@
#!/bin/bash
# Script de test Gotenberg avec tunnel SSH vers VPS Coolify
# Usage: ./test-gotenberg-tunnel.sh
echo "╔════════════════════════════════════════════════════════════╗"
echo "║ TEST GOTENBERG VIA TUNNEL SSH (Coolify) ║"
echo "╚════════════════════════════════════════════════════════════╝"
echo ""
# Vérifier si le tunnel SSH existe déjà
if lsof -Pi :3001 -sTCP:LISTEN -t >/dev/null ; then
echo "✅ Tunnel SSH déjà actif sur le port 3001"
else
echo "🔌 Création du tunnel SSH vers le VPS..."
echo " ssh -L 3001:gotenberg:3000 renaud@144.91.113.70 -N"
echo ""
echo "⚠️ Veuillez lancer cette commande dans un autre terminal :"
echo " ssh -L 3001:gotenberg:3000 renaud@144.91.113.70 -N"
echo ""
echo "Puis relancer ce script."
exit 1
fi
echo ""
echo "🧪 Test de connexion à Gotenberg via le tunnel..."
curl -s http://localhost:3001/health | jq '.' 2>/dev/null || curl -s http://localhost:3001/health
if [ $? -eq 0 ]; then
echo ""
echo "✅ Tunnel fonctionnel !"
echo ""
echo "📋 Configuration dans .env.local :"
echo " GOTENBERG_URL=http://localhost:3001"
echo ""
echo "🚀 Lancer les tests :"
echo " node test-gotenberg-local.js"
else
echo ""
echo "❌ Impossible de contacter Gotenberg"
echo ""
echo "💡 Vérifications :"
echo " 1. Le tunnel SSH est-il actif ?"
echo " lsof -Pi :3001 -sTCP:LISTEN"
echo " 2. Gotenberg tourne-t-il sur le VPS ?"
echo " ssh renaud@144.91.113.70 'docker ps | grep gotenberg'"
fi

14
tunnel-gotenberg.sh Executable file
View file

@ -0,0 +1,14 @@
#!/bin/bash
# Script pour créer un tunnel SSH vers Gotenberg sur le VPS
# Usage: ./tunnel-gotenberg.sh
echo "🚇 Création du tunnel SSH vers Gotenberg..."
echo "📍 Gotenberg sera accessible sur: http://localhost:3001"
echo "⚠️ Assurez-vous que GOTENBERG_URL=http://localhost:3001 est dans .env.local"
echo ""
# Créer le tunnel SSH
# -L 3001:gotenberg:3000 : Forward le port local 3001 vers gotenberg:3000 sur le VPS
# -N : Ne pas exécuter de commande distante
ssh -L 3001:gotenberg:3000 renaud@144.91.113.70 -N