# GitLab CI for Laravel 12 # Save this file as: .gitlab-ci.yml workflow: rules: - if: '$CI_PIPELINE_SOURCE == "push"' - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_TAG' stages: - validate - test - build - security variables: APP_ENV: testing APP_DEBUG: "false" LOG_CHANNEL: stderr CACHE_DRIVER: array SESSION_DRIVER: array QUEUE_CONNECTION: sync DB_CONNECTION: sqlite DB_DATABASE: "$CI_PROJECT_DIR/database/database.sqlite" COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.composer-cache" NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm-cache" cache: key: files: - composer.lock - package-lock.json paths: - .composer-cache/ - .npm-cache/ - vendor/ - node_modules/ .php_laravel_job: image: php:8.3-cli before_script: - apt-get update - apt-get install -y --no-install-recommends git unzip curl libzip-dev libpng-dev libonig-dev libxml2-dev libsqlite3-dev - docker-php-ext-install mbstring zip gd - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - php composer-setup.php --install-dir=/usr/local/bin --filename=composer - rm composer-setup.php - composer install --prefer-dist --no-interaction --no-progress - | cat > .env <&1 | tee reports/composer-validate.log' - bash -o pipefail -c 'php -v 2>&1 | tee reports/php-version.log' - bash -o pipefail -c 'php artisan --version 2>&1 | tee reports/artisan-version.log' artifacts: when: always expire_in: 7 days paths: - reports/ - storage/logs/ laravel_pint: extends: .php_laravel_job stage: validate script: - mkdir -p reports - bash -o pipefail -c 'vendor/bin/pint --test 2>&1 | tee reports/pint.log' artifacts: when: always expire_in: 7 days paths: - reports/ - storage/logs/ phpunit: extends: .php_laravel_job stage: test script: - mkdir -p reports - bash -o pipefail -c 'php artisan migrate --force 2>&1 | tee reports/migrate.log' - bash -o pipefail -c 'php artisan test --testsuite=Feature --log-junit reports/phpunit-feature.xml 2>&1 | tee reports/phpunit-feature.log' - bash -o pipefail -c 'php artisan test --testsuite=Unit --log-junit reports/phpunit-unit.xml 2>&1 | tee reports/phpunit-unit.log' artifacts: when: always expire_in: 7 days reports: junit: - reports/phpunit-feature.xml - reports/phpunit-unit.xml paths: - reports/ - storage/logs/ build_frontend: image: node:22-alpine stage: build before_script: - npm ci script: - mkdir -p reports - sh -c 'npm run build 2>&1 | tee reports/npm-build.log' artifacts: when: always expire_in: 7 days paths: - public/build/ - reports/ composer_audit: extends: .php_laravel_job stage: security script: - mkdir -p reports - bash -o pipefail -c 'composer audit --locked --no-interaction 2>&1 | tee reports/composer-audit.log' artifacts: when: always expire_in: 7 days paths: - reports/ - storage/logs/ npm_audit: image: node:22-alpine stage: security before_script: - npm ci script: - mkdir -p reports - sh -c 'npm audit --audit-level=high 2>&1 | tee reports/npm-audit.log' artifacts: when: always expire_in: 7 days paths: - reports/ allow_failure: true secret_detection_basic: image: alpine:3.20 stage: security before_script: - apk add --no-cache git grep script: - mkdir -p reports - | echo "Scanning for obvious committed secrets..." | tee reports/secret-detection-basic.log ! grep -RInE "(APP_KEY=base64:|DB_PASSWORD=.+|JWT_SECRET=.+|MAIL_PASSWORD=.+|PAYPAL_(CLIENT|SECRET|MODE)|AKIA[0-9A-Z]{16}|-----BEGIN (RSA|OPENSSH|PRIVATE) KEY-----)" \ --exclude-dir=.git \ --exclude-dir=vendor \ --exclude-dir=node_modules \ --exclude=.env.example \ --exclude=.env.prod.example \ . 2>&1 | tee -a reports/secret-detection-basic.log artifacts: when: always expire_in: 7 days paths: - reports/ allow_failure: false # Optional GitLab-native security scanners. # These run only if your GitLab tier/project supports the templates. include: - template: Jobs/SAST.gitlab-ci.yml - template: Jobs/Secret-Detection.gitlab-ci.yml - template: Jobs/Dependency-Scanning.gitlab-ci.yml