From 89c55f6918dc44d02f8b32b9bd057473fc3820eb Mon Sep 17 00:00:00 2001
From: Conrad Lara <54534-cmlara@users.noreply.drupalcode.org>
Date: Sat, 29 Jul 2023 05:19:43 +0000
Subject: [PATCH] Issue #3366139 by cmlara: Adopt GitlabCi

---
 .gitlab-ci.yml        | 142 +++++++++++++++++
 composer.json         |   8 +
 phpstan-baseline.neon | 360 ++++++++++++++++++++++++++++++++++++++++++
 phpstan.neon          |  18 +++
 4 files changed, 528 insertions(+)
 create mode 100644 .gitlab-ci.yml
 create mode 100644 phpstan-baseline.neon
 create mode 100644 phpstan.neon

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
new file mode 100644
index 0000000..6867b6a
--- /dev/null
+++ b/.gitlab-ci.yml
@@ -0,0 +1,142 @@
+################
+# GitLab template for the RabbitMQ module.
+# Utilizes the Drupal gitlab_templates base
+#
+# Additional features:
+#   * PHPStan analysis.
+#   * PCOV Code Coverage reporting.
+################
+
+include:
+  ################
+  # DrupalCI includes:
+  # As long as you include this, any future includes added by the Drupal Association will be accessible to your pipelines automatically.
+  # View these include files at https://git.drupalcode.org/project/gitlab_templates/
+  ################
+  - project: $_GITLAB_TEMPLATES_REPO
+    ref: $_GITLAB_TEMPLATES_REF
+    file:
+      - '/includes/include.drupalci.main.yml'
+      - '/includes/include.drupalci.variables.yml'
+      - '/includes/include.drupalci.workflows.yml'
+
+################
+# Pipeline configuration variables
+#
+# Docs at https://git.drupalcode.org/project/gitlab_templates/-/blob/1.0.x/includes/include.drupalci.variables.yml
+################
+variables:
+  _TARGET_CORE:
+    value: "$CORE_SUPPORTED"
+  _TARGET_PHP:
+    value: "8.1"
+  # Collect code coverage data.
+  _PHPUNIT_EXTRA:
+    value: --coverage-cobertura $CI_PROJECT_DIR/coverage.xml --coverage-filter $CI_PROJECT_DIR/$_WEB_ROOT/modules/custom/ --coverage-text --colors=never
+  # Generate a new phpstan baseline.
+  GENERATE_PHPSTAN_BASELINE:
+    value: "0"
+
+################
+# Customize composer stage to not symlink the module as it interferes with
+# the PCOV extension tracking coverage.
+#
+# During archive assets stage trying to overwrite symlinks with actual
+# files/directives causes errors so we must perform these actions
+# during the initial script phase instead of during after_script.
+################
+.composer-local:
+  extends: .composer-base
+  script:
+    # Run the normal commands first.
+    - !reference [.composer-base, script]
+    # Remove the module directory and all the symlinks in it.
+    - rm -Rf web/modules/custom/$CI_PROJECT_NAME
+    # Duplicate the code into the modules folder without using symlinks.
+    - git clone ./ web/modules/custom/$CI_PROJECT_NAME
+    # Remove the build root copy to avoid duplicate classnames.
+    - rm -Rf src tests
+
+composer:
+  extends: .composer-local
+
+################
+# Add PHPStan validation.
+################
+phpstan:
+  stage: validate
+  needs: ["composer"]
+  script:
+    # Output a copy in GitLab code quality format.
+    - vendor/bin/phpstan analyse -c web/modules/custom/$CI_PROJECT_NAME/phpstan.neon --no-progress --error-format gitlab web/modules/custom/$CI_PROJECT_NAME > phpstan.xml || true
+    # Output a copy in junit
+    - vendor/bin/phpstan analyse -c web/modules/custom/$CI_PROJECT_NAME/phpstan.neon --no-progress --error-format junit web/modules/custom/$CI_PROJECT_NAME > junit.xml || true
+    # Ensure paths for coverage are git-relative.
+    - sed -i "s#web/modules/custom/$CI_PROJECT_NAME/##" phpstan.xml junit.xml || true
+    # Output a copy in plain text for human logs.
+    - vendor/bin/phpstan analyse -c web/modules/custom/$CI_PROJECT_NAME/phpstan.neon --no-progress --error-format table web/modules/custom/$CI_PROJECT_NAME
+  allow_failure: true
+  artifacts:
+    expose_as: phpstan
+    when: always
+    expire_in: 6 mos
+    reports:
+      codequality: phpstan.xml
+      junit: junit.xml
+    paths:
+      - phpstan.xml
+      - junit.xml
+
+phpstan-new-baseline:
+  stage: validate
+  rules:
+    - if: '$GENERATE_PHPSTAN_BASELINE == "1"'
+      when: always
+    - when: never
+  script:
+    # Purge the existing baseline.
+    - echo '' > web/modules/custom/$CI_PROJECT_NAME/phpstan-baseline.neon
+    # Generate a new baseline.
+    # We must put the baseline in the source folder to get relative paths.
+    - vendor/bin/phpstan analyse -c web/modules/custom/$CI_PROJECT_NAME/phpstan.neon --no-progress --generate-baseline web/modules/custom/$CI_PROJECT_NAME/phpstan-baseline-new.neon web/modules/custom/$CI_PROJECT_NAME
+    - mv web/modules/custom/$CI_PROJECT_NAME/phpstan-baseline-new.neon phpstan-baseline-new.neon
+  allow_failure: false
+  artifacts:
+    expose_as: phpstan-new-baseline
+    when: always
+    expire_in: 6 mos
+    paths:
+      - phpstan-baseline-new.neon
+
+################
+# Customize phpunit stage to:
+#   * Enable PCOV Coverage Reporting.
+#   * Collect code coverage data.
+################
+phpunit:
+  extends: .phpunit-base
+  services:
+     # Include the normal containers.
+    - !reference [.with-database]
+    - !reference [.with-chrome]
+    # Add a container for RabbitMq.
+    - name: rabbitmq:3
+  before_script:
+    # Install and enable PCOV.
+    - echo -e '[pcov]\npcov.directory=.' > /usr/local/etc/php/conf.d/pcov.ini
+    - pecl install pcov && docker-php-ext-enable pcov
+  after_script:
+    # Ensure paths for coverage are git-relative.
+    - sed -i "s#<source>$CI_PROJECT_DIR/web/modules/custom/$CI_PROJECT_NAME#<source>$CI_PROJECT_DIR#" coverage.xml
+  # Capture line coverage counts for GitLab UI display.
+  coverage: /^\s*Lines:\s*\d+.\d+\%/
+  artifacts:
+    reports:
+      coverage_report:
+        coverage_format: cobertura
+        path: coverage.xml
+    paths:
+      - junit.xml
+      - apache.access.log.txt
+      - $BROWSERTEST_OUTPUT_DIRECTORY
+      - coverage.xml
diff --git a/composer.json b/composer.json
index 08924a0..792b2fd 100644
--- a/composer.json
+++ b/composer.json
@@ -10,10 +10,18 @@
     "homepage": "https://www.drupal.org/project/rabbitmq",
     "license": "GPL-2.0-or-later",
     "name": "drupal/rabbitmq",
+    "prefer-stable": true,
     "require": {
         "drupal/core": "^9 || ^10",
         "php-amqplib/php-amqplib": "^3.1"
     },
+    "require-dev": {
+        "mglaman/phpstan-drupal": "^1.1",
+        "phpstan/extension-installer": "^1.2",
+        "phpstan/phpstan": "^1.9",
+        "phpstan/phpstan-deprecation-rules": "^1.1",
+        "phpstan/phpstan-phpunit": "^1.3"
+    },
     "suggest": {
         "ext-pcntl": "Needed to support the timeout option"
     },
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
new file mode 100644
index 0000000..50f4608
--- /dev/null
+++ b/phpstan-baseline.neon
@@ -0,0 +1,360 @@
+parameters:
+	ignoreErrors:
+		-
+			message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
+			count: 2
+			path: rabbitmq.install
+
+		-
+			message: "#^Cannot access offset 'name' on mixed\\.$#"
+			count: 4
+			path: rabbitmq.install
+
+		-
+			message: "#^Function rabbitmq_update_9401\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: rabbitmq.install
+
+		-
+			message: "#^Cannot access offset string on mixed\\.$#"
+			count: 1
+			path: src/Commands/RabbitmqCommands.php
+
+		-
+			message: "#^Cannot cast mixed to int\\.$#"
+			count: 1
+			path: src/Commands/RabbitmqCommands.php
+
+		-
+			message: "#^Method Drupal\\\\rabbitmq\\\\Commands\\\\RabbitmqCommands\\:\\:worker\\(\\) should return int but return statement is missing\\.$#"
+			count: 1
+			path: src/Commands/RabbitmqCommands.php
+
+		-
+			message: "#^Parameter \\#2 \\$length of method Drush\\\\Commands\\\\DrushCommands\\:\\:yell\\(\\) expects int, null given\\.$#"
+			count: 1
+			path: src/Commands/RabbitmqCommands.php
+
+		-
+			message: "#^Cannot access offset mixed on mixed\\.$#"
+			count: 1
+			path: src/ConnectionFactory.php
+
+		-
+			message: "#^Method Drupal\\\\rabbitmq\\\\ConnectionFactory\\:\\:getCredentials\\(\\) should return array but returns mixed\\.$#"
+			count: 1
+			path: src/ConnectionFactory.php
+
+		-
+			message: "#^Parameter \\#2 \\$array of function array_key_exists expects array, mixed given\\.$#"
+			count: 1
+			path: src/ConnectionFactory.php
+
+		-
+			message: "#^Access to an undefined property object\\:\\:\\$data\\.$#"
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Access to an undefined property object\\:\\:\\$id\\.$#"
+			count: 2
+			path: src/Consumer.php
+
+		-
+			message: """
+				#^Call to deprecated function watchdog_exception\\(\\)\\:
+				in drupal\\:10\\.1\\.0 and is removed from drupal\\:11\\.0\\.0\\. Use
+				  Use \\\\Drupal\\\\Core\\\\Utility\\\\Error\\:\\:logException\\(\\) instead\\.$#
+			"""
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Cannot call method basic_ack\\(\\) on PhpAmqpLib\\\\Channel\\\\AMQPChannel\\|null\\.$#"
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Cannot call method basic_reject\\(\\) on PhpAmqpLib\\\\Channel\\\\AMQPChannel\\|null\\.$#"
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Parameter \\#1 \\$data of function unserialize expects string, mixed given\\.$#"
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Parameter \\#1 \\$maxIterations of method Drupal\\\\rabbitmq\\\\Consumer\\:\\:hitIterationsLimit\\(\\) expects int, mixed given\\.$#"
+			count: 2
+			path: src/Consumer.php
+
+		-
+			message: "#^Parameter \\#1 \\$memoryLimit of method Drupal\\\\rabbitmq\\\\Consumer\\:\\:hitMemoryLimit\\(\\) expects int, mixed given\\.$#"
+			count: 3
+			path: src/Consumer.php
+
+		-
+			message: "#^Parameter \\#1 \\$seconds of function pcntl_alarm expects int, mixed given\\.$#"
+			count: 2
+			path: src/Consumer.php
+
+		-
+			message: "#^Parameter \\#3 \\$timeout of method Drupal\\\\rabbitmq\\\\Consumer\\:\\:getCallback\\(\\) expects int, mixed given\\.$#"
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Parameter \\#3 \\$timeout of method PhpAmqpLib\\\\Channel\\\\AbstractChannel\\:\\:wait\\(\\) expects float\\|int\\|null, mixed given\\.$#"
+			count: 1
+			path: src/Consumer.php
+
+		-
+			message: "#^Cannot call method getServerProperties\\(\\) on PhpAmqpLib\\\\Connection\\\\AbstractConnection\\|null\\.$#"
+			count: 1
+			path: src/Controller/StatusController.php
+
+		-
+			message: "#^\\\\Drupal calls should be avoided in classes, use dependency injection instead$#"
+			count: 1
+			path: src/Controller/StatusController.php
+
+		-
+			message: "#^Access to an undefined property object\\:\\:\\$id\\.$#"
+			count: 5
+			path: src/Queue/Queue.php
+
+		-
+			message: "#^Method Drupal\\\\rabbitmq\\\\Queue\\\\Queue\\:\\:createItem\\(\\) has parameter \\$data with no type specified\\.$#"
+			count: 1
+			path: src/Queue/Queue.php
+
+		-
+			message: "#^Method Drupal\\\\rabbitmq\\\\Queue\\\\Queue\\:\\:createItem\\(\\) should return bool but returns string\\|false\\.$#"
+			count: 1
+			path: src/Queue/Queue.php
+
+		-
+			message: "#^Method Drupal\\\\rabbitmq\\\\Queue\\\\Queue\\:\\:createQueue\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: src/Queue/Queue.php
+
+		-
+			message: "#^Parameter \\#1 \\$array of function array_slice expects array, mixed given\\.$#"
+			count: 1
+			path: src/Queue/Queue.php
+
+		-
+			message: "#^\\\\Drupal calls should be avoided in classes, use dependency injection instead$#"
+			count: 2
+			path: src/Queue/Queue.php
+
+		-
+			message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
+			count: 2
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'auto_delete' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'durable' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'internal' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'name' on mixed\\.$#"
+			count: 4
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'nowait' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'passive' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'type' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot call method channel\\(\\) on PhpAmqpLib\\\\Connection\\\\AbstractConnection\\|null\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot call method queue_bind\\(\\) on PhpAmqpLib\\\\Channel\\\\AMQPChannel\\|null\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Dead catch \\- PhpAmqpLib\\\\Exception\\\\AMQPProtocolChannelException is never thrown in the try block\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^If condition is always true\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#1 \\$exchange of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects string, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#2 \\$type of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects string, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#3 \\$passive of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects bool, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#4 \\$durable of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects bool, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#5 \\$auto_delete of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects bool, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#6 \\$internal of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects bool, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Parameter \\#7 \\$nowait of method PhpAmqpLib\\\\Channel\\\\AMQPChannel\\:\\:exchange_declare\\(\\) expects bool, mixed given\\.$#"
+			count: 1
+			path: src/Queue/QueueBase.php
+
+		-
+			message: "#^Cannot access offset 'queue_default' on mixed\\.$#"
+			count: 1
+			path: src/Queue/QueueFactory.php
+
+		-
+			message: "#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\\.$#"
+			count: 1
+			path: src/RabbitmqServiceProvider.php
+
+		-
+			message: "#^Access to an undefined property object\\:\\:\\$data\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Cannot access an offset on mixed\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Cannot access offset string on mixed\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Cannot access property \\$created on bool\\|object\\.$#"
+			count: 2
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Cannot access property \\$data on bool\\|object\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Cannot access property \\$item_id on bool\\|object\\.$#"
+			count: 2
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:alter\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:testCreateAndClaimObjects\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:testItemId\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:testMissingQueueNameException\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:testQueueConfigSave\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:testQueuePriority\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Kernel\\\\RabbitMqQueueBaseTest\\:\\:testTimestamp\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqQueueBaseTest.php
+
+		-
+			message: "#^Cannot access an offset on mixed\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqTestBase.php
+
+		-
+			message: "#^Cannot use array destructuring on array\\|null\\.$#"
+			count: 1
+			path: tests/src/Kernel/RabbitMqTestBase.php
+
+		-
+			message: "#^Access to an undefined property object\\:\\:\\$created\\.$#"
+			count: 1
+			path: tests/src/Unit/QueueTest.php
+
+		-
+			message: "#^Access to an undefined property object\\:\\:\\$item_id\\.$#"
+			count: 1
+			path: tests/src/Unit/QueueTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Unit\\\\QueueTest\\:\\:testClaimItemTimestamp\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Unit/QueueTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Unit\\\\QueueTest\\:\\:testCreateItemId\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Unit/QueueTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Unit\\\\QueueTest\\:\\:testCreateItemTimestamp\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Unit/QueueTest.php
+
+		-
+			message: "#^Method Drupal\\\\Tests\\\\rabbitmq\\\\Unit\\\\QueueTest\\:\\:testItemIdFromClaimItem\\(\\) has no return type specified\\.$#"
+			count: 1
+			path: tests/src/Unit/QueueTest.php
diff --git a/phpstan.neon b/phpstan.neon
new file mode 100644
index 0000000..19661a3
--- /dev/null
+++ b/phpstan.neon
@@ -0,0 +1,18 @@
+parameters:
+	fileExtensions:
+	    - php
+	    - module
+	    - install
+	paths:
+		- ./
+	excludePaths:
+		- web
+		- vendor
+		- expand_composer_json.php
+		- symlink_project.php
+	level: 9
+	ignoreErrors:
+		- '#Unsafe usage of new static\(\)#'
+	checkMissingIterableValueType: false
+includes:
+	- phpstan-baseline.neon
\ No newline at end of file
-- 
GitLab