spec: inputs: phpversion: type: string default: "8.1" mariadbversion: type: string default: "10.2.7" mysqlversion: type: string default: "8.0" --- workflow: rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_REF_PROTECTED == "true"' image: studip/studip:tests-php$[[ inputs.phpversion ]] variables: FF_NETWORK_PER_BUILD: 1 GIT_DEPTH: 1 MYSQL_RANDOM_ROOT_PASSWORD: "true" MYSQL_DATABASE: studip_db MYSQL_USER: studip_user MYSQL_PASSWORD: studip_password MYSQL_HOST: mariadb DEMO_DATA: "true" MAIL_TRANSPORT: debug PHPSTAN_LEVEL: 0 # Optimize caching FF_USE_FASTZIP: "true" CACHE_COMPRESSION_LEVEL: "fast" # Use faster docker driver DOCKER_DRIVER: overlay2 # Images NODE_IMAGE: node:18 # Directories CACHE_DIR: .caches REPORT_DIR: .reports # Set npm cache directory npm_config_cache: $CI_PROJECT_DIR/.npm stages: - noop - build - checks - analyse - test - cache - packaging - release .scripts: mkdir-caches: - mkdir -p $CACHE_DIR mkdir-reports: - mkdir -p $REPORT_DIR install-composer: - make composer-dev configure-studip: - !reference [.scripts, install-composer] - cp docker/studip/config_local.php config/config_local.inc.php - cp config/config.inc.php.dist config/config.inc.php initialize-studip-database: - !reference [.scripts, configure-studip] - chmod +x .gitlab/scripts/install_db.sh - .gitlab/scripts/install_db.sh - cli/studip migrate .caches: composer: &composer-cache key: files: - composer.lock fallback_keys: - composer-default paths: - composer/ policy: pull-push npm: &npm-cache key: files: - package-lock.json fallback_keys: - npm-default paths: - .npm policy: pull-push .definitions: mariadb-service: &mariadb-service - name: mariadb:$[[ inputs.mariadbversion ]] command: [ "--sql_mode=","--character-set-client=utf8","--character-set-server=utf8","--collation-server=utf8_unicode_ci"] mysql-service: &mysql-service - name: mysql:$[[ inputs.mysqlversion ]] command: [ "--sql_mode=","--character-set-server=utf8mb4","--collation-server=utf8mb4_general_ci"] php-changed: &php-changed - changes: paths: - "**/*.php" - composer.lock compare_to: 'refs/heads/main' css-changed: &css-changed - changes: paths: - "resources/assets/stylesheets/**/*" - package-lock.json compare_to: 'refs/heads/main' js-changed: &js-changed - changes: paths: - "resources/assets/javascripts/**/*" - "resources/vue/**/*" - package-lock.json compare_to: 'refs/heads/main' noop: stage: noop script: - echo "No relevant changes detected - skipping the rest of the pipeline." rules: - changes: paths: - '**/*.php' - composer.lock - 'resources/vue/**/*' - 'resources/assets/**/*' - package-lock.json when: never - when: always build-composer: stage: build needs: [] rules: *php-changed interruptible: true variables: COMPOSER_CACHE: $CACHE_DIR/composer-cache before_script: - mkdir -p $COMPOSER_CACHE script: - composer install cache: - <<: *composer-cache lint-php: stage: checks needs: [build-composer] rules: *php-changed variables: CACHE_LOCATION: $CACHE_DIR/phplint-cache PHPLINT_JSON_REPORT: $REPORT_DIR/phplint-report.json PHPLINT_CODE_QUALITY_REPORT: $REPORT_DIR/phplint-codequality.json interruptible: true cache: - <<: *composer-cache - key: "$CI_JOB_NAME_SLUG" paths: - $CACHE_LOCATION before_script: - !reference [.scripts, mkdir-caches] - !reference [.scripts, mkdir-reports] - !reference [.scripts, install-composer] - source .gitlab/scripts/ci-helpers.sh script: - COMPOSER_MEMORY_LIMIT=-1 composer exec phplint -- $(get_changed_files '*.php') --output=$PHPLINT_JSON_REPORT --format=json --cache=$CACHE_LOCATION after_script: - ./.gitlab/scripts/convert-phplint-report $PHPLINT_JSON_REPORT > $PHPLINT_CODE_QUALITY_REPORT artifacts: reports: codequality: $PHPLINT_CODE_QUALITY_REPORT lint-php-8.3: image: studip/studip:tests-php8.3 stage: checks needs: [build-composer] rules: *php-changed variables: CACHE_LOCATION: $CACHE_DIR/phplint-cache PHPLINT_JSON_REPORT: $REPORT_DIR/phplint-report-8.3.json PHPLINT_CODE_QUALITY_REPORT: $REPORT_DIR/phplint-codequality-8.3.json interruptible: true cache: - <<: *composer-cache - key: "$CI_JOB_NAME_SLUG" paths: - $CACHE_LOCATION before_script: - !reference [.scripts, mkdir-caches] - !reference [.scripts, mkdir-reports] - !reference [.scripts, install-composer] - source .gitlab/scripts/ci-helpers.sh script: - COMPOSER_MEMORY_LIMIT=-1 composer exec phplint -- $(get_changed_files '*.php') --output=$PHPLINT_JSON_REPORT --format=json --cache=$CACHE_LOCATION after_script: - ./.gitlab/scripts/convert-phplint-report $PHPLINT_JSON_REPORT > $PHPLINT_CODE_QUALITY_REPORT artifacts: reports: codequality: $PHPLINT_CODE_QUALITY_REPORT lint-js: stage: checks needs: [] rules: *js-changed image: $NODE_IMAGE variables: CACHE_LOCATION: $CACHE_DIR/eslint-cache ESLINT_CODE_QUALITY_REPORT: $REPORT_DIR/eslint-codequality.json cache: - <<: *npm-cache - key: "$CI_JOB_NAME_SLUG" paths: - $CACHE_LOCATION policy: pull-push interruptible: true before_script: - !reference [.scripts, mkdir-reports] - !reference [.scripts, mkdir-caches] - npm ci --prefer-offline - source .gitlab/scripts/ci-helpers.sh script: - npx eslint $(get_changed_files '*.js' '*.ts' '*.vue') --config eslint.config.mjs --cache --cache-location $CACHE_LOCATION --format gitlab artifacts: reports: codequality: $ESLINT_CODE_QUALITY_REPORT lint-css: stage: checks needs: [] rules: *css-changed image: $NODE_IMAGE variables: CACHE_LOCATION: $CACHE_DIR/stylelint-cache STYLELINT_CODE_QUALITY_REPORT: $REPORT_DIR/stylelint-codequality.json interruptible: true cache: - <<: *npm-cache - key: "$CI_JOB_NAME_SLUG" paths: - $CACHE_LOCATION policy: pull-push before_script: - !reference [.scripts, mkdir-reports] - !reference [.scripts, mkdir-caches] - npm ci --prefer-offline - source .gitlab/scripts/ci-helpers.sh script: - npx stylelint $(get_changed_files '*.scss' '*.css') --cache --cache-location $CACHE_LOCATION --custom-formatter=node_modules/stylelint-formatter-gitlab --output-file $STYLELINT_CODE_QUALITY_REPORT artifacts: reports: codequality: $STYLELINT_CODE_QUALITY_REPORT phpstan: stage: analyse needs: [build-composer] rules: *php-changed variables: CACHE_LOCATION: $CACHE_DIR/phpstan PHPSTAN_CODE_QUALITY_REPORT: $REPORT_DIR/phpstan-codequality.json interruptible: true cache: - <<: *composer-cache - key: "$CI_JOB_NAME_SLUG" paths: - $CACHE_LOCATION before_script: - !reference [.scripts, mkdir-caches] - !reference [.scripts, mkdir-reports] - !reference [.scripts, install-composer] - source .gitlab/scripts/ci-helpers.sh - | cat < phpstan.neon includes: - phpstan.neon.dist parameters: tmpDir: $CACHE_LOCATION EOF script: - RELEVANT=$(get_changed_files '*.php' | grep -vE '^lib/ilias_interface/studip_referrer_.*\.php$' || true) - | if [ -z "$RELEVANT" ]; then echo "No relevant files changed - skipping PHPStan" exit 0 fi composer/bin/phpstan analyse $RELEVANT --memory-limit=1G --no-progress --level=$PHPSTAN_LEVEL --error-format=gitlab > $PHPSTAN_CODE_QUALITY_REPORT after_script: - rm phpstan.neon artifacts: reports: codequality: $PHPSTAN_CODE_QUALITY_REPORT test-unit: stage: test needs: [lint-php] rules: *php-changed variables: PHPUNIT_XML_REPORT: $REPORT_DIR/phpunit-report.xml cache: <<: *composer-cache policy: pull allow_failure: false interruptible: true before_script: - !reference [.scripts, mkdir-reports] - !reference [.scripts, configure-studip] script: - 'composer/bin/codecept run unit --xml=$PHPUNIT_XML_REPORT -o "paths: output: ."' after_script: - sed -i "s%$PWD/%%" $PHPUNIT_XML_REPORT artifacts: reports: junit: $PHPUNIT_XML_REPORT test-jest: stage: test needs: [lint-js] rules: *js-changed image: $NODE_IMAGE variables: JS_TEST_REPORT: $REPORT_DIR/jest.xml cache: - <<: *npm-cache interruptible: true before_script: - !reference [.scripts, mkdir-reports] - npm install script: - JEST_JUNIT_OUTPUT_FILE="$JS_TEST_REPORT" npx jest tests/jest/ --ci --reporters=default --reporters=jest-junit artifacts: reports: junit: $JS_TEST_REPORT test-functional: stage: test needs: [lint-php] rules: *php-changed variables: FUNCTIONAL_XML_REPORT: $REPORT_DIR/functional-report.xml FUNCTIONAL_CODE_QUALITY_REPORT: $REPORT_DIR/functional-codequality.json MYSQL_HOST: mysql cache: <<: *composer-cache policy: pull services: - !reference [.definitions, mysql-service] allow_failure: false interruptible: true before_script: - !reference [.scripts, mkdir-reports] - !reference [.scripts, initialize-studip-database] script: - 'composer/bin/codecept run functional --xml=$FUNCTIONAL_XML_REPORT -o "paths: output: ."' after_script: - sed -i "s%$PWD/%%" $FUNCTIONAL_XML_REPORT artifacts: reports: junit: $FUNCTIONAL_XML_REPORT test-jsonapi: stage: test needs: [lint-php] rules: *php-changed cache: <<: *composer-cache policy: pull services: - !reference [.definitions, mariadb-service] variables: JSONAPI_XML_REPORT: $REPORT_DIR/jsonapi-report.xml interruptible: true before_script: - !reference [.scripts, mkdir-reports] - !reference [.scripts, initialize-studip-database] script: - 'composer/bin/codecept run jsonapi --xml=$JSONAPI_XML_REPORT -o "paths: output: ."' after_script: - sed -i "s%$PWD/%%" $JSONAPI_XML_REPORT artifacts: reports: junit: $JSONAPI_XML_REPORT test-assets: stage: test needs: [] rules: - !reference [.definitions, js-changed] - !reference [.definitions, css-changed] image: $NODE_IMAGE cache: - <<: *npm-cache interruptible: true before_script: - npm install script: - npm run webpack-dev test-e2e: stage: test # needs: [lint-css, lint-js, lint-php] image: mcr.microsoft.com/playwright:v1.33.0-jammy services: - name: mariadb command: ["--sql_mode="] variables: PHP_WEBSERVER_URL: localhost:65432 E2E_REPORT: $REPORT_DIR/e2e.xml interruptible: true when: manual cache: - !reference [.caches, composer] - !reference [.caches, npm] before_script: - mkdir ./bin - apt-get update - apt -y install software-properties-common - add-apt-repository ppa:ondrej/php - apt-get update - DEBIAN_FRONTEND=noninteractive apt-get -yq install make zip unzip mariadb-client php7.4 libapache2-mod-php7.4 php7.4-common php7.4-curl php7.4-mbstring php7.4-xmlrpc php7.4-mysql php7.4-gd php7.4-xml php7.4-intl php7.4-ldap php7.4-imagick php7.4-json php7.4-cli - echo "short_open_tag=On" >> /etc/php/7.4/php.ini - echo "short_open_tag=On" >> /etc/php/7.4/cli/php.ini - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" - php composer-setup.php --install-dir=./bin --filename=composer - export PATH="./bin:$PATH" - php -r "unlink('composer-setup.php');" - !reference [.scripts, mkdir-reports] - !reference [.scripts, initialize-studip-database] - ./cli/studip config:set SHOW_TERMS_ON_FIRST_LOGIN 0 - npm install playwright - npm ci - npx playwright install --with-deps script: - php -S $PHP_WEBSERVER_URL -t public -q & - PHP_SERVER_PID=$! - PLAYWRIGHT_JUNIT_OUTPUT_NAME="$E2E_REPORT" PLAYWRIGHT_BASE_URL="http://$PHP_WEBSERVER_URL" npx playwright test --reporter=junit --grep-invert a11y - kill -3 $PHP_SERVER_PID artifacts: reports: junit: $E2E_REPORT packaging: stage: packaging cache: [] rules: - if: $CI_COMMIT_TAG before_script: - echo GE_JOB_ID=$CI_JOB_ID >> .packaging.env - mkdir .pkg script: - echo 'Running packaging job' - make build clean-npm - zip -r9 .pkg/studip-$CI_COMMIT_TAG.zip * - tar -czf .pkg/studip-$CI_COMMIT_TAG.tar.gz * artifacts: name: 'Stud.IP-Release-$CI_COMMIT_TAG' paths: - .pkg/studip-$CI_COMMIT_TAG.zip - .pkg/studip-$CI_COMMIT_TAG.tar.gz reports: dotenv: .packaging.env expire_in: never build_image: image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] stage: build when: manual interruptible: true variables: IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME script: - /kaniko/executor --context=dir://${CI_PROJECT_DIR} --dockerfile ${CI_PROJECT_DIR}/docker/studip/Dockerfile --destination ${IMAGE_TAG} --cache=true release: stage: release image: studip/release-cli cache: [] rules: - if: $CI_COMMIT_TAG script: - echo 'Running release job' needs: - job: packaging artifacts: true release: name: "$CI_COMMIT_TAG" description: "https://gitlab.studip.de/studip/studip/-/blob/${CI_COMMIT_TAG}/ChangeLog.md" tag_name: "$CI_COMMIT_TAG" assets: links: - name: "studip-$CI_COMMIT_TAG.zip" url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${GE_JOB_ID}/artifacts/.pkg/studip-$CI_COMMIT_TAG.zip" link_type: package - name: "studip-$CI_COMMIT_TAG.tar.gz" url: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${GE_JOB_ID}/artifacts/.pkg/studip-$CI_COMMIT_TAG.tar.gz" link_type: package