diff --git a/.circleci/config.yml b/.circleci/config.yml index f8f76c5ca..3ac59815e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -108,6 +108,106 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:3.1.0 . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + #;< TOOL_ESLINT_STYLELINT + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + #;> TOOL_ESLINT_STYLELINT + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + #;< TOOL_PHPCS + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + #;> TOOL_PHPCS + + #;< TOOL_PHPSTAN + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + #;> TOOL_PHPSTAN + + #;< TOOL_RECTOR + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + #;> TOOL_RECTOR + + #;< TOOL_PHPMD + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + #;> TOOL_PHPMD + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + #;< TOOL_BEHAT + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + #;> TOOL_BEHAT + + #;< TOOL_ESLINT_STYLELINT + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + #;> TOOL_ESLINT_STYLELINT + + #;< DRUPAL_THEME + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + #;> DRUPAL_THEME + #;< !PROVISION_TYPE_PROFILE # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump @@ -245,20 +345,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:3.1.0 . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -277,81 +363,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - #;< TOOL_ESLINT_STYLELINT - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - #;> TOOL_ESLINT_STYLELINT - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - #;< TOOL_PHPCS - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_PHPCS - - #;< TOOL_PHPSTAN - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_PHPSTAN - - #;< TOOL_RECTOR - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_RECTOR - - #;< TOOL_PHPMD - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_PHPMD - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - #;< TOOL_BEHAT - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_BEHAT - - #;< TOOL_ESLINT_STYLELINT - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_ESLINT_STYLELINT - - #;< DRUPAL_THEME - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - #;> DRUPAL_THEME - run: name: Provision site @@ -578,6 +589,10 @@ workflows: tags: only: /.*/ #;> !PROVISION_TYPE_PROFILE + - lint: + filters: + tags: + only: /.*/ - build: #;< !PROVISION_TYPE_PROFILE requires: @@ -590,6 +605,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -608,6 +624,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.circleci/vortex-test-common.yml b/.circleci/vortex-test-common.yml index f5bc22c8e..aaace6957 100644 --- a/.circleci/vortex-test-common.yml +++ b/.circleci/vortex-test-common.yml @@ -211,20 +211,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:3.1.0 . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -243,81 +229,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - #;< TOOL_ESLINT_STYLELINT - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - #;> TOOL_ESLINT_STYLELINT - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - #;< TOOL_PHPCS - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_PHPCS - - #;< TOOL_PHPSTAN - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_PHPSTAN - - #;< TOOL_RECTOR - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_RECTOR - - #;< TOOL_PHPMD - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_PHPMD - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - #;< TOOL_BEHAT - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_BEHAT - - #;< TOOL_ESLINT_STYLELINT - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - #;> TOOL_ESLINT_STYLELINT - - #;< DRUPAL_THEME - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - #;> DRUPAL_THEME - run: name: Provision site diff --git a/.github/workflows/build-test-deploy.yml b/.github/workflows/build-test-deploy.yml index 5ac7ef6cc..221a5800b 100644 --- a/.github/workflows/build-test-deploy.yml +++ b/.github/workflows/build-test-deploy.yml @@ -53,6 +53,122 @@ defaults: shell: bash jobs: + + lint: + runs-on: ubuntu-latest + #;< !PROVISION_TYPE_PROFILE + if: ${{ github.event_name != 'schedule' && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} + #;> !PROVISION_TYPE_PROFILE + + container: + # https://hub.docker.com/r/drevops/ci-runner + image: drevops/ci-runner:26.2.0@sha256:fe1561c2984a1023e84eebe6461056b0b55afedbb2512e6c2c7f19aca6beb398 + env: + PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }} + VORTEX_CONTAINER_REGISTRY_USER: ${{ secrets.VORTEX_CONTAINER_REGISTRY_USER }} + VORTEX_CONTAINER_REGISTRY_PASS: ${{ secrets.VORTEX_CONTAINER_REGISTRY_PASS }} + TZ: ${{ vars.TZ || 'UTC' }} + TERM: xterm-256color + VORTEX_DEBUG: ${{ vars.VORTEX_DEBUG }} + + steps: + - name: Preserve $HOME set in the container + run: echo HOME=/root >> "$GITHUB_ENV" # https://github.com/actions/runner/issues/863 + + - name: Check out code + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Process the codebase to run in CI + run: find . -name "docker-compose.yml" -print0 | xargs -0 -I {} sh -c "sed -i -e '/###/d' {} && sed -i -e 's/##//' {}" + + - name: Load environment variables from .env + run: t=$(mktemp) && export -p >"${t}" && set -a && . ./.env && set +a && . "${t}" && env >> "$GITHUB_ENV" + + - name: Validate Composer configuration + run: composer validate --strict + continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE == '1' }} + + - name: Login to container registry + run: ./scripts/vortex/login-container-registry.sh + + - name: Lint Dockerfiles with Hadolint + run: | + find .docker -name 'Dockerfile' -o -name '*.dockerfile' | while read -r file; do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint + done + continue-on-error: ${{ vars.VORTEX_CI_HADOLINT_IGNORE_FAILURE == '1' }} + + - name: Lint Docker Compose files with DCLint + run: docker run --rm -v "${PWD}":/app zavoloklom/dclint:3.1.0 . + continue-on-error: ${{ vars.VORTEX_CI_DCLINT_IGNORE_FAILURE == '1' }} + + - name: Build stack + run: docker compose up --no-deps --detach cli + + - name: Install development dependencies + run: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + #;< TOOL_ESLINT_STYLELINT + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + #;> TOOL_ESLINT_STYLELINT + + - name: Audit Composer packages + run: docker compose exec -T cli composer audit + continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE == '1' }} + + - name: Validate Composer configuration is normalized + run: docker compose exec -T cli composer normalize --dry-run + continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} + + #;< TOOL_PHPCS + - name: Lint code with PHPCS + run: docker compose exec -T cli vendor/bin/phpcs + continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} + #;> TOOL_PHPCS + + #;< TOOL_PHPSTAN + - name: Lint code with PHPStan + run: docker compose exec -T cli vendor/bin/phpstan + continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} + #;> TOOL_PHPSTAN + + #;< TOOL_RECTOR + - name: Lint code with Rector + run: docker compose exec -T cli vendor/bin/rector --dry-run + continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} + #;> TOOL_RECTOR + + #;< TOOL_PHPMD + - name: Lint code with PHPMD + run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml + continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} + #;> TOOL_PHPMD + + - name: Lint code with Twig CS Fixer + run: docker compose exec -T cli vendor/bin/twig-cs-fixer + continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} + + #;< TOOL_BEHAT + - name: Lint code with Gherkin Lint + run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features + continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} + #;> TOOL_BEHAT + + #;< TOOL_ESLINT_STYLELINT + - name: Lint module code with NodeJS linters + run: docker compose exec -T cli bash -c "yarn run lint" + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} + #;> TOOL_ESLINT_STYLELINT + + #;< DRUPAL_THEME + - name: Lint theme code with NodeJS linters + if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} + run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} + #;> DRUPAL_THEME + #;< !PROVISION_TYPE_PROFILE database: runs-on: ubuntu-latest @@ -168,8 +284,8 @@ jobs: build: runs-on: ubuntu-latest - needs: database #;< !PROVISION_TYPE_PROFILE + needs: database if: ${{ github.event_name != 'schedule' && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} #;> !PROVISION_TYPE_PROFILE @@ -248,19 +364,6 @@ jobs: - name: Login to container registry run: ./scripts/vortex/login-container-registry.sh - - name: Lint Dockerfiles with Hadolint - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: | - find .docker -name 'Dockerfile' -o -name '*.dockerfile' | while read -r file; do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint - done - continue-on-error: ${{ vars.VORTEX_CI_HADOLINT_IGNORE_FAILURE == '1' }} - - - name: Lint Docker Compose files with DCLint - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker run --rm -v "${PWD}":/app zavoloklom/dclint:3.1.0 . - continue-on-error: ${{ vars.VORTEX_CI_DCLINT_IGNORE_FAILURE == '1' }} - - name: Build stack run: docker compose up --detach && docker builder prune --all --force @@ -277,72 +380,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - #;< TOOL_ESLINT_STYLELINT - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - #;> TOOL_ESLINT_STYLELINT - - - name: Audit Composer packages - run: docker compose exec -T cli composer audit - continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE == '1' }} - - - name: Validate Composer configuration is normalized - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli composer normalize --dry-run - continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} - - #;< TOOL_PHPCS - - name: Lint code with PHPCS - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpcs - continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} - #;> TOOL_PHPCS - - #;< TOOL_PHPSTAN - - name: Lint code with PHPStan - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpstan - continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} - #;> TOOL_PHPSTAN - - #;< TOOL_RECTOR - - name: Lint code with Rector - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/rector --dry-run - continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} - #;> TOOL_RECTOR - - #;< TOOL_PHPMD - - name: Lint code with PHPMD - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml - continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} - #;> TOOL_PHPMD - - - name: Lint code with Twig CS Fixer - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/twig-cs-fixer - continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} - - #;< TOOL_BEHAT - - name: Lint code with Gherkin Lint - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features - continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - #;> TOOL_BEHAT - - #;< TOOL_ESLINT_STYLELINT - - name: Lint module code with NodeJS linters - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - #;> TOOL_ESLINT_STYLELINT - - #;< DRUPAL_THEME - - name: Lint theme code with NodeJS linters - if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - #;> DRUPAL_THEME - name: Provision site run: | @@ -459,7 +496,7 @@ jobs: #;< DEPLOYMENT deploy: runs-on: ubuntu-latest - needs: build + needs: [build, lint] #;< !PROVISION_TYPE_PROFILE if: ${{ github.event_name != 'schedule' && !startsWith(github.head_ref || github.ref_name, 'deps/') && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} #;> !PROVISION_TYPE_PROFILE diff --git a/.vortex/docs/content/_code-lifecycle.mdx b/.vortex/docs/content/_code-lifecycle.mdx index 34c2c456b..62dbb73b3 100644 --- a/.vortex/docs/content/_code-lifecycle.mdx +++ b/.vortex/docs/content/_code-lifecycle.mdx @@ -1,516 +1,77 @@ -```mermaid -%%============================================================================== -%% Vortex Code Lifecycle Diagram -%% Naming Convention: -%% - All identifiers use UPPER_SNAKE_CASE with hierarchical prefixes -%% - Subgraphs: SUBGRAPH_PARENT_CHILD (e.g., SUBGRAPH_CI_BUILD_JOB_ASSEMBLY_PHASE) -%% - Regular nodes: PARENT_CHILD_NODE, no SUBGRAPH_ prefix (e.g., CI_BUILD_JOB_ASSEMBLY_PHASE_BUILD_DOCKER) -%%============================================================================== - -%%{init: {'flowchart': {'curve': 'linear'}}}%% -flowchart TB - subgraph SUBGRAPH_LOCAL["Local Development"] - direction LR - LOCAL_DEV["Developer writes code"] - --> LOCAL_BUILD_LOCAL["Build and test locally"] - --> LOCAL_COMMIT["Commit changes"] - end - - subgraph SUBGRAPH_GIT["Git Repository"] - direction LR - GIT_PUSH["Push to remote branch"] - --> GIT_PR["Open/Update Pull Request"] - end - - %% CI Pipeline (Outer Box) - subgraph SUBGRAPH_CI["CI Pipeline"] - direction TB - - subgraph SUBGRAPH_CI_DATABASE_JOB_NIGHTLY["Database Job (Nightly)"] - direction LR - CI_DATABASE_JOB_NIGHTLY_SCHEDULE["Scheduled trigger"] - --> CI_DATABASE_JOB_NIGHTLY_DB_PROD_DOWNLOAD["Download production
database"] - --> CI_DATABASE_JOB_NIGHTLY_DB_SANITIZE_NIGHTLY["Sanitize database
Remove sensitive data"] - --> CI_DATABASE_JOB_NIGHTLY_DB_CACHE_NIGHTLY["Store database cache"] - end - - subgraph SUBGRAPH_CI_DATABASE_JOB["Database Job"] - direction LR - - CI_DATABASE_JOB_DB_CACHE_CHECK{"Nightly database
cache exists?"} - CI_DATABASE_JOB_DB_CACHE_SUCCESS["Pipeline Success"] - - CI_DATABASE_JOB_DB_DOWNLOAD_NEW["Download production
database"] - CI_DATABASE_JOB_DB_SANITIZE["Sanitize database
Remove sensitive data"] - CI_DATABASE_JOB_DB_STORE_CACHE["Store database cache"] - end - - subgraph SUBGRAPH_CI_BUILD_JOB["Build Job"] - direction TB - - subgraph SUBGRAPH_CI_BUILD_JOB_ASSEMBLY_PHASE["Code assembly"] - direction LR - CI_BUILD_JOB_ASSEMBLY_PHASE_BUILD_DOCKER["Build Docker
image"] - --> CI_BUILD_JOB_ASSEMBLY_PHASE_COMPOSER["Install
Composer deps"] - --> CI_BUILD_JOB_ASSEMBLY_PHASE_NPM["Install
NPM deps"] - --> CI_BUILD_JOB_ASSEMBLY_PHASE_BUILD_ASSETS["Build front-end
assets"] - end - - subgraph SUBGRAPH_CI_BUILD_JOB_PROVISION_PHASE["Website setup"] - direction LR - CI_BUILD_JOB_PROVISION_PHASE_DB_DOWNLOAD["Import cached
database"] - --> CI_BUILD_JOB_PROVISION_PHASE_PROVISION_OPS_PROV_DEPLOY["Run drush deploy"] - --> CI_BUILD_JOB_PROVISION_PHASE_PROVISION_OPS_PROV_CUSTOM["Run custom
scripts
"] - end - - subgraph SUBGRAPH_CI_BUILD_JOB_TEST_PHASE["Testing"] - direction LR - CI_BUILD_JOB_TEST_PHASE_COMPOSER_CHECK["Composer checks
Check lock
Audit dependencies"] - --> CI_BUILD_JOB_TEST_PHASE_LINT["Coding standards
PHPCS, PHPStan, Rector, PHPMD, ESLint, Twig CS Fixer"] - --> CI_BUILD_JOB_TEST_PHASE_UNIT["PHPUnit
tests
"] - --> CI_BUILD_JOB_TEST_PHASE_BEHAT["Behat
tests
"] - end - end - - subgraph SUBGRAPH_CI_DEPLOYMENT_JOB["Deployment Job"] - direction LR - CI_DEPLOYMENT_JOB_WEBHOOK["Webhook
Call webhook URL"] - ~~~ CI_DEPLOYMENT_JOB_ARTIFACT["Artifact
Package Git artifact"] - ~~~ CI_DEPLOYMENT_JOB_LAGOON["Lagoon
Call Lagoon webhook"] - ~~~ CI_DEPLOYMENT_JOB_DOCKER["Docker
Create container image"] - end - end - - subgraph SUBGRAPH_HOSTING["Hosting Platform"] - direction LR - - HOSTING_ENV_DECISION{"Environment
exists?"} - HOSTING_NEW_DB_SYNC["Sync database
from production"] - - HOSTING_PROVISION_OPS_PROV_DEPLOY["Run drush deploy"] - --> HOSTING_PROVISION_OPS_PROV_CUSTOM["Run custom
scripts
"] - --> HOSTING_SEND_NOTIFICATIONS["Send notifications
Email, Slack, NewRelic"] - end - - subgraph SUBGRAPH_ENVIRONMENTS["Available Environments"] - direction LR - ENVIRONMENTS_PR_ENV["PR Environment
Auto-removed"] - ~~~ ENVIRONMENTS_DEV_ENV["Dev
develop branch"] - ~~~ ENVIRONMENTS_STAGE_ENV["Staging
main branch"] - ~~~ ENVIRONMENTS_PROD_ENV["Production
production branch or tag"] - end - - %% Main Flow - Only OUTER Box to OUTER Box Connections - SUBGRAPH_LOCAL --> SUBGRAPH_GIT - SUBGRAPH_GIT --> SUBGRAPH_CI - SUBGRAPH_CI --> SUBGRAPH_HOSTING - SUBGRAPH_HOSTING --> SUBGRAPH_ENVIRONMENTS - - %% Internal flows within CI Pipeline - SUBGRAPH_CI_DATABASE_JOB_NIGHTLY -.->|Provides cached
database| SUBGRAPH_CI_DATABASE_JOB - - %% Database Job internal flow - CI_DATABASE_JOB_DB_CACHE_CHECK -->|Yes| CI_DATABASE_JOB_DB_CACHE_SUCCESS - CI_DATABASE_JOB_DB_CACHE_CHECK -->|No| CI_DATABASE_JOB_DB_DOWNLOAD_NEW - CI_DATABASE_JOB_DB_DOWNLOAD_NEW --> CI_DATABASE_JOB_DB_SANITIZE - - CI_DATABASE_JOB_DB_SANITIZE --> CI_DATABASE_JOB_DB_STORE_CACHE - - SUBGRAPH_CI_DATABASE_JOB --> SUBGRAPH_CI_BUILD_JOB - SUBGRAPH_CI_BUILD_JOB_ASSEMBLY_PHASE --> SUBGRAPH_CI_BUILD_JOB_PROVISION_PHASE - SUBGRAPH_CI_BUILD_JOB_PROVISION_PHASE --> SUBGRAPH_CI_BUILD_JOB_TEST_PHASE - SUBGRAPH_CI_BUILD_JOB --> SUBGRAPH_CI_DEPLOYMENT_JOB - - %% Internal flows within Hosting Platform - HOSTING_ENV_DECISION -->|No| HOSTING_NEW_DB_SYNC - HOSTING_NEW_DB_SYNC --> HOSTING_PROVISION_OPS_PROV_DEPLOY - HOSTING_ENV_DECISION -.->|Yes| HOSTING_PROVISION_OPS_PROV_DEPLOY +```text + Local Development + ═════════════════════════════════════════════════════════════════════════════════════════ + Developer writes code ──► Build and test locally ──► Commit changes + │ + ▼ + Git Repository + ═════════════════════════════════════════════════════════════════════════════════════════ + Push to remote branch ──► Open/Update Pull Request + │ + ▼ +┌─ CI Pipeline ────────────────────────────────────────────────────────────────────────────┐ +│ │ +│ ┌─ Database Job (Nightly) ───────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Scheduled ──► Download production ──► Sanitize database ──► Store database cache │ │ +│ │ trigger database Remove sensitive data │ │ +│ │ │ │ +│ └─────────────────────────────────────┬──────────────────────────────────────────────┘ │ +│ │ Provides cached database │ +│ ▼ │ +│ ┌─ Lint Job ────────────┐ ┌─ Database Job ──────────────────────────────────────────┐ │ +│ │ │ │ │ │ +│ │ Build CLI container │ │ ◆ Nightly cache ──Yes──► Pipeline Success │ │ +│ │ ▼ │ │ exists? │ │ +│ │ Composer validate │ │ │ No │ │ +│ │ ▼ │ │ ▼ │ │ +│ │ Composer audit │ │ Download ──► Sanitize ──► Store database │ │ +│ │ ▼ │ │ production database cache │ │ +│ │ Composer normalize │ │ database Remove │ │ +│ │ ▼ │ │ sensitive data │ │ +│ │ Hadolint │ │ │ │ +│ │ ▼ │ └───────────────────────────┬─────────────────────────────┘ │ +│ │ DCLint │ │ │ +│ │ ▼ │ ▼ │ +│ │ PHPCS │ ┌─ Build Job ────────────────────────────────────────────┐ │ +│ │ ▼ │ │ │ │ +│ │ PHPStan │ │ Code assembly │ │ +│ │ ▼ │ │ Build Docker ──► Composer deps ──► NPM deps ──► Assets│ │ +│ │ Rector │ │ │ │ │ +│ │ ▼ │ │ ▼ │ │ +│ │ PHPMD │ │ Website setup │ │ +│ │ ▼ │ │ Import cached DB ──► drush deploy ──► Custom scripts │ │ +│ │ Twig CS Fixer │ │ │ │ │ +│ │ ▼ │ │ ▼ │ │ +│ │ Gherkin Lint │ │ Testing │ │ +│ │ ▼ │ │ PHPUnit tests ──► Behat tests │ │ +│ │ ESLint / Stylelint │ │ │ │ +│ │ │ └────────────────────────────┬───────────────────────────┘ │ +│ └──────────┬────────────┘ │ │ +│ │ │ │ +│ │ │ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌─ Deployment Job ─────────────────────────────────────────────────────────────────┐ │ +│ │ │ │ +│ │ Webhook Artifact Lagoon Docker │ │ +│ │ Call URL Package artifact Call Lagoon webhook Create container image │ │ +│ │ │ │ +│ └──────────────────────────────────────────────────────────────────────────────────┘ │ +│ │ +└──────────────────────────────────────────────────────────────────────────────────────────┘ + │ + ▼ + Hosting Platform + ═════════════════════════════════════════════════════════════════════════════════════════ + ◆ Environment ──No──► Sync DB from production ───┐ + exists? │ + │ Yes ▼ + └──────────────────────────────────► drush deploy ──► Custom scripts ──► Notifications + + + Available Environments + ═════════════════════════════════════════════════════════════════════════════════════════ + ┊ PR Environment ┊ Dev Staging Production + ┊ (auto-removed) ┊ develop branch main branch production branch or tag ``` - - diff --git a/.vortex/docs/content/continuous-integration/README.mdx b/.vortex/docs/content/continuous-integration/README.mdx index f398fe3c3..836081cc6 100644 --- a/.vortex/docs/content/continuous-integration/README.mdx +++ b/.vortex/docs/content/continuous-integration/README.mdx @@ -14,7 +14,8 @@ providers. You would need to choose one of them and follow the setup instructions. The continuous integration pipeline consists of multiple jobs executed in a -containerized environment to ensure consistency across runs. +[`drevops/ci-runner`](https://github.com/drevops/ci-runner) container to ensure +consistency across runs. ## Workflow structure @@ -22,28 +23,36 @@ import CodeLifecycle from '../_code-lifecycle.mdx'; -### 1. Database +### 1. Lint + +- Runs in parallel with other jobs (no dependencies) +- Builds only the CLI container (no database or other services needed) +- Validates Composer configuration +- Lints Dockerfiles and Docker Compose files +- Installs development dependencies +- Runs all code linters: PHPCS, PHPStan, Rector, PHPMD, Twig CS Fixer, Gherkin Lint, ESLint, Stylelint +- Audits and normalizes Composer packages + +### 2. Database -- Runs in a [`drevops/ci-runner`](https://github.com/drevops/ci-runner) _runner_ container - Downloads the latest DB version based on a caching strategy - Caches database dumps to speed up the follow-up runs -### 2. Build +### 3. Build - Runs after the `database` job -- Uses Docker Compose to set up the environment -- Validates Composer lock and audits dependencies +- Uses Docker Compose to set up the full environment +- Validates Composer configuration - Assembles the codebase by installing dependencies - Provisions a website -- Lints code (first instance only) - Runs PHPUnit tests (first instance only) - Checks code coverage and posts PR comment (first instance only) - Runs BDD tests (distributed across all instances) - Collects and stores test results and artifacts -### 3. Deployment +### 4. Deployment -- Runs after successful completion of a previous `build` job +- Runs after successful completion of both `build` and `lint` jobs - Uses the built codebase without development dependencies from the `build` step - Adds required secrets and environment variables - Triggers a deployment using a router script @@ -108,22 +117,24 @@ The build job runs across multiple parallel containers (2 by default) to speed up test execution. Since each container runs the full build and provision steps, the test workload is distributed to make the best use of each container. +Code linting runs in a separate `lint` job and is not affected by test +parallelism settings. + ### What runs where | Task | First container | Other containers | |------|:---:|:---:| -| Code linting (PHPCS, PHPStan, Rector, etc.) | ✓ | — | | PHPUnit tests | ✓ | — | | Code coverage check and PR comment | ✓ | — | | Behat tests | ✓ (profile `p0`) | ✓ (profile `p1`, `p2`, ...) | -Linting, PHPUnit, and coverage reporting run exclusively on the first container +PHPUnit and coverage reporting run exclusively on the first container to avoid duplicate work. Behat tests run on all containers using profile-based distribution. ### Balancing Behat tests -Because the first container handles linting, PHPUnit, and coverage in addition +Because the first container handles PHPUnit and coverage in addition to Behat tests, it has more work to do than the other containers. To keep overall build time low, assign more Behat scenarios to the non-first containers. @@ -183,7 +194,7 @@ environment inconsistencies between local development and CI. It also massively speeds up builds by avoiding repetitive installation of common tools. To update to a newer version, change the image tag in your CI configuration -file. The image follows [CalVer](https://calver.org/) versioning (e.g., `25.10.0`) with +file. The image follows [CalVer](https://calver.org/) versioning (e.g., `26.2.0`) with monthly releases. ### Ignore tool failures @@ -193,22 +204,22 @@ Sometimes you may want to allow builds to pass despite linter and test failures. Set the corresponding `VORTEX_CI_*_IGNORE_FAILURE` variable to `1` to ignore failures (but still run the tool and see the results in the logs): -| Variable | Tool | -|-----------------------------------------------|----------------------| -| `VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE` | Composer validate | -| `VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE` | Composer audit | -| `VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE` | Composer normalize | -| `VORTEX_CI_HADOLINT_IGNORE_FAILURE` | Hadolint (Dockerfile)| -| `VORTEX_CI_DCLINT_IGNORE_FAILURE` | Docker Compose lint | -| `VORTEX_CI_PHPCS_IGNORE_FAILURE` | PHPCS | -| `VORTEX_CI_PHPSTAN_IGNORE_FAILURE` | PHPStan | -| `VORTEX_CI_RECTOR_IGNORE_FAILURE` | Rector | -| `VORTEX_CI_PHPMD_IGNORE_FAILURE` | PHPMD | -| `VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE` | Twig CS Fixer | -| `VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE` | Gherkin Lint | -| `VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE` | Node.js/Yarn lint | -| `VORTEX_CI_PHPUNIT_IGNORE_FAILURE` | PHPUnit | -| `VORTEX_CI_BEHAT_IGNORE_FAILURE` | Behat | +| Tool | Purpose | Variable | +|-------------------------------------------------------------|------------------------------------------|-----------------------------------------------| +| [Behat](/docs/tools/behat) | Run BDD acceptance tests | `VORTEX_CI_BEHAT_IGNORE_FAILURE` | +| Composer normalize | Ensure `composer.json` is sorted | `VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE` | +| Composer security audit | Check dependencies for vulnerabilities | `VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE` | +| Composer validate | Validate `composer.json` and lock file | `VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE` | +| [DCLint](/docs/tools/dclint) | Lint Docker Compose files | `VORTEX_CI_DCLINT_IGNORE_FAILURE` | +| [ESLint](/docs/tools/eslint) | Run ESLint and Stylelint | `VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE` | +| [Gherkin Lint](/docs/tools/gherkin-lint) | Lint Behat feature files | `VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE` | +| [Hadolint](/docs/tools/hadolint) | Lint Dockerfiles for best practices | `VORTEX_CI_HADOLINT_IGNORE_FAILURE` | +| [PHPCS](/docs/tools/phpcs) | Check PHP coding standards | `VORTEX_CI_PHPCS_IGNORE_FAILURE` | +| [PHPMD](/docs/tools/phpmd) | Detect PHP code smells and complexity | `VORTEX_CI_PHPMD_IGNORE_FAILURE` | +| [PHPStan](/docs/tools/phpstan) | Static analysis for PHP | `VORTEX_CI_PHPSTAN_IGNORE_FAILURE` | +| [PHPUnit](/docs/tools/phpunit) | Run unit, kernel, and functional tests | `VORTEX_CI_PHPUNIT_IGNORE_FAILURE` | +| [Rector](/docs/tools/rector) | Check for automated refactoring rules | `VORTEX_CI_RECTOR_IGNORE_FAILURE` | +| [Twig CS Fixer](/docs/tools/twig-cs-fixer) | Lint Twig templates | `VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE` | ### Configure deployment skip conditions diff --git a/.vortex/docs/cspell.json b/.vortex/docs/cspell.json index 5227a84bd..530df5224 100644 --- a/.vortex/docs/cspell.json +++ b/.vortex/docs/cspell.json @@ -11,6 +11,7 @@ "BROWSERTEST", "Buildx", "Diffy", + "Dockerfiles", "GHSA", "NRAK", "REDIS", diff --git a/.vortex/installer/tests/Fixtures/handler_process/_baseline/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/_baseline/.github/workflows/build-test-deploy.yml index e914f5fbb..1afc9088b 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/_baseline/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/_baseline/.github/workflows/build-test-deploy.yml @@ -48,6 +48,104 @@ defaults: shell: bash jobs: + + lint: + runs-on: ubuntu-latest + if: ${{ github.event_name != 'schedule' && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} + + container: + # https://hub.docker.com/r/drevops/ci-runner + image: drevops/ci-runner:__VERSION__ + env: + PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }} + VORTEX_CONTAINER_REGISTRY_USER: ${{ secrets.VORTEX_CONTAINER_REGISTRY_USER }} + VORTEX_CONTAINER_REGISTRY_PASS: ${{ secrets.VORTEX_CONTAINER_REGISTRY_PASS }} + TZ: ${{ vars.TZ || 'UTC' }} + TERM: xterm-256color + VORTEX_DEBUG: ${{ vars.VORTEX_DEBUG }} + + steps: + - name: Preserve $HOME set in the container + run: echo HOME=/root >> "$GITHUB_ENV" # https://github.com/actions/runner/issues/863 + + - name: Check out code + uses: actions/checkout@__HASH__ # __VERSION__ + + - name: Process the codebase to run in CI + run: find . -name "docker-compose.yml" -print0 | xargs -0 -I {} sh -c "sed -i -e '/###/d' {} && sed -i -e 's/##//' {}" + + - name: Load environment variables from .env + run: t=$(mktemp) && export -p >"${t}" && set -a && . ./.env && set +a && . "${t}" && env >> "$GITHUB_ENV" + + - name: Validate Composer configuration + run: composer validate --strict + continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE == '1' }} + + - name: Login to container registry + run: ./scripts/vortex/login-container-registry.sh + + - name: Lint Dockerfiles with Hadolint + run: | + find .docker -name 'Dockerfile' -o -name '*.dockerfile' | while read -r file; do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint + done + continue-on-error: ${{ vars.VORTEX_CI_HADOLINT_IGNORE_FAILURE == '1' }} + + - name: Lint Docker Compose files with DCLint + run: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . + continue-on-error: ${{ vars.VORTEX_CI_DCLINT_IGNORE_FAILURE == '1' }} + + - name: Build stack + run: docker compose up --no-deps --detach cli + + - name: Install development dependencies + run: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - name: Audit Composer packages + run: docker compose exec -T cli composer audit + continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE == '1' }} + + - name: Validate Composer configuration is normalized + run: docker compose exec -T cli composer normalize --dry-run + continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} + + - name: Lint code with PHPCS + run: docker compose exec -T cli vendor/bin/phpcs + continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} + + - name: Lint code with PHPStan + run: docker compose exec -T cli vendor/bin/phpstan + continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} + + - name: Lint code with Rector + run: docker compose exec -T cli vendor/bin/rector --dry-run + continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} + + - name: Lint code with PHPMD + run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml + continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} + + - name: Lint code with Twig CS Fixer + run: docker compose exec -T cli vendor/bin/twig-cs-fixer + continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} + + - name: Lint code with Gherkin Lint + run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features + continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} + + - name: Lint module code with NodeJS linters + run: docker compose exec -T cli bash -c "yarn run lint" + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} + + - name: Lint theme code with NodeJS linters + if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} + run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} + database: runs-on: ubuntu-latest if: ${{ github.event_name == 'push' || !startsWith(github.head_ref, 'project/') }} @@ -225,19 +323,6 @@ jobs: - name: Login to container registry run: ./scripts/vortex/login-container-registry.sh - - name: Lint Dockerfiles with Hadolint - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: | - find .docker -name 'Dockerfile' -o -name '*.dockerfile' | while read -r file; do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint - done - continue-on-error: ${{ vars.VORTEX_CI_HADOLINT_IGNORE_FAILURE == '1' }} - - - name: Lint Docker Compose files with DCLint - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . - continue-on-error: ${{ vars.VORTEX_CI_DCLINT_IGNORE_FAILURE == '1' }} - - name: Build stack run: docker compose up --detach && docker builder prune --all --force @@ -254,56 +339,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - name: Audit Composer packages - run: docker compose exec -T cli composer audit - continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE == '1' }} - - - name: Validate Composer configuration is normalized - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli composer normalize --dry-run - continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPCS - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpcs - continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPStan - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpstan - continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} - - - name: Lint code with Rector - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/rector --dry-run - continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPMD - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml - continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} - - - name: Lint code with Twig CS Fixer - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/twig-cs-fixer - continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} - - - name: Lint code with Gherkin Lint - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features - continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint module code with NodeJS linters - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint theme code with NodeJS linters - if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - name: Provision site run: | @@ -409,7 +444,7 @@ jobs: deploy: runs-on: ubuntu-latest - needs: build + needs: [build, lint] if: ${{ github.event_name != 'schedule' && !startsWith(github.head_ref || github.ref_name, 'deps/') && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} container: diff --git a/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/.circleci/config.yml index 8a07a8758..24e086c7d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -481,6 +492,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -490,6 +505,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -508,6 +524,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/ciprovider_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/db_download_source_acquia/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/db_download_source_acquia/.github/workflows/build-test-deploy.yml index 3427e38b2..6ff0ca642 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/db_download_source_acquia/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/db_download_source_acquia/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -127,6 +127,9 @@ +@@ -225,6 +225,9 @@ VORTEX_DOWNLOAD_DB_SEMAPHORE=/tmp/download-db-success ./scripts/vortex/download-db.sh echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 diff --git a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/.circleci/config.yml index 8a07a8758..24e086c7d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -481,6 +492,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -490,6 +505,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -508,6 +524,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_all_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/.circleci/config.yml index 12d51b334..f3c93b016 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -423,6 +434,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database diff --git a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_gha/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_gha/.github/workflows/build-test-deploy.yml index 09e1781d4..ad062fb1c 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_gha/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/deploy_types_none_gha/.github/workflows/build-test-deploy.yml @@ -1,11 +1,11 @@ -@@ -406,76 +406,3 @@ +@@ -441,76 +441,3 @@ timeout-minutes: 120 # Cancel the action after 15 minutes, regardless of whether a connection has been established. with: detached: true - - deploy: - runs-on: ubuntu-latest -- needs: build +- needs: [build, lint] - if: ${{ github.event_name != 'schedule' && !startsWith(github.head_ref || github.ref_name, 'deps/') && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} - - container: diff --git a/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/.circleci/config.yml index 8a07a8758..24e086c7d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -481,6 +492,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -490,6 +505,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -508,6 +524,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/deps_updates_provider_ci_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/.github/workflows/build-test-deploy.yml index 3427e38b2..6ff0ca642 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/hosting_acquia/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -127,6 +127,9 @@ +@@ -225,6 +225,9 @@ VORTEX_DOWNLOAD_DB_SEMAPHORE=/tmp/download-db-success ./scripts/vortex/download-db.sh echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 diff --git a/.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/.github/workflows/build-test-deploy.yml index 3427e38b2..6ff0ca642 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/hosting_project_name___acquia/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -127,6 +127,9 @@ +@@ -225,6 +225,9 @@ VORTEX_DOWNLOAD_DB_SEMAPHORE=/tmp/download-db-success ./scripts/vortex/download-db.sh echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/.circleci/config.yml index 8a07a8758..24e086c7d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -481,6 +492,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -490,6 +505,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -508,6 +524,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_disabled_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_acquia/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_acquia/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_acquia/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_acquia/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_ftp/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_ftp/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_ftp/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_ftp/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_lagoon/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_lagoon/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_lagoon/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_lagoon/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_s3/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_s3/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_s3/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_s3/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_url/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_url/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_url/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_download_source_url/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/.circleci/config.yml index a0ba1a34a..e4b73f62b 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -228,20 +312,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -260,65 +330,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -490,6 +501,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -499,6 +514,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -517,6 +533,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_lagoon/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_lagoon/.github/workflows/build-test-deploy.yml index 81974f68d..e74ad7b35 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_lagoon/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/migration_enabled_lagoon/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -128,6 +128,9 @@ +@@ -226,6 +226,9 @@ echo "db_hash=${{ hashFiles('.data') }}" >> "$GITHUB_ENV" timeout-minutes: 30 @@ -8,7 +8,7 @@ - name: Export DB run: | if [ ! -f /tmp/download-db-success ]; then echo "==> Database download semaphore file is missing. DB export will not proceed."; exit 0; fi -@@ -310,6 +313,10 @@ +@@ -345,6 +348,10 @@ if [ -f .data/db.sql ]; then docker compose exec cli mkdir -p .data docker compose cp -L .data/db.sql cli:/app/.data/db.sql diff --git a/.vortex/installer/tests/Fixtures/handler_process/provision_profile/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/provision_profile/.github/workflows/build-test-deploy.yml index 6e511bc4a..adf86cdef 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/provision_profile/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/provision_profile/.github/workflows/build-test-deploy.yml @@ -7,14 +7,22 @@ defaults: run: -@@ -48,111 +46,10 @@ - shell: bash +@@ -51,7 +49,6 @@ + + lint: + runs-on: ubuntu-latest +- if: ${{ github.event_name != 'schedule' && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} + + container: + # https://hub.docker.com/r/drevops/ci-runner +@@ -146,111 +143,8 @@ + run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - jobs: - database: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'push' || !startsWith(github.head_ref, 'project/') }} - +- - container: - # https://hub.docker.com/r/drevops/ci-runner - image: drevops/ci-runner:__VERSION__ @@ -114,12 +122,12 @@ - build: runs-on: ubuntu-latest - needs: database +- needs: database - if: ${{ github.event_name != 'schedule' && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} strategy: # A matrix to run multiple jobs in parallel. -@@ -173,14 +70,6 @@ +@@ -271,14 +165,6 @@ VORTEX_SSH_DISABLE_STRICT_HOST_KEY_CHECKING: "1" VORTEX_SSH_REMOVE_ALL_KEYS: "1" VORTEX_DEBUG: ${{ vars.VORTEX_DEBUG }} @@ -134,7 +142,7 @@ steps: - name: Preserve $HOME set in the container -@@ -199,29 +88,6 @@ +@@ -297,29 +183,6 @@ run: composer validate --strict continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE == '1' }} @@ -164,10 +172,10 @@ - name: Login to container registry run: ./scripts/vortex/login-container-registry.sh -@@ -410,7 +276,6 @@ +@@ -445,7 +308,6 @@ deploy: runs-on: ubuntu-latest - needs: build + needs: [build, lint] - if: ${{ github.event_name != 'schedule' && !startsWith(github.head_ref || github.ref_name, 'deps/') && (github.event_name == 'push' || !startsWith(github.head_ref, 'project/')) }} container: diff --git a/.vortex/installer/tests/Fixtures/handler_process/theme_claro/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/theme_claro/.github/workflows/build-test-deploy.yml index 071af6d2b..389fdf2bb 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/theme_claro/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/theme_claro/.github/workflows/build-test-deploy.yml @@ -1,12 +1,12 @@ -@@ -300,11 +300,6 @@ +@@ -141,11 +141,6 @@ run: docker compose exec -T cli bash -c "yarn run lint" continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Lint theme code with NodeJS linters -- if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} +- if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Provision site - run: | - if [ -f .data/db.sql ]; then + database: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' || !startsWith(github.head_ref, 'project/') }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/theme_olivero/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/theme_olivero/.github/workflows/build-test-deploy.yml index 071af6d2b..389fdf2bb 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/theme_olivero/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/theme_olivero/.github/workflows/build-test-deploy.yml @@ -1,12 +1,12 @@ -@@ -300,11 +300,6 @@ +@@ -141,11 +141,6 @@ run: docker compose exec -T cli bash -c "yarn run lint" continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Lint theme code with NodeJS linters -- if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} +- if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Provision site - run: | - if [ -f .data/db.sql ]; then + database: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' || !startsWith(github.head_ref, 'project/') }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/theme_stark/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/theme_stark/.github/workflows/build-test-deploy.yml index 071af6d2b..389fdf2bb 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/theme_stark/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/theme_stark/.github/workflows/build-test-deploy.yml @@ -1,12 +1,12 @@ -@@ -300,11 +300,6 @@ +@@ -141,11 +141,6 @@ run: docker compose exec -T cli bash -c "yarn run lint" continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Lint theme code with NodeJS linters -- if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} +- if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Provision site - run: | - if [ -f .data/db.sql ]; then + database: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' || !startsWith(github.head_ref, 'project/') }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/.circleci/config.yml index 8a07a8758..24e086c7d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -481,6 +492,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -490,6 +505,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -508,6 +524,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/timezone_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint/.github/workflows/build-test-deploy.yml index af52839e0..7c4e01bc5 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint/.github/workflows/build-test-deploy.yml @@ -1,27 +1,23 @@ -@@ -265,26 +265,6 @@ +@@ -113,22 +113,6 @@ run: docker compose exec -T cli composer normalize --dry-run continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPCS -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpcs - continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPStan -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpstan - continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} - - - name: Lint code with Rector -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/rector --dry-run - continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPMD -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml - continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} - - name: Lint code with Twig CS Fixer - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli vendor/bin/twig-cs-fixer + continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/.circleci/config.yml index eb8de42e1..88d85e1f3 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/.circleci/config.yml @@ -97,6 +97,74 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +291,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,41 +309,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -457,6 +476,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -466,6 +489,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -484,6 +508,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/tests/phpunit/CircleCiConfigTest.php index 113f4f668..98bfab325 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_lint_circleci/tests/phpunit/CircleCiConfigTest.php @@ -43,7 +43,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -217,7 +217,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/.github/workflows/build-test-deploy.yml index e3c6749dd..ed31833fb 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests/.github/workflows/build-test-deploy.yml @@ -1,16 +1,15 @@ -@@ -290,11 +290,6 @@ +@@ -133,10 +133,6 @@ run: docker compose exec -T cli vendor/bin/twig-cs-fixer continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} - - name: Lint code with Gherkin Lint -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features - continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - name: Lint module code with NodeJS linters - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli bash -c "yarn run lint" -@@ -312,65 +307,6 @@ + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} +@@ -347,65 +343,6 @@ docker compose cp -L .data/db.sql cli:/app/.data/db.sql fi docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli ./scripts/vortex/provision.sh diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/.circleci/config.yml index 6b292634e..dc61bdb31 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_be_tests_circleci/.circleci/config.yml @@ -97,6 +97,86 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +303,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,59 +321,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -412,6 +425,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -421,6 +438,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -439,6 +457,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/.github/workflows/build-test-deploy.yml index b2e441d2e..12d35af03 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -254,7 +254,6 @@ +@@ -103,7 +103,6 @@ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" @@ -6,15 +6,14 @@ - name: Audit Composer packages run: docker compose exec -T cli composer audit -@@ -294,11 +293,6 @@ - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} +@@ -136,10 +135,6 @@ + - name: Lint code with Gherkin Lint run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint module code with NodeJS linters -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - name: Lint theme code with NodeJS linters - if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} + if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/.circleci/config.yml index 90082d00a..689a5f131 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/.circleci/config.yml @@ -97,6 +97,85 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +302,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -256,58 +321,6 @@ jobs: if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Provision site command: | @@ -474,6 +487,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -483,6 +500,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -501,6 +519,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/.github/workflows/build-test-deploy.yml index d82b3fbf3..76d20769a 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -254,7 +254,6 @@ +@@ -103,7 +103,6 @@ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" @@ -6,20 +6,19 @@ - name: Audit Composer packages run: docker compose exec -T cli composer audit -@@ -294,16 +293,6 @@ - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} +@@ -136,15 +135,6 @@ + - name: Lint code with Gherkin Lint run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint module code with NodeJS linters -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint theme code with NodeJS linters -- if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} +- if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Provision site - run: | + database: + runs-on: ubuntu-latest diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/.circleci/config.yml index 3b8f81204..7627ee9f5 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/.circleci/config.yml @@ -97,6 +97,79 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +296,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -256,52 +315,6 @@ jobs: if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Provision site command: | @@ -468,6 +481,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -477,6 +494,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -495,6 +513,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_groups_no_fe_lint_no_theme_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/.github/workflows/build-test-deploy.yml index 7870f224f..c10937741 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat/.github/workflows/build-test-deploy.yml @@ -1,16 +1,15 @@ -@@ -290,11 +290,6 @@ +@@ -133,10 +133,6 @@ run: docker compose exec -T cli vendor/bin/twig-cs-fixer continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} - - name: Lint code with Gherkin Lint -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features - continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - name: Lint module code with NodeJS linters - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli bash -c "yarn run lint" -@@ -360,18 +355,6 @@ + continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} +@@ -395,18 +391,6 @@ token: ${{ secrets.CODECOV_TOKEN }} env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/.circleci/config.yml index 08cda9e0e..5b8a4f744 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/.circleci/config.yml @@ -97,6 +97,86 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +303,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,59 +321,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -465,6 +478,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -474,6 +491,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -492,6 +510,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_behat_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint/.github/workflows/build-test-deploy.yml index b2e441d2e..12d35af03 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -254,7 +254,6 @@ +@@ -103,7 +103,6 @@ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" @@ -6,15 +6,14 @@ - name: Audit Composer packages run: docker compose exec -T cli composer audit -@@ -294,11 +293,6 @@ - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} +@@ -136,10 +135,6 @@ + - name: Lint code with Gherkin Lint run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint module code with NodeJS linters -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - name: Lint theme code with NodeJS linters - if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} + if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/.circleci/config.yml index 90082d00a..689a5f131 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/.circleci/config.yml @@ -97,6 +97,85 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +302,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -256,58 +321,6 @@ jobs: if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Provision site command: | @@ -474,6 +487,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -483,6 +500,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -501,6 +519,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_no_theme/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_no_theme/.github/workflows/build-test-deploy.yml index d82b3fbf3..76d20769a 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_no_theme/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_eslint_no_theme/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -254,7 +254,6 @@ +@@ -103,7 +103,6 @@ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" @@ -6,20 +6,19 @@ - name: Audit Composer packages run: docker compose exec -T cli composer audit -@@ -294,16 +293,6 @@ - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} +@@ -136,15 +135,6 @@ + - name: Lint code with Gherkin Lint run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint module code with NodeJS linters -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint theme code with NodeJS linters -- if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} +- if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Provision site - run: | + database: + runs-on: ubuntu-latest diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs/.github/workflows/build-test-deploy.yml index da501f94e..0b3940a4d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs/.github/workflows/build-test-deploy.yml @@ -1,12 +1,11 @@ -@@ -265,11 +265,6 @@ +@@ -113,10 +113,6 @@ run: docker compose exec -T cli composer normalize --dry-run continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPCS -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpcs - continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPStan - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli vendor/bin/phpstan + continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/.circleci/config.yml index e18ac1dc9..38b3cb5a5 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/.circleci/config.yml @@ -97,6 +97,86 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +303,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,59 +321,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -475,6 +488,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -484,6 +501,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -502,6 +520,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/tests/phpunit/CircleCiConfigTest.php index 86f336226..15776fa5c 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpcs_circleci/tests/phpunit/CircleCiConfigTest.php @@ -44,7 +44,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -218,7 +218,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd/.github/workflows/build-test-deploy.yml index 7a1641d9d..dbc19396e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd/.github/workflows/build-test-deploy.yml @@ -1,12 +1,11 @@ -@@ -280,11 +280,6 @@ +@@ -125,10 +125,6 @@ run: docker compose exec -T cli vendor/bin/rector --dry-run continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPMD -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml - continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} - - name: Lint code with Twig CS Fixer - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli vendor/bin/twig-cs-fixer + continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/.circleci/config.yml index 9fd82b7c8..61873f3a1 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/.circleci/config.yml @@ -97,6 +97,86 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +303,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,59 +321,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -475,6 +488,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -484,6 +501,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -502,6 +520,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/tests/phpunit/CircleCiConfigTest.php index 43859a8fc..9cdb89a80 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpmd_circleci/tests/phpunit/CircleCiConfigTest.php @@ -47,7 +47,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -221,7 +221,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan/.github/workflows/build-test-deploy.yml index 0ccbfe13c..a0f4998e2 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan/.github/workflows/build-test-deploy.yml @@ -1,12 +1,11 @@ -@@ -270,11 +270,6 @@ +@@ -117,10 +117,6 @@ run: docker compose exec -T cli vendor/bin/phpcs continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPStan -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpstan - continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} - - name: Lint code with Rector - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli vendor/bin/rector --dry-run + continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/.circleci/config.yml index 89c775a00..0ae0e3dff 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/.circleci/config.yml @@ -97,6 +97,86 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +303,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,59 +321,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -475,6 +488,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -484,6 +501,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -502,6 +520,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpstan_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/.github/workflows/build-test-deploy.yml index 8729e7c93..0fbfd7b55 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -314,53 +314,6 @@ +@@ -349,53 +349,6 @@ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli ./scripts/vortex/provision.sh timeout-minutes: 30 diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/.circleci/config.yml index 05a2b68b5..3814cb88c 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_phpunit_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -428,6 +439,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -437,6 +452,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -455,6 +471,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector/.github/workflows/build-test-deploy.yml index 06a056b92..ba87e2632 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector/.github/workflows/build-test-deploy.yml @@ -1,12 +1,11 @@ -@@ -275,11 +275,6 @@ +@@ -121,10 +121,6 @@ run: docker compose exec -T cli vendor/bin/phpstan continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} - - name: Lint code with Rector -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/rector --dry-run - continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPMD - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml + continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/.circleci/config.yml index bf6b2ad1d..1b484cc52 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/.circleci/config.yml @@ -97,6 +97,86 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +303,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,59 +321,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -475,6 +488,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -484,6 +501,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -502,6 +520,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_rector_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/.circleci/config.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/.circleci/config.yml index 8a07a8758..24e086c7d 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/.circleci/config.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/.circleci/config.yml @@ -97,6 +97,90 @@ aliases: ################################################################################ jobs: + + # Lint job runs in parallel with database and build jobs. + lint: + <<: *runner_config + steps: + - checkout + - *step_process_codebase_for_ci + - *load_variables_from_dotenv + + - run: + name: Validate Composer configuration + command: composer validate --strict || [ "${VORTEX_CI_COMPOSER_VALIDATE_IGNORE_FAILURE:-0}" -eq 1 ] + + - *step_setup_remote_docker + + - run: + name: Login to container registry + command: ./scripts/vortex/login-container-registry.sh + + - run: + name: Lint Dockerfiles with Hadolint + command: | + for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do + echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] + done + + - run: + name: Lint Docker Compose files with DCLint + command: docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Build stack + command: docker compose up --no-deps --detach cli + + - run: + name: Install development dependencies + command: | + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ + if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ + COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" + docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" + + - run: + name: Audit Composer packages + command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Validate Composer configuration is normalized + command: docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPCS + command: docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPStan + command: docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Rector + command: docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with PHPMD + command: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Twig CS Fixer + command: docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint code with Gherkin Lint + command: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint module code with NodeJS linters + command: docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + + - run: + name: Lint theme code with NodeJS linters + command: | + [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 + docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] + # Database handling is a first step of the build. # - $VORTEX_CI_DB_CACHE_TIMESTAMP is used to determine if a fresh DB dump # should be downloaded for the current build. Usually, a daily database dump @@ -223,20 +307,6 @@ jobs: name: Login to container registry command: ./scripts/vortex/login-container-registry.sh - - run: - name: Lint Dockerfiles with Hadolint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - for file in $(find .docker -name 'Dockerfile' -o -name '*.dockerfile'); do - echo "Linting ${file}" && cat "${file}" | docker run --rm -i hadolint/hadolint || [ "${VORTEX_CI_HADOLINT_IGNORE_FAILURE:-0}" -eq 1 ] - done - - - run: - name: Lint Docker Compose files with DCLint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker run --rm -v "${PWD}":/app zavoloklom/dclint:__VERSION__ . || [ "${VORTEX_CI_DCLINT_IGNORE_FAILURE:-0}" -eq 1 ] - - run: name: Build stack command: docker compose up --detach && docker builder prune --all --force @@ -255,65 +325,6 @@ jobs: docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" - docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c "yarn install --frozen-lockfile" - - - run: - name: Audit Composer packages - command: docker compose exec -T cli composer audit || [ "${VORTEX_CI_COMPOSER_AUDIT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Validate Composer configuration is normalized - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli composer normalize --dry-run || [ "${VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPCS - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpcs || [ "${VORTEX_CI_PHPCS_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPStan - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpstan || [ "${VORTEX_CI_PHPSTAN_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Rector - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/rector --dry-run || [ "${VORTEX_CI_RECTOR_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with PHPMD - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml || [ "${VORTEX_CI_PHPMD_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Twig CS Fixer - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/twig-cs-fixer || [ "${VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint code with Gherkin Lint - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features || [ "${VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint module code with NodeJS linters - command: | - [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ] && exit 0 - docker compose exec -T cli bash -c "yarn run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - - - run: - name: Lint theme code with NodeJS linters - command: | - { [ "${CIRCLE_NODE_TOTAL:-1}" -gt 1 ] && [ "${CIRCLE_NODE_INDEX:-0}" -ne 0 ]; } || [ "${VORTEX_FRONTEND_BUILD_SKIP:-0}" -eq 1 ] && exit 0 - docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" || [ "${VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE:-0}" -eq 1 ] - run: name: Provision site @@ -481,6 +492,10 @@ workflows: filters: tags: only: /.*/ + - lint: + filters: + tags: + only: /.*/ - build: requires: - database @@ -490,6 +505,7 @@ workflows: - deploy: requires: - build + - lint filters: branches: # Allowed branches: @@ -508,6 +524,7 @@ workflows: - deploy-tags: requires: - build + - lint filters: branches: ignore: /.*/ diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/tests/phpunit/CircleCiConfigTest.php b/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/tests/phpunit/CircleCiConfigTest.php index f79f32706..1d28e375e 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/tests/phpunit/CircleCiConfigTest.php +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_circleci/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /** diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_no_theme/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_no_theme/.github/workflows/build-test-deploy.yml index 071af6d2b..389fdf2bb 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_no_theme/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_no_stylelint_no_theme/.github/workflows/build-test-deploy.yml @@ -1,12 +1,12 @@ -@@ -300,11 +300,6 @@ +@@ -141,11 +141,6 @@ run: docker compose exec -T cli bash -c "yarn run lint" continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Lint theme code with NodeJS linters -- if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} +- if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} - run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - - name: Provision site - run: | - if [ -f .data/db.sql ]; then + database: + runs-on: ubuntu-latest + if: ${{ github.event_name == 'push' || !startsWith(github.head_ref, 'project/') }} diff --git a/.vortex/installer/tests/Fixtures/handler_process/tools_none/.github/workflows/build-test-deploy.yml b/.vortex/installer/tests/Fixtures/handler_process/tools_none/.github/workflows/build-test-deploy.yml index 20f270f49..ac7241279 100644 --- a/.vortex/installer/tests/Fixtures/handler_process/tools_none/.github/workflows/build-test-deploy.yml +++ b/.vortex/installer/tests/Fixtures/handler_process/tools_none/.github/workflows/build-test-deploy.yml @@ -1,4 +1,4 @@ -@@ -254,7 +254,6 @@ +@@ -103,7 +103,6 @@ docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli bash -c " \ if [ -n \"${PACKAGE_TOKEN:-}\" ]; then export COMPOSER_AUTH='{\"github-oauth\": {\"github.com\": \"${PACKAGE_TOKEN-}\"}}'; fi && \ COMPOSER_MEMORY_LIMIT=-1 composer --ansi install --prefer-dist" @@ -6,49 +6,42 @@ - name: Audit Composer packages run: docker compose exec -T cli composer audit -@@ -265,41 +264,11 @@ +@@ -113,34 +112,10 @@ run: docker compose exec -T cli composer normalize --dry-run continue-on-error: ${{ vars.VORTEX_CI_COMPOSER_NORMALIZE_IGNORE_FAILURE == '1' }} - - name: Lint code with PHPCS -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpcs - continue-on-error: ${{ vars.VORTEX_CI_PHPCS_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPStan -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpstan - continue-on-error: ${{ vars.VORTEX_CI_PHPSTAN_IGNORE_FAILURE == '1' }} - - - name: Lint code with Rector -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/rector --dry-run - continue-on-error: ${{ vars.VORTEX_CI_RECTOR_IGNORE_FAILURE == '1' }} - - - name: Lint code with PHPMD -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/phpmd . text phpmd.xml - continue-on-error: ${{ vars.VORTEX_CI_PHPMD_IGNORE_FAILURE == '1' }} - - name: Lint code with Twig CS Fixer - if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} run: docker compose exec -T cli vendor/bin/twig-cs-fixer continue-on-error: ${{ vars.VORTEX_CI_TWIG_CS_FIXER_IGNORE_FAILURE == '1' }} - - name: Lint code with Gherkin Lint -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli vendor/bin/gherkinlint lint tests/behat/features - continue-on-error: ${{ vars.VORTEX_CI_GHERKIN_LINT_IGNORE_FAILURE == '1' }} - - - name: Lint module code with NodeJS linters -- if: ${{ matrix.instance == 0 || strategy.job-total == 1 }} - run: docker compose exec -T cli bash -c "yarn run lint" - continue-on-error: ${{ vars.VORTEX_CI_NODEJS_LINT_IGNORE_FAILURE == '1' }} - - name: Lint theme code with NodeJS linters - if: ${{ (matrix.instance == 0 || strategy.job-total == 1) && vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} + if: ${{ vars.VORTEX_FRONTEND_BUILD_SKIP != '1' }} run: docker compose exec -T cli bash -c "yarn --cwd=\${WEBROOT}/themes/custom/\${DRUPAL_THEME} run lint" -@@ -312,65 +281,6 @@ +@@ -347,65 +322,6 @@ docker compose cp -L .data/db.sql cli:/app/.data/db.sql fi docker compose exec $(env | cut -f1 -d= | sed 's/^/-e /') -T cli ./scripts/vortex/provision.sh diff --git a/tests/phpunit/CircleCiConfigTest.php b/tests/phpunit/CircleCiConfigTest.php index 5beaafefe..370bccded 100644 --- a/tests/phpunit/CircleCiConfigTest.php +++ b/tests/phpunit/CircleCiConfigTest.php @@ -48,7 +48,7 @@ protected function setUp(): void { */ #[DataProvider('dataProviderDeployBranchRegex')] public function testDeployBranchRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][2]['deploy']['filters']['branches']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy']['filters']['branches']['only'], $branch)); } /** @@ -222,7 +222,7 @@ public static function dataProviderDeployBranchRegex(): array { */ #[DataProvider('dataProviderDeployTagRegex')] public function testDeployTagRegex(string $branch, bool $expected = TRUE): void { - $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][3]['deploy-tags']['filters']['tags']['only'], $branch)); + $this->assertEquals($expected, preg_match($this->config['workflows']['commit']['jobs'][4]['deploy-tags']['filters']['tags']['only'], $branch)); } /**