feat: Clean and add CICD for K8S migration

This commit is contained in:
Vincent BRIDIER 2025-01-24 15:32:29 +01:00
parent ba6380fb94
commit 9333185e4d
No known key found for this signature in database
GPG key ID: 8571BFA20420D512
14 changed files with 270 additions and 102 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
.git
*.md

View file

@ -3,7 +3,6 @@ APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_THEME=basic
LOG_CHANNEL=stack
LOG_LEVEL=debug

View file

@ -1,12 +1,23 @@
include:
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'lint/lint7.3.yml'
- project: 'ldc-web/shared-ci'
ref: 'main'
file: 'security/security7.3.yml'
- project: "ldc-web/shared-ci"
ref: "main"
file: "lint/lint7.3.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "security/security7.3.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "build/build7.3.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "test/test.yml"
- project: "ldc-web/shared-ci"
ref: "main"
file: "deploy/deploy.yml"
stages:
- lint
- security
- lint
- security
- build
- test
- deploy

5
Dockerfile Normal file
View file

@ -0,0 +1,5 @@
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-7.3:latest
COPY --chown=www-data:www-data . /app/srcs
USER root
RUN chmod -R 755 /app/srcs/storage
USER www-data

View file

@ -1,8 +1,5 @@
## Boutique Click N Collect
## Boutique Click N Collect Sablé
## Required systems
* supervisor
## Installation

View file

@ -1,76 +0,0 @@
<?php
/**
* Command Name: LDC Web Status Checker
* Description: Envoi des infos Serveur/Laravel vers LDC Web
* Version: 1.0
* Author: Vincent BRIDIER
* Author URI: vincent.bridier@ldc.fr
*/
namespace App\Console\Commands;
use Illuminate\Console\Command;
class LDCWebStatusChecker extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'ldcweb:statuschecker';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Envoi des infos Serveur/Laravel vers LDC Web';
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$data = [];
$data['uuid'] = config('ldcweb.project_uuid');
// Sitemap.xml ?
if (file_exists(public_path() . '/sitemap.xml')) {
$data['sitemap'] = 'true';
} else {
$data['sitemap'] = 'false';
}
// Robots.txt ?
if (file_exists(public_path() . '/robots.txt')) {
$data['robots'] = 'true';
} else {
$data['robots'] = 'false';
}
// Check logs.
$data['logs'] = 0;
$patherror = storage_path('/logs');
$files = glob($patherror . '/*.log');
if (count($files) > 0) {
foreach ($files as $file) {
$data['logs'] = $data['logs'] + filesize($file);
}
}
$data['code']['version'] = app()->version();
// Send by cURL.
$url = 'https://ldc-web.ldc.fr/api/status-checker';
$ch = curl_init($url);
$payload = ['token' => 'CE8S52Qq7stf5k8frF4T', 'datas' => json_encode($data)];
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
curl_close($ch);
}
}

View file

@ -24,7 +24,7 @@ return [
|
*/
'theme' => env('APP_THEME', 'basic'),
'theme' => 'sable',
/*
|--------------------------------------------------------------------------

View file

@ -1,5 +0,0 @@
<?php
return [
'project_uuid' => env('PROJECT_UUID')
];

View file

@ -112,6 +112,23 @@ return [
'emergency' => [
'path' => storage_path('logs/laravel.log'),
],
'stdout' => [
'driver' => 'monolog',
'level' => env('LOG_LEVEL', 'debug'),
'handler' => StreamHandler::class,
'formatter' => env('LOG_STDOUT_FORMATTER'),
'with' => [
'stream' => 'php://stdout',
],
],
'k8s' => [
'driver' => 'stack',
'channels' => ['daily', 'stdout'],
'ignore_exceptions' => false,
],
],
];

View file

@ -93,10 +93,10 @@ return [
],
'contactsList' => [
'serviceweb' => explode(",", env('MAIL_LIST_SERVICEWEB', 'informatique.internet@ldc.fr')),
'serviceweb' => explode(",", env('MAIL_LIST_SERVICEWEB', 'digital@ldc.fr')),
'invalidInco' => explode(
",",
env('MAIL_LIST_INVALIDINCO', 'informatique.internet@ldc.fr,vincent.pierre@ldc.fr,christelle.manceau@ldc.fr')
env('MAIL_LIST_INVALIDINCO', 'digital@ldc.fr,lise.de-wever@ldc.fr,christelle.manceau@ldc.fr')
),
],

30
k8s-queues.sh Normal file
View file

@ -0,0 +1,30 @@
#!/usr/bin/env bash
# From https://stackoverflow.com/a/76488746/17320077
work=true
function stopQueues() {
echo "Stopping queues..."
work=false
php artisan queue:restart
sleep 45s
exit 0
}
# handle graceful shutdown
trap "" SIGPIPE
trap stopQueues EXIT
echo "Starting PHP queue workers..."
while $work; do
php artisan queue:work database --sleep=3 --tries=3 --max-time=3600 --no-interaction
sleep 1
done
# Si besoin de plusieurs threads puis terminer par un done sans &
#(while $work; do
# php artisan queue:work --queue="$(grep -oP 'SQS_QUEUE=\K.*' .env)" --no-interaction
# sleep 1
#done &)

175
manifest.yaml Normal file
View file

@ -0,0 +1,175 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: ${CI_PROJECT_PATH_SLUG}-config-map
data:
APP_NAME: "${APP_APP_NAME}"
APP_ENV: "${APP_APP_ENV}"
APP_KEY: "${APP_APP_KEY}"
APP_DEBUG: "${APP_APP_DEBUG}"
APP_URL: "https://${REDIRECT}${APP_DOMAIN}"
LOG_CHANNEL: "k8s"
DB_HOST: "mariadb.common-services"
DB_DATABASE: "${APP_DB_DATABASE}"
DB_USERNAME: "${APP_DB_USERNAME}"
DB_PASSWORD: "${APP_DB_PASSWORD}"
MAIL_HOST: "${APP_MAIL_HOST}"
MAIL_PORT: "${APP_MAIL_PORT}"
MAIL_USERNAME: "${APP_MAIL_USERNAME}"
MAIL_PASSWORD: "${APP_MAIL_PASSWORD}"
MAIL_ENCRYPTION: "${APP_MAIL_ENCRYPTION}"
MAIL_FROM_ADDRESS: "${APP_MAIL_FROM_ADDRESS}"
MAIL_FROM_NAME: "${APP_APP_NAME}"
CRM_ENDPOINT: "${APP_CRM_ENDPOINT}"
CRM_TOKEN: "${APP_CRM_TOKEN}"
CRM_PASSWORD: "${APP_CRM_PASSWORD}"
SENTRY_LARAVEL_DSN: "${APP_SENTRY_LARAVEL_DSN}"
MATOMO_SITE_ID: "${APP_MATOMO_SITE_ID}"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ${CI_PROJECT_PATH_SLUG}-pvc-storage
spec:
storageClassName: "csi-cinder-classic"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: $APP_PVC_SIZE
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ${CI_PROJECT_PATH_SLUG}-deployment
spec:
replicas: 1
selector:
matchLabels:
app: ${CI_PROJECT_PATH_SLUG}-app
template:
metadata:
labels:
app: ${CI_PROJECT_PATH_SLUG}-app
spec:
containers:
- name: ${CI_PROJECT_PATH_SLUG}-container
image: $IMAGE_TAG
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
- name: ${CI_PROJECT_PATH_SLUG}-queue-worker
image: $IMAGE_TAG
lifecycle:
preStop:
exec:
command: [ "/bin/sh", "-c", "kill -s TERM 1; while test $(ps ax | grep -v grep | grep bash | wc -l) -gt 0; do sleep 2s; done" ]
resources:
limits:
memory: 512Mi
cpu: "1"
command:
- "bash"
args:
- "k8s-queues.sh"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
---
apiVersion: v1
kind: Service
metadata:
name: ${CI_PROJECT_PATH_SLUG}-service
spec:
selector:
app: ${CI_PROJECT_PATH_SLUG}-app
ports:
- port: 80
targetPort: 443
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ${CI_PROJECT_PATH_SLUG}-ingress-route
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`${APP_DOMAIN}`) || Host(`www.${APP_DOMAIN}`)
kind: Rule
services:
- name: ${CI_PROJECT_PATH_SLUG}-service
port: 80
middlewares:
- name: redirect-no-www-to-www
tls:
secretName: ${CRT_TLS_NAME}
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: ${CI_PROJECT_PATH_SLUG}-cronjob
spec:
schedule: "* * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- ${CI_PROJECT_PATH_SLUG}-app
topologyKey: "kubernetes.io/hostname"
namespaces: [ $KUBE_NAMESPACE ]
containers:
- name: ${CI_PROJECT_PATH_SLUG}-scheduled
image: $IMAGE_TAG
imagePullPolicy: IfNotPresent
command:
- "php"
args:
- "artisan"
- "schedule:run"
envFrom:
- configMapRef:
name: ${CI_PROJECT_PATH_SLUG}-config-map
volumeMounts:
- name: storage
mountPath: /app/srcs/storage
imagePullSecrets:
- name: docker-registry-credentials
volumes:
- name: storage
persistentVolumeClaim:
claimName: ${CI_PROJECT_PATH_SLUG}-pvc-storage
securityContext:
runAsUser: 33
runAsGroup: 33
fsGroup: 33
fsGroupChangePolicy: "OnRootMismatch"
restartPolicy: OnFailure

13
production-resources.yaml Normal file
View file

@ -0,0 +1,13 @@
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: $APP_DOMAIN
spec:
dnsNames:
- $APP_DOMAIN
- www.${APP_DOMAIN}
secretName: $APP_DOMAIN
issuerRef:
name: $APP_CERT_ISSUER
kind: ClusterIssuer

8
webpack.mix.js vendored
View file

@ -28,13 +28,13 @@ mix.js("resources/js/app.js", "public/b-o/js")
);
//add front theme mix
mix.js('resources/views/front/' + process.env.APP_THEME + '/js/app.js', 'public/' + process.env.APP_THEME + '/js')
.sass('resources/views/front/' + process.env.APP_THEME + '/sass/app.scss', 'public/' + process.env.APP_THEME + '/css')
mix.js('resources/views/front/sable/js/app.js', 'public/sable/js')
.sass('resources/views/front/sable/sass/app.scss', 'public/sable/css')
.options({
processCssUrls: false
})
.version();
mix.copyDirectory('resources/views/front/' + process.env.APP_THEME + '/img', 'public/' + process.env.APP_THEME + '/img/')
.copyDirectory('resources/views/front/' + process.env.APP_THEME + '/fonts', 'public/' + process.env.APP_THEME + '/fonts/');
mix.copyDirectory('resources/views/front/sable/img', 'public/sable/img/')
.copyDirectory('resources/views/front/sable/fonts', 'public/sable/fonts/');