Configuration ci cd
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
---
|
||||
- name: Récupérer l'ancienne version
|
||||
ansible.builtin.shell: "dpkg-query -W -f='${Version}' {{ vhost.type }}-{{ vhost.package_name }} || echo 'N/A'"
|
||||
register: old_version
|
||||
changed_when: false
|
||||
|
||||
- name: Installer le package
|
||||
ansible.builtin.apt:
|
||||
name: "{{ vhost.type }}-{{ vhost.package_name }}={{ vhost.version }}"
|
||||
state: present
|
||||
|
||||
- name: Récupérer la nouvelle version
|
||||
ansible.builtin.shell: "dpkg-query -W -f='${Version}' {{ vhost.type }}-{{ vhost.package_name }} || echo 'N/A'"
|
||||
register: new_version
|
||||
changed_when: false
|
||||
|
||||
- name: Notification en cas de mise à jour
|
||||
block:
|
||||
- name: Changer le propriétaire et permissions du projet
|
||||
file:
|
||||
path: /var/www/{{ vhost.package_name }}
|
||||
state: directory
|
||||
recurse: yes
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0750'
|
||||
|
||||
- name: Créer le fichier de log
|
||||
file:
|
||||
path: /var/log/nginx/{{ vhost.package_name }}.log
|
||||
state: touch
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0664'
|
||||
|
||||
- name: Afficher l'évolution de la version
|
||||
ansible.builtin.debug:
|
||||
msg: "📦 Mise à jour du paquet {{ vhost.package_name }} de {{ old_version.stdout }} vers {{ new_version.stdout }}"
|
||||
|
||||
- name: Envoyer notification Telegram
|
||||
ansible.builtin.uri:
|
||||
url: "https://api.telegram.org/bot{{ telegram_bot_token }}/sendMessage"
|
||||
method: POST
|
||||
body_format: json
|
||||
body:
|
||||
chat_id: "{{ telegram_chat_id }}"
|
||||
text: |
|
||||
📦 {{ vhost.package_name }} mis à jour !
|
||||
Ancienne version : {{ old_version.stdout }}
|
||||
Nouvelle version : {{ new_version.stdout }}
|
||||
headers:
|
||||
Content-Type: "application/json"
|
||||
when: old_version.stdout != new_version.stdout
|
||||
|
||||
- name: Déployer le fichier .env
|
||||
ansible.builtin.template:
|
||||
src: "{{ vhost.env_template | default('host.env.j2') }}"
|
||||
dest: "/var/www/{{ vhost.package_name }}/.env"
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: "0640"
|
||||
|
||||
- name: Exécuter les commandes artisan post-déploiement
|
||||
ansible.builtin.shell: >
|
||||
runuser -u www-data --
|
||||
/usr/bin/php{{ vhost.php_version }} artisan {{ item }}
|
||||
args:
|
||||
chdir: "/var/www/{{ vhost.package_name }}"
|
||||
loop: "{{ vhost.artisan_post_deploy_commands | default([]) }}"
|
||||
loop_control:
|
||||
label: "{{ item }}"
|
||||
when: vhost.artisan_post_deploy_commands is defined
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
- name: Créer le répertoire de logs
|
||||
file:
|
||||
path: "/var/log/laravel-worker"
|
||||
state: directory
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0755'
|
||||
|
||||
- name: Déployer le fichier de configuration
|
||||
copy:
|
||||
dest: /etc/supervisor/conf.d/{{ worker.name }}.conf
|
||||
content: |
|
||||
[program:{{ worker.name }}]
|
||||
command=/usr/bin/php{{ worker.php_version }} /var/www/{{ worker.package_name }}/artisan queue:work --queue={{ worker.queue }}{% if worker.options is defined %} {{ worker.options }}{% endif %}
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stderr_logfile=/var/log/laravel-worker/{{ worker.name }}.err.log
|
||||
stdout_logfile=/var/log/laravel-worker/{{ worker.name }}.out.log
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
loop: "{{ laravel_workers }}"
|
||||
loop_control:
|
||||
loop_var: worker
|
||||
label: "{{ worker.name }}"
|
||||
|
||||
- name: Créer le fichier de log du worker
|
||||
ansible.builtin.file:
|
||||
path: "/var/log/laravel-worker/{{ worker.name }}.log"
|
||||
state: touch
|
||||
owner: www-data
|
||||
group: www-data
|
||||
mode: '0664'
|
||||
loop: "{{ laravel_workers }}"
|
||||
loop_control:
|
||||
loop_var: worker
|
||||
label: "{{ worker.name }}"
|
||||
|
||||
- name: Recharger la configuration de supervisord
|
||||
command: supervisorctl reread
|
||||
|
||||
- name: Mettre à jour les processus supervisord
|
||||
command: supervisorctl update
|
||||
|
||||
- name: Redémarrer les workers
|
||||
command: supervisorctl restart all
|
||||
@@ -0,0 +1,52 @@
|
||||
FROM eclipse-temurin:21-jdk
|
||||
|
||||
ARG ANDROID_API_VERSION=36
|
||||
ARG ANDROID_BUILD_TOOLS_VERSION=36.0.0
|
||||
ARG FLUTTER_CHANNEL=stable
|
||||
|
||||
ENV ANDROID_SDK_ROOT=/opt/android-sdk \
|
||||
ANDROID_HOME=/opt/android-sdk \
|
||||
FLUTTER_HOME=/opt/flutter \
|
||||
DEBIAN_FRONTEND=noninteractive \
|
||||
HOME=/root \
|
||||
PUB_CACHE=/root/.pub-cache \
|
||||
GRADLE_USER_HOME=/root/.gradle
|
||||
|
||||
ENV PATH=${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin:${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin:${ANDROID_SDK_ROOT}/platform-tools:${PATH}
|
||||
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
bash \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
libglu1-mesa \
|
||||
openssh-client \
|
||||
unzip \
|
||||
wget \
|
||||
xz-utils \
|
||||
zip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools \
|
||||
&& curl -fsSL -o /tmp/commandlinetools.zip https://dl.google.com/android/repository/commandlinetools-linux-11076708_latest.zip \
|
||||
&& unzip -q /tmp/commandlinetools.zip -d ${ANDROID_SDK_ROOT}/cmdline-tools \
|
||||
&& mv ${ANDROID_SDK_ROOT}/cmdline-tools/cmdline-tools ${ANDROID_SDK_ROOT}/cmdline-tools/latest \
|
||||
&& rm /tmp/commandlinetools.zip
|
||||
|
||||
RUN yes | sdkmanager --licenses >/dev/null \
|
||||
&& sdkmanager \
|
||||
"platform-tools" \
|
||||
"platforms;android-${ANDROID_API_VERSION}" \
|
||||
"build-tools;${ANDROID_BUILD_TOOLS_VERSION}" \
|
||||
"cmdline-tools;latest"
|
||||
|
||||
RUN git clone --depth 1 --branch ${FLUTTER_CHANNEL} https://github.com/flutter/flutter.git ${FLUTTER_HOME} \
|
||||
&& git config --global --add safe.directory ${FLUTTER_HOME}
|
||||
|
||||
RUN flutter config --no-analytics \
|
||||
&& flutter precache --android \
|
||||
&& flutter doctor -v || true
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
CMD ["bash"]
|
||||
@@ -0,0 +1,121 @@
|
||||
def call(Map config = [:]) {
|
||||
def packageName = config.get('name', 'flutter-app')
|
||||
def apiVersion = config.get('api', '36')
|
||||
def dockerImage = "jenkins/build-flutter-android:${apiVersion}"
|
||||
|
||||
// URLs configurables depuis le Jenkinsfile si besoin
|
||||
def debugApiBaseUrl = config.get('debugApiBaseUrl', 'http://192.168.1.37:8000/api/v1')
|
||||
def releaseApiBaseUrl = config.get('releaseApiBaseUrl', 'https://laundry-dev.abpcode.fr//api/v1')
|
||||
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
PUB_CACHE = "${WORKSPACE}/.pub-cache"
|
||||
GRADLE_USER_HOME = "${WORKSPACE}/.gradle"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prepare docker') {
|
||||
steps {
|
||||
script {
|
||||
writeFile file: 'Dockerfile', text: libraryResource("dockerfiles/flutter/android/${apiVersion}/Dockerfile")
|
||||
docker.build(dockerImage, "--pull=false .")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
cleanWs()
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Flutter doctor') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u root') {
|
||||
sh 'git config --global --add safe.directory "$WORKSPACE" || true'
|
||||
sh 'flutter --version'
|
||||
sh 'flutter doctor -v'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Dependencies') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u root') {
|
||||
sh 'git config --global --add safe.directory "$WORKSPACE" || true'
|
||||
sh 'flutter pub get'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Analyze') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u root') {
|
||||
sh 'git config --global --add safe.directory "$WORKSPACE" || true'
|
||||
sh 'flutter analyze'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Test') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u root') {
|
||||
sh 'git config --global --add safe.directory "$WORKSPACE" || true'
|
||||
sh 'flutter test'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build Android') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u root') {
|
||||
sh 'git config --global --add safe.directory "$WORKSPACE" || true'
|
||||
|
||||
if (env.TAG_NAME) {
|
||||
sh """
|
||||
flutter build apk --release \
|
||||
--dart-define=API_BASE_URL=${releaseApiBaseUrl}
|
||||
"""
|
||||
} else {
|
||||
sh """
|
||||
flutter build apk --debug \
|
||||
--dart-define=API_BASE_URL=${debugApiBaseUrl}
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Publish') {
|
||||
steps {
|
||||
script {
|
||||
if (env.TAG_NAME) {
|
||||
env.deployment = 'prod'
|
||||
env.version = "${env.TAG_NAME}-${env.BUILD_NUMBER}"
|
||||
sh "cp build/app/outputs/flutter-apk/app-release.apk ./${packageName}-${env.deployment}-${env.version}.apk"
|
||||
} else {
|
||||
env.deployment = 'debug'
|
||||
env.version = "${env.BUILD_NUMBER}"
|
||||
sh "cp build/app/outputs/flutter-apk/app-debug.apk ./${packageName}-${env.deployment}-${env.version}.apk"
|
||||
}
|
||||
|
||||
archiveArtifacts artifacts: "${packageName}-${env.deployment}-${env.version}.apk", fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
APP_NAME='{{ vhost.package_name }}'
|
||||
APP_ENV='{{ vhost.app_env | default('production') }}'
|
||||
APP_DEBUG='{{ vhost.app_debug | default('false') }}'
|
||||
APP_URL='{{ vhost.app_url }}'
|
||||
APP_KEY='{{ vhost.app_key }}'
|
||||
APP_TIMEZONE='{{ vhost.app_timezone | default('Europe/Paris') }}'
|
||||
|
||||
APP_LOCALE='fr'
|
||||
APP_FALLBACK_LOCALE='fr'
|
||||
|
||||
LOG_CHANNEL='stack'
|
||||
LOG_STACK='single'
|
||||
LOG_LEVEL='{{ vhost.app_log_lvl | default('info') }}'
|
||||
|
||||
DB_CONNECTION='mysql'
|
||||
DB_HOST='localhost'
|
||||
DB_PORT='8001'
|
||||
DB_DATABASE='{{ vhost.app_db_name }}'
|
||||
DB_USERNAME='{{ vhost.app_db_user }}'
|
||||
DB_PASSWORD='{{ vhost.app_db_password }}'
|
||||
|
||||
SESSION_DRIVER='{{ vhost.app_session_driver | default('database') }}'
|
||||
SESSION_LIFETIME='120'
|
||||
|
||||
QUEUE_CONNECTION='{{ vhost.app_queue_connection | default('database') }}'
|
||||
CACHE_STORE='{{ vhost.app_cache_store | default('database') }}'
|
||||
|
||||
BROADCAST_CONNECTION='log'
|
||||
FILESYSTEM_DISK='local'
|
||||
|
||||
STRIPE_KEY='{{ vhost.app_stripe_key | default('') }}'
|
||||
STRIPE_SECRET='{{ vhost.app_stripe_secret_key | default('') }}'
|
||||
STRIPE_WEBHOOK_SECRET='{{ vhost.app_stripe_webhook_secret | default('') }}'
|
||||
|
||||
CORS_ALLOWED_ORIGINS='{{ vhost.app_cors_allowed_origins | default(vhost.app_url) }}'
|
||||
|
||||
LAVERIE_MACHINE_API_KEY='{{ vhost.app_laverie_machine_api_key | default('') }}'
|
||||
LAVERIE_SIM_CYCLE_SECONDS='{{ vhost.app_laverie_sim_cycle_seconds | default('30') }}'
|
||||
LAVERIE_BOOKING_FEE='{{ vhost.app_laverie_booking_fee | default('1.00') }}'
|
||||
LAVERIE_BOOKING_CANCEL_GRACE_HOURS='{{ vhost.app_laverie_booking_cancel_grace_hours | default('2') }}'
|
||||
LAVERIE_BOOKING_NO_SHOW_GRACE_MINUTES='{{ vhost.app_laverie_booking_no_show_grace_minutes | default('15') }}'
|
||||
LAVERIE_BOOKING_PENALTY_AMOUNT='{{ vhost.app_laverie_booking_penalty_amount | default('3.00') }}'
|
||||
LAVERIE_MACHINE_OFFLINE_THRESHOLD_MINUTES='{{ vhost.app_laverie_machine_offline_threshold_minutes | default('10') }}'
|
||||
LAVERIE_MACHINE_OFFLINE_CHECK_ENABLED='{{ vhost.app_laverie_machine_offline_check_enabled | default('false') }}'
|
||||
LAVERIE_PAYMENT_PROVIDER='{{ vhost.app_laverie_payment_provider | default('stripe') }}'
|
||||
LAVERIE_TOP_UP_MIN='{{ vhost.app_laverie_top_up_min | default('5') }}'
|
||||
LAVERIE_TOP_UP_MAX='{{ vhost.app_laverie_top_up_max | default('150') }}'
|
||||
@@ -0,0 +1,30 @@
|
||||
|
||||
- package_name: 'laundry-backend'
|
||||
server_name:
|
||||
- 'laundry-dev.abpcode.fr'
|
||||
php_version: '8.3'
|
||||
type: 'laravel'
|
||||
version: '*'
|
||||
env_template: 'host-laundry.env.j2'
|
||||
app_env: 'production'
|
||||
app_debug: 'false'
|
||||
app_log_lvl: 'info'
|
||||
app_url: 'https://laundry-dev.abpcode.fr/'
|
||||
app_key: 'VFMopd0BT6Ll6tQ28gtmif4JSjnaijdU'
|
||||
app_db_name: ''
|
||||
app_db_user: ''
|
||||
app_db_password: ''
|
||||
app_queue_connection: 'database'
|
||||
app_cache_store: 'database'
|
||||
app_session_driver: 'database'
|
||||
app_cors_allowed_origins: 'https://laundry-dev.abpcode.fr'
|
||||
app_laverie_machine_api_key: 'prod-laundry-machine-api-k7x9m2n4p8q1'
|
||||
app_laverie_machine_offline_check_enabled: 'false'
|
||||
app_laverie_payment_provider: 'stripe'
|
||||
app_stripe_key: ''
|
||||
app_stripe_secret_key: ''
|
||||
artisan_post_deploy_commands:
|
||||
- 'migrate --force'
|
||||
- 'config:cache'
|
||||
- 'route:cache'
|
||||
- 'view:cache'
|
||||
@@ -0,0 +1,128 @@
|
||||
def call(Map config = [:]) {
|
||||
def packageName = config.get('name', 'web')
|
||||
def phpVersion = config.get('phpVersion', '7.4')
|
||||
def dockerImage = "jenkins/build-web:${phpVersion}"
|
||||
def packageType = "laravel"
|
||||
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
stages {
|
||||
stage('Prepare docker') {
|
||||
steps {
|
||||
script {
|
||||
writeFile file: 'Dockerfile', text: libraryResource("dockerfiles/web/${phpVersion}/Dockerfile")
|
||||
docker.build(dockerImage, "--pull=false .")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
cleanWs()
|
||||
checkout scm
|
||||
}
|
||||
}
|
||||
|
||||
stage('Dependencies') {
|
||||
parallel {
|
||||
stage('Composer') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside("-u jenkins --mount type=bind,source=${JENKINS_SSH_PATH},target=/home/jenkins/.ssh -w /app") {
|
||||
dir('src') {
|
||||
sh 'composer install --no-interaction --prefer-dist --no-dev -v'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Node') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u jenkins -w /app') {
|
||||
dir('src') {
|
||||
sh 'npm install'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
script {
|
||||
docker.image(dockerImage).inside('-u jenkins -w /app') {
|
||||
dir('src') {
|
||||
sh 'npm run prod'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Packaging') {
|
||||
steps {
|
||||
script {
|
||||
if (env.TAG_NAME) {
|
||||
env['packageVersion'] = sh(returnStdout: true, script: "echo ${TAG_NAME}-${BUILD_NUMBER}").trim()
|
||||
} else {
|
||||
env['packageVersion'] = sh(returnStdout: true, script: "echo ${BUILD_NUMBER}").trim()
|
||||
}
|
||||
|
||||
dir('src') {
|
||||
sh """
|
||||
mkdir -p ../fpm/var/www/${packageName}
|
||||
rsync -a . ../fpm/var/www/${packageName} \
|
||||
--exclude=".env" \
|
||||
--exclude=".env.testing" \
|
||||
--exclude=".env.exemple" \
|
||||
--exclude="conf.php" \
|
||||
--exclude="*test*" \
|
||||
--exclude="vendor/phpunit" \
|
||||
--exclude="phpunit.xml" \
|
||||
--exclude="package-lock.json" \
|
||||
--exclude="composer.lock"
|
||||
"""
|
||||
}
|
||||
|
||||
dir('fpm') {
|
||||
sh """
|
||||
fpm --deb-no-default-config-files -s dir -t deb -a all -m technique@abpcode.fr \
|
||||
-n ${packageType}-${packageName} \
|
||||
-v ${packageVersion} \
|
||||
--url ${GIT_URL} \
|
||||
-p ../${packageType}-${packageName}-${packageVersion}.deb ./
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Publish') {
|
||||
steps {
|
||||
script {
|
||||
archiveArtifacts artifacts: "${packageType}-${packageName}-${packageVersion}.deb", fingerprint: true
|
||||
|
||||
if (env.TAG_NAME) {
|
||||
def debFile = sh(
|
||||
script: "ls -1 ${packageType}-${packageName}-${packageVersion}.deb",
|
||||
returnStdout: true
|
||||
).trim()
|
||||
|
||||
sh """
|
||||
scp -P 2224 -i /var/jenkins_home/.ssh/id_rsa -o StrictHostKeyChecking=no \
|
||||
${debFile} jenkins@repo.abpcode.fr:/repo/pool/.tmp.deb
|
||||
ssh -p 2224 -i /var/jenkins_home/.ssh/id_rsa -o StrictHostKeyChecking=no \
|
||||
jenkins@repo.abpcode.fr "mv /repo/pool/.tmp.deb /repo/pool/${debFile}"
|
||||
"""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
# Utiliser PHP 8.3 CLI
|
||||
FROM php:8.3-cli
|
||||
|
||||
# Installer Git, unzip/zip et curl
|
||||
RUN apt-get update && apt-get install -y \
|
||||
git \
|
||||
unzip \
|
||||
zip \
|
||||
curl \
|
||||
openssh-client \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Installer Composer 2
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Installer Node.js
|
||||
RUN curl -sL https://deb.nodesource.com/setup_22.x | bash -
|
||||
RUN apt install -y nodejs
|
||||
|
||||
# Créer l'utilisateur jenkins avec home et bash
|
||||
RUN useradd -m -s /bin/bash jenkins
|
||||
|
||||
# Créer le répertoire .ssh pour Jenkins
|
||||
RUN mkdir -p /home/jenkins/.ssh \
|
||||
&& chmod 700 /home/jenkins/.ssh
|
||||
|
||||
# Définir l'utilisateur jenkins pour la suite
|
||||
USER jenkins
|
||||
|
||||
# Définir le répertoire de travail
|
||||
WORKDIR /app
|
||||
|
||||
# Définir GIT_SSH_COMMAND pour tous les builds
|
||||
ENV GIT_SSH_COMMAND="ssh -i /home/jenkins/.ssh/id_rsa -o StrictHostKeyChecking=no"
|
||||
|
||||
# Optionnel : copier un script d'entrée ou autres fichiers si nécessaire
|
||||
# COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
# RUN chmod +x /usr/local/bin/entrypoint.sh
|
||||
# ENTRYPOINT ["entrypoint.sh"]
|
||||
Reference in New Issue
Block a user