From 65f6d8a530dc9a0dd3fc48fa6694360e7c6f11a5 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 9 Feb 2026 18:11:34 +0100 Subject: [PATCH] =?UTF-8?q?feat=20:=20ajout=20monolog=20+=20fix=20script?= =?UTF-8?q?=20de=20d=C3=A9ploiement?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/SIRH.iml | 3 + .idea/dataSources.xml | 12 -- .idea/data_source_mapping.xml | 6 - .idea/php.xml | 3 + composer.json | 1 + composer.lock | 261 +++++++++++++++++++++++++++++++++- config/bundles.php | 2 + config/packages/monolog.yaml | 28 ++++ config/reference.php | 147 +++++++++++++++++++ deploy/nginx/sirh.conf | 43 ++++++ scripts/deploy-release.sh | 83 +++++++++++ symfony.lock | 12 ++ 12 files changed, 582 insertions(+), 19 deletions(-) delete mode 100644 .idea/dataSources.xml delete mode 100644 .idea/data_source_mapping.xml create mode 100644 config/packages/monolog.yaml create mode 100644 deploy/nginx/sirh.conf create mode 100644 scripts/deploy-release.sh diff --git a/.idea/SIRH.iml b/.idea/SIRH.iml index ce7d6d2..6ff23a1 100644 --- a/.idea/SIRH.iml +++ b/.idea/SIRH.iml @@ -142,6 +142,9 @@ + + + diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml deleted file mode 100644 index 6b0c16f..0000000 --- a/.idea/dataSources.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - postgresql - true - org.postgresql.Driver - jdbc:postgresql://localhost:5433/postgres - $ProjectFileDir$ - - - \ No newline at end of file diff --git a/.idea/data_source_mapping.xml b/.idea/data_source_mapping.xml deleted file mode 100644 index c4bcacd..0000000 --- a/.idea/data_source_mapping.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/php.xml b/.idea/php.xml index 380453f..6df8250 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -150,6 +150,9 @@ + + + diff --git a/composer.json b/composer.json index f0b9733..bf8f442 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "symfony/flex": "^2", "symfony/framework-bundle": "8.0.*", "symfony/http-client": "8.0.*", + "symfony/monolog-bundle": "^4.0", "symfony/property-access": "8.0.*", "symfony/property-info": "8.0.*", "symfony/runtime": "8.0.*", diff --git a/composer.lock b/composer.lock index 19fbdb0..58cd62f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f181b165d122aecdae0a7df1d1e33aec", + "content-hash": "71d28cc0a29fa3f385b067186aa43678", "packages": [ { "name": "api-platform/doctrine-common", @@ -2771,6 +2771,109 @@ }, "time": "2025-07-25T09:04:22+00:00" }, + { + "name": "monolog/monolog", + "version": "3.10.0", + "source": { + "type": "git", + "url": "https://github.com/Seldaek/monolog.git", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/b321dd6749f0bf7189444158a3ce785cc16d69b0", + "reference": "b321dd6749f0bf7189444158a3ce785cc16d69b0", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/log": "^2.0 || ^3.0" + }, + "provide": { + "psr/log-implementation": "3.0.0" + }, + "require-dev": { + "aws/aws-sdk-php": "^3.0", + "doctrine/couchdb": "~1.0@dev", + "elasticsearch/elasticsearch": "^7 || ^8", + "ext-json": "*", + "graylog2/gelf-php": "^1.4.2 || ^2.0", + "guzzlehttp/guzzle": "^7.4.5", + "guzzlehttp/psr7": "^2.2", + "mongodb/mongodb": "^1.8 || ^2.0", + "php-amqplib/php-amqplib": "~2.4 || ^3", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", + "predis/predis": "^1.1 || ^2", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", + "symfony/mailer": "^5.4 || ^6", + "symfony/mime": "^5.4 || ^6" + }, + "suggest": { + "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", + "doctrine/couchdb": "Allow sending log messages to a CouchDB server", + "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client", + "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", + "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler", + "ext-mbstring": "Allow to work properly with unicode symbols", + "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)", + "ext-openssl": "Required to send log messages using SSL", + "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)", + "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", + "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)", + "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", + "rollbar/rollbar": "Allow sending log messages to Rollbar", + "ruflin/elastica": "Allow sending log messages to an Elastic Search server" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Monolog\\": "src/Monolog" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "https://seld.be" + } + ], + "description": "Sends your logs to files, sockets, inboxes, databases and various web services", + "homepage": "https://github.com/Seldaek/monolog", + "keywords": [ + "log", + "logging", + "psr-3" + ], + "support": { + "issues": "https://github.com/Seldaek/monolog/issues", + "source": "https://github.com/Seldaek/monolog/tree/3.10.0" + }, + "funding": [ + { + "url": "https://github.com/Seldaek", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", + "type": "tidelift" + } + ], + "time": "2026-01-02T08:56:05+00:00" + }, { "name": "nelmio/cors-bundle", "version": "2.6.1", @@ -5271,6 +5374,162 @@ ], "time": "2026-01-28T10:46:31+00:00" }, + { + "name": "symfony/monolog-bridge", + "version": "v8.0.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bridge.git", + "reference": "7c3da570ec252d5ca1212945ddbbf1dac4a0d779" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bridge/zipball/7c3da570ec252d5ca1212945ddbbf1dac4a0d779", + "reference": "7c3da570ec252d5ca1212945ddbbf1dac4a0d779", + "shasum": "" + }, + "require": { + "monolog/monolog": "^3", + "php": ">=8.4", + "symfony/http-kernel": "^7.4|^8.0", + "symfony/service-contracts": "^2.5|^3" + }, + "require-dev": { + "symfony/console": "^7.4|^8.0", + "symfony/http-client": "^7.4|^8.0", + "symfony/mailer": "^7.4|^8.0", + "symfony/messenger": "^7.4|^8.0", + "symfony/mime": "^7.4|^8.0", + "symfony/security-core": "^7.4|^8.0", + "symfony/var-dumper": "^7.4|^8.0" + }, + "type": "symfony-bridge", + "autoload": { + "psr-4": { + "Symfony\\Bridge\\Monolog\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides integration for Monolog with various Symfony components", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/monolog-bridge/tree/v8.0.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-07T12:23:22+00:00" + }, + { + "name": "symfony/monolog-bundle", + "version": "v4.0.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/monolog-bundle.git", + "reference": "3b4ee2717ee56c5e1edb516140a175eb2a72bc66" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/3b4ee2717ee56c5e1edb516140a175eb2a72bc66", + "reference": "3b4ee2717ee56c5e1edb516140a175eb2a72bc66", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0", + "monolog/monolog": "^3.5", + "php": ">=8.2", + "symfony/config": "^7.3 || ^8.0", + "symfony/dependency-injection": "^7.3 || ^8.0", + "symfony/http-kernel": "^7.3 || ^8.0", + "symfony/monolog-bridge": "^7.3 || ^8.0", + "symfony/polyfill-php84": "^1.30" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.41 || ^12.3", + "symfony/console": "^7.3 || ^8.0", + "symfony/yaml": "^7.3 || ^8.0" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Symfony\\Bundle\\MonologBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony MonologBundle", + "homepage": "https://symfony.com", + "keywords": [ + "log", + "logging" + ], + "support": { + "issues": "https://github.com/symfony/monolog-bundle/issues", + "source": "https://github.com/symfony/monolog-bundle/tree/v4.0.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-12-08T08:00:13+00:00" + }, { "name": "symfony/password-hasher", "version": "v8.0.4", diff --git a/config/bundles.php b/config/bundles.php index 3b0483e..746539c 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -8,6 +8,7 @@ use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle; use Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle; use Nelmio\CorsBundle\NelmioCorsBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\MonologBundle\MonologBundle; use Symfony\Bundle\SecurityBundle\SecurityBundle; use Symfony\Bundle\TwigBundle\TwigBundle; @@ -20,4 +21,5 @@ return [ NelmioCorsBundle::class => ['all' => true], ApiPlatformBundle::class => ['all' => true], LexikJWTAuthenticationBundle::class => ['all' => true], + MonologBundle::class => ['all' => true], ]; diff --git a/config/packages/monolog.yaml b/config/packages/monolog.yaml new file mode 100644 index 0000000..06b67a2 --- /dev/null +++ b/config/packages/monolog.yaml @@ -0,0 +1,28 @@ +monolog: + channels: [deprecation] + +when@dev: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + channels: ["!event"] + console: + type: console + process_psr_3_messages: false + channels: ["!event", "!doctrine", "!console"] + +when@prod: + monolog: + handlers: + main: + type: stream + path: "%kernel.logs_dir%/%kernel.environment%.log" + level: debug + channels: ["!deprecation"] + deprecation: + type: stream + channels: [deprecation] + path: "%kernel.logs_dir%/deprecations.log" diff --git a/config/reference.php b/config/reference.php index b0fdc61..e6f1493 100644 --- a/config/reference.php +++ b/config/reference.php @@ -1608,6 +1608,149 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * cache?: scalar|Param|null, // Storage to track blocked tokens // Default: "cache.app" * }, * } + * @psalm-type MonologConfig = array{ + * use_microseconds?: scalar|Param|null, // Default: true + * channels?: list, + * handlers?: array, + * }>, + * accepted_levels?: list, + * min_level?: scalar|Param|null, // Default: "DEBUG" + * max_level?: scalar|Param|null, // Default: "EMERGENCY" + * buffer_size?: scalar|Param|null, // Default: 0 + * flush_on_overflow?: bool|Param, // Default: false + * handler?: scalar|Param|null, + * url?: scalar|Param|null, + * exchange?: scalar|Param|null, + * exchange_name?: scalar|Param|null, // Default: "log" + * channel?: scalar|Param|null, // Default: null + * bot_name?: scalar|Param|null, // Default: "Monolog" + * use_attachment?: scalar|Param|null, // Default: true + * use_short_attachment?: scalar|Param|null, // Default: false + * include_extra?: scalar|Param|null, // Default: false + * icon_emoji?: scalar|Param|null, // Default: null + * webhook_url?: scalar|Param|null, + * exclude_fields?: list, + * token?: scalar|Param|null, + * region?: scalar|Param|null, + * source?: scalar|Param|null, + * use_ssl?: bool|Param, // Default: true + * user?: mixed, + * title?: scalar|Param|null, // Default: null + * host?: scalar|Param|null, // Default: null + * port?: scalar|Param|null, // Default: 514 + * config?: list, + * members?: list, + * connection_string?: scalar|Param|null, + * timeout?: scalar|Param|null, + * time?: scalar|Param|null, // Default: 60 + * deduplication_level?: scalar|Param|null, // Default: 400 + * store?: scalar|Param|null, // Default: null + * connection_timeout?: scalar|Param|null, + * persistent?: bool|Param, + * message_type?: scalar|Param|null, // Default: 0 + * parse_mode?: scalar|Param|null, // Default: null + * disable_webpage_preview?: bool|Param|null, // Default: null + * disable_notification?: bool|Param|null, // Default: null + * split_long_messages?: bool|Param, // Default: false + * delay_between_messages?: bool|Param, // Default: false + * topic?: int|Param, // Default: null + * factor?: int|Param, // Default: 1 + * tags?: list, + * console_formatter_options?: mixed, // Default: [] + * formatter?: scalar|Param|null, + * nested?: bool|Param, // Default: false + * publisher?: string|array{ + * id?: scalar|Param|null, + * hostname?: scalar|Param|null, + * port?: scalar|Param|null, // Default: 12201 + * chunk_size?: scalar|Param|null, // Default: 1420 + * encoder?: "json"|"compressed_json"|Param, + * }, + * mongodb?: string|array{ + * id?: scalar|Param|null, // ID of a MongoDB\Client service + * uri?: scalar|Param|null, + * username?: scalar|Param|null, + * password?: scalar|Param|null, + * database?: scalar|Param|null, // Default: "monolog" + * collection?: scalar|Param|null, // Default: "logs" + * }, + * elasticsearch?: string|array{ + * id?: scalar|Param|null, + * hosts?: list, + * host?: scalar|Param|null, + * port?: scalar|Param|null, // Default: 9200 + * transport?: scalar|Param|null, // Default: "Http" + * user?: scalar|Param|null, // Default: null + * password?: scalar|Param|null, // Default: null + * }, + * index?: scalar|Param|null, // Default: "monolog" + * document_type?: scalar|Param|null, // Default: "logs" + * ignore_error?: scalar|Param|null, // Default: false + * redis?: string|array{ + * id?: scalar|Param|null, + * host?: scalar|Param|null, + * password?: scalar|Param|null, // Default: null + * port?: scalar|Param|null, // Default: 6379 + * database?: scalar|Param|null, // Default: 0 + * key_name?: scalar|Param|null, // Default: "monolog_redis" + * }, + * predis?: string|array{ + * id?: scalar|Param|null, + * host?: scalar|Param|null, + * }, + * from_email?: scalar|Param|null, + * to_email?: list, + * subject?: scalar|Param|null, + * content_type?: scalar|Param|null, // Default: null + * headers?: list, + * mailer?: scalar|Param|null, // Default: null + * email_prototype?: string|array{ + * id: scalar|Param|null, + * method?: scalar|Param|null, // Default: null + * }, + * verbosity_levels?: array{ + * VERBOSITY_QUIET?: scalar|Param|null, // Default: "ERROR" + * VERBOSITY_NORMAL?: scalar|Param|null, // Default: "WARNING" + * VERBOSITY_VERBOSE?: scalar|Param|null, // Default: "NOTICE" + * VERBOSITY_VERY_VERBOSE?: scalar|Param|null, // Default: "INFO" + * VERBOSITY_DEBUG?: scalar|Param|null, // Default: "DEBUG" + * }, + * channels?: string|array{ + * type?: scalar|Param|null, + * elements?: list, + * }, + * }>, + * } * @psalm-type ConfigType = array{ * imports?: ImportsConfig, * parameters?: ParametersConfig, @@ -1620,6 +1763,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * nelmio_cors?: NelmioCorsConfig, * api_platform?: ApiPlatformConfig, * lexik_jwt_authentication?: LexikJwtAuthenticationConfig, + * monolog?: MonologConfig, * "when@dev"?: array{ * imports?: ImportsConfig, * parameters?: ParametersConfig, @@ -1632,6 +1776,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * nelmio_cors?: NelmioCorsConfig, * api_platform?: ApiPlatformConfig, * lexik_jwt_authentication?: LexikJwtAuthenticationConfig, + * monolog?: MonologConfig, * }, * "when@prod"?: array{ * imports?: ImportsConfig, @@ -1645,6 +1790,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * nelmio_cors?: NelmioCorsConfig, * api_platform?: ApiPlatformConfig, * lexik_jwt_authentication?: LexikJwtAuthenticationConfig, + * monolog?: MonologConfig, * }, * "when@test"?: array{ * imports?: ImportsConfig, @@ -1658,6 +1804,7 @@ use Symfony\Component\Config\Loader\ParamConfigurator as Param; * nelmio_cors?: NelmioCorsConfig, * api_platform?: ApiPlatformConfig, * lexik_jwt_authentication?: LexikJwtAuthenticationConfig, + * monolog?: MonologConfig, * }, * ...&2 + exit 1 +fi + +REPO_OWNER="MALIO-DEV" +REPO_NAME="SIRH" +GITEA_API="https://gitea.malio.fr/api/v1" +DEPLOY_DIR="/var/www/sirh" + +if [ -f /etc/sirh-release-token ] && [ -z "${RELEASE_TOKEN:-}" ]; then + RELEASE_TOKEN="$(cat /etc/sirh-release-token)" +fi + +tmp_dir="$(mktemp -d)" +cleanup() { + rm -rf "$tmp_dir" +} +trap cleanup EXIT + +release_json="$tmp_dir/release.json" +curl_opts=(-sS) +if [ -n "${RELEASE_TOKEN:-}" ]; then + curl_opts+=(-H "Authorization: token ${RELEASE_TOKEN}") +fi +curl "${curl_opts[@]}" \ + "${GITEA_API}/repos/${REPO_OWNER}/${REPO_NAME}/releases/tags/${TAG}" \ + -o "$release_json" + +asset_url="$(python3 - "$release_json" <<'PY' +import json, sys +data = json.load(open(sys.argv[1], 'r')) +assets = data.get("assets", []) +for a in assets: + name = a.get("name", "") + if name.startswith("sirh-") and name.endswith(".tar.gz"): + print(a.get("browser_download_url", "")) + break +PY +)" + +if [ -z "$asset_url" ]; then + echo "Release asset not found for tag ${TAG}" >&2 + exit 1 +fi + +archive="$tmp_dir/artefact.tar.gz" +curl "${curl_opts[@]}" -L "$asset_url" -o "$archive" + +tar -xzf "$archive" -C "$tmp_dir" + +if command -v rsync >/dev/null 2>&1; then + rsync -a --delete --no-perms --no-owner --no-group \ + --exclude ".env" \ + --exclude ".env.local" \ + --exclude "config/jwt" \ + --exclude "var" \ + "$tmp_dir"/ "$DEPLOY_DIR"/ +else + cp -a "$tmp_dir"/. "$DEPLOY_DIR"/ +fi + +# Ensure Nginx can traverse the deploy path. +chmod o+rx "$(dirname "$DEPLOY_DIR")" "$DEPLOY_DIR" 2>/dev/null || true + +echo "Release ${TAG} deployed to ${DEPLOY_DIR}" + +if [ -f "${DEPLOY_DIR}/.env" ]; then + echo "Running migrations (if any)..." + php "${DEPLOY_DIR}/bin/console" doctrine:migrations:migrate --no-interaction --env=prod +else + echo "Skip migrations: ${DEPLOY_DIR}/.env not found" >&2 +fi diff --git a/symfony.lock b/symfony.lock index 3dc0692..3ac0e96 100644 --- a/symfony.lock +++ b/symfony.lock @@ -145,6 +145,18 @@ ".editorconfig" ] }, + "symfony/monolog-bundle": { + "version": "4.0", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "3.7", + "ref": "1b9efb10c54cb51c713a9391c9300ff8bceda459" + }, + "files": [ + "config/packages/monolog.yaml" + ] + }, "symfony/property-info": { "version": "8.0", "recipe": {