# 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 pdo pdo_sqlite 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 - cp .env.example .env || true - | cat > .env <<'EOF' APP_NAME=school_api APP_ENV=testing APP_KEY= APP_DEBUG=false APP_URL=http://localhost LOG_CHANNEL=stderr LOG_LEVEL=debug DB_CONNECTION=sqlite DB_DATABASE=${CI_PROJECT_DIR}/database/database.sqlite CACHE_DRIVER=array SESSION_DRIVER=array QUEUE_CONNECTION=sync MAIL_MAILER=array BROADCAST_CONNECTION=log FILESYSTEM_DISK=local JWT_SECRET=ci_dummy_secret_not_for_production EOF - mkdir -p database storage/framework/cache storage/framework/sessions storage/framework/views bootstrap/cache - touch database/database.sqlite - php artisan key:generate --force - php artisan config:clear composer_validate: extends: .php_laravel_job stage: validate script: - composer validate --strict - php -v - php artisan --version laravel_pint: extends: .php_laravel_job stage: validate script: - vendor/bin/pint --test phpunit: extends: .php_laravel_job stage: test script: - php artisan migrate --force - php artisan test --testsuite=Feature --no-interaction - php artisan test --testsuite=Unit --no-interaction artifacts: when: always expire_in: 7 days paths: - storage/logs/ build_frontend: image: node:22-alpine stage: build before_script: - npm ci script: - npm run build artifacts: expire_in: 7 days paths: - public/build/ composer_audit: extends: .php_laravel_job stage: security script: - composer audit --locked --no-interaction npm_audit: image: node:22-alpine stage: security before_script: - npm ci script: - npm audit --audit-level=high allow_failure: true secret_detection_basic: image: alpine:3.20 stage: security before_script: - apk add --no-cache git grep script: - | echo "Scanning for obvious committed secrets..." ! 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 \ . 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