Skip to content

Commit

Permalink
Merge branch 'gh-actions' into beta
Browse files Browse the repository at this point in the history
  • Loading branch information
fedys committed May 30, 2024
2 parents 3aa8e62 + 3bd500d commit 9599090
Show file tree
Hide file tree
Showing 14 changed files with 6,295 additions and 15 deletions.
145 changes: 145 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
name: Mautic Build and Test

on:
push:
branches:
- staging # Main branch
- '[0-9]+\.[0-9]+'
- development
- beta
pull_request:

env:
PLUGIN_DIR: plugins/CustomObjectsBundle # Same as extra.install-directory-name in composer.json

jobs:
phpunit:
runs-on: ubuntu-latest

strategy:
matrix:
php-versions: ['7.4', '8.0'] # The supported PHP versions
db-types: ['mysql'] # can be: ['mysql', 'mariadb'] but not necessary for this plugin that does not add any DB schema
mautic-versions: ['4.4'] # The supported Mautic versions

name: Tests on PHP ${{ matrix.php-versions }}, ${{ matrix.db-types }}, Mautic ${{ matrix.mautic-versions }}

services:
database:
image: ${{ matrix.db-types == 'mysql' && 'mysql:8.0' || 'mariadb:10.3' }}
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: mautictest
ports:
- 3306
options: >-
--shm-size=2gb
--name=${{ matrix.db-types }}
--tmpfs=/var/lib/mysql
--health-cmd="mysqladmin ping"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- name: Checkout Mautic
uses: actions/checkout@v4
with:
repository: mautic/mautic
ref: ${{ matrix.mautic-versions }}

- name: Checkout this plugin
uses: actions/checkout@v4
with:
path: ${{ env.PLUGIN_DIR }}

- name: Setup PHP, with composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
ini-values: -dpcov.enabled=0, pcov.directory=."
extensions: mbstring, xml, ctype, iconv, intl, pdo_sqlite, mysql, pdo_mysql
coverage: pcov

- name: add MySQL config file
run: |
mysqldump --version
mysqldump --print-defaults
cp .github/ci-files/.my.cnf ~/.my.cnf
mysqldump --print-defaults
- name: Set SYMFONY_ENV to test
run: |
echo "SYMFONY_ENV=test" >> $GITHUB_ENV
echo "MAUTIC_ENV=test" >> $GITHUB_ENV
- name: Install Composer dependencies
run: |
composer install
# - name: Get composer cache directory
# id: composer-cache
# run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

# - name: Cache composer dependencies
# uses: actions/cache@v4
# with:
# path: ${{ steps.composer-cache.outputs.dir }}
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
# restore-keys: ${{ runner.os }}-composer-

- name: Install Mautic
env:
DB_PORT: ${{ job.services.database.ports[3306] }}
run: |
cp ./.github/ci-files/local.php ./app/config/local.php
php bin/console mautic:install --force http://localhost
- name: Install Plugins
env:
DB_PORT: ${{ job.services.database.ports[3306] }}
run: php bin/console mautic:plugins:install --env=dev

# - name: Run static analysis
# env:
# COMPOSER_ALLOW_SUPERUSER: 1
# run: composer phpstan -- --no-progress

- name: Run Code Style check
run: bin/php-cs-fixer fix ${{ env.PLUGIN_DIR }} --config=.php-cs-fixer.php -v --dry-run --show-progress=dots --diff

# - name: PHPSTAN - baseline (debug, enable if you need to regenerate baseline for all PHP versions)
# run: bin/phpstan --configuration=${{ env.PLUGIN_DIR }}/phpstan.neon --generate-baseline=var/logs/phpstan-baseline-${{ matrix.php-versions }}.neon --allow-empty-baseline

- name: PHPSTAN
run: bin/phpstan --configuration=${{ env.PLUGIN_DIR }}/phpstan.neon

- name: Rector
run: composer rector -- --dry-run --no-progress-bar ${{ env.PLUGIN_DIR }}

- name: Twig Lint
run: bin/console lint:twig ${{ env.PLUGIN_DIR }}

- name: Run PHPUNIT tests
env:
DB_PORT: ${{ job.services.database.ports[3306] }}
# run: XDEBUG_MODE=coverage APP_DEBUG=0 php -dpcov.enabled=1 -dpcov.directory=. -dpcov.exclude="~tests|themes|vendor~" bin/phpunit -d memory_limit=1G --bootstrap vendor/autoload.php --configuration ${{ env.PLUGIN_DIR }}/phpunit.xml --coverage-clover=${{ env.PLUGIN_DIR }}/coverage.xml --coverage-text
run: XDEBUG_MODE=coverage APP_DEBUG=0 php -dpcov.enabled=1 -dpcov.directory=. bin/phpunit -d memory_limit=1G --bootstrap vendor/autoload.php --configuration ${{ env.PLUGIN_DIR }}/phpunit.xml --filter=CustomObjectsBundle --coverage-clover=${{ env.PLUGIN_DIR }}/coverage.xml --coverage-text

# - name: Coverage report (debug)
# run: cat ${{ env.PLUGIN_DIR }}/coverage.xml

# - name: Upload coverage report
# if: ${{ matrix.php-versions == '8.0' && matrix.db-types == 'mysql' && matrix.mautic-versions == '4.4' }} # upload just once, change for your matrix
# uses: codecov/codecov-action@v3
# with:
# token: ${{ secrets.CODECOV_TOKEN }}
# fail_ci_if_error: true
# working-directory: ${{ env.PLUGIN_DIR }}
# verbose: true

- name: Upload logs as artifacts
uses: actions/upload-artifact@v3
with:
name: mautic-logs
path: var/logs/
3 changes: 0 additions & 3 deletions Command/GenerateSampleDataCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,10 @@ function ($value) {
switch (gettype($value)) {
case 'string':
return "'$value'";
break;
case 'integer':
return (string) $value;
break;
case 'boolean':
return (bool) $value;
break;
default:
$type = gettype($value);
throw new \InvalidArgumentException("Unsupported type '$type' for insert query");
Expand Down
2 changes: 0 additions & 2 deletions CustomFieldType/PhoneType.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ public function validateValue(CustomField $customField, $value): void
$phoneNumber = $phoneUtil->parse($value, PhoneNumberUtil::UNKNOWN_REGION);
} catch (NumberParseException $e) {
throw new \UnexpectedValueException($message);

return;
}

if (false === $phoneUtil->isValidNumber($phoneNumber)) {
Expand Down
10 changes: 5 additions & 5 deletions EventListener/CampaignSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ public function onCampaignTriggerCondition(CampaignExecutionEvent $event): void
);

if ($innerQueryBuilder instanceof UnionQueryContainer) {
$this->applyParamsToMultipleQueries($innerQueryBuilder, $queryAlias, $contact, $operator);
$this->applyParamsToMultipleQueries($innerQueryBuilder, $queryAlias, $contact);
} else {
$this->applyParamsToQuery($innerQueryBuilder, $queryAlias, $contact, $operator);
$this->applyParamsToQuery($innerQueryBuilder, $queryAlias, $contact);
}

$queryBuilder = $this->buildOuterQuery($innerQueryBuilder, $queryAlias);
Expand All @@ -238,14 +238,14 @@ public function onCampaignTriggerCondition(CampaignExecutionEvent $event): void
}
}

private function applyParamsToMultipleQueries(UnionQueryContainer $unionQueryContainer, string $queryAlias, Lead $contact, string $operator): void
private function applyParamsToMultipleQueries(UnionQueryContainer $unionQueryContainer, string $queryAlias, Lead $contact): void
{
foreach ($unionQueryContainer as $segmentQueryBuilder) {
$this->applyParamsToQuery($segmentQueryBuilder, $queryAlias, $contact, $operator);
$this->applyParamsToQuery($segmentQueryBuilder, $queryAlias, $contact);
}
}

private function applyParamsToQuery(SegmentQueryBuilder $innerQueryBuilder, string $queryAlias, Lead $contact, string $operator): void
private function applyParamsToQuery(SegmentQueryBuilder $innerQueryBuilder, string $queryAlias, Lead $contact): void
{
$innerQueryBuilder->select($queryAlias.'_value.custom_item_id');
$this->queryFilterHelper->addContactIdRestriction($innerQueryBuilder, $queryAlias, (int) $contact->getId());
Expand Down
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ See [Wiki](https://github.com/acquia/mc-cs-plugin-custom-objects/wiki)

The plugin has currently test coverage of 91%. Each new PR must be covered by tests to be considered to be merged. To run the tests execute `composer test -- --filter CustomObjects` from the Mautic root dir.

## Static Analysis

PHPSTAN is used for static analysis. Here is how to run it locally from the Mautic's root dir:
```
bin/phpstan --configuration=plugins/CustomObjectsBundle/phpstan.neon
```

This plugin has its own PHPSTAN configuration because there is too big tech debt pile already and so it must have its own PHPSTAN baseline file.

The tech debt is visible in the phpstan-baseline.neon file and can be regenerated with:
```
bin/phpstan --configuration=plugins/CustomObjectsBundle/phpstan.neon --generate-baseline=plugins/CustomObjectsBundle/phpstan-baseline.neon && sed -i 's/plugins\/CustomObjectsBundle\//g' plugins/CustomObjectsBundle/phpstan-neon.php
```
Please do not add more tech debt on this pile. Fix all the new PHPSTAN errors and possibly some old ones with your code changes.

## License

Copyright (C) 2022 Acquia, Inc.
Expand Down
19 changes: 19 additions & 0 deletions Tests/Functional/DataFixtures/Traits/FixtureObjectsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ trait FixtureObjectsTrait
*/
public function setFixtureObjects(array $objects): void
{
$this->skipIfMissingDependency();

foreach ($objects as $key => $object) {
$this->objects[get_class($object)][$key] = $object;
$this->entityMap[$key] = get_class($object);
Expand All @@ -45,6 +47,8 @@ public function setFixtureObjects(array $objects): void
*/
public function getFixturesByEntityClassName(string $type): array
{
$this->skipIfMissingDependency();

if (!isset($this->objects[$type])) {
throw new FixtureNotFoundException('No fixtures of type '.$type.' defined');
}
Expand All @@ -57,6 +61,8 @@ public function getFixturesByEntityClassName(string $type): array
*/
public function getFixtureByEntityClassNameAndIndex(string $type, int $index): CommonEntity
{
$this->skipIfMissingDependency();

$fixtures = $this->getFixturesByEntityClassName($type);

$fixtures = array_values($fixtures);
Expand All @@ -75,6 +81,8 @@ public function getFixtureByEntityClassNameAndIndex(string $type, int $index): C
*/
public function getFixtureById(string $id): UniqueEntityInterface
{
$this->skipIfMissingDependency();

if (!isset($this->entityMap[$id])) {
throw new FixtureNotFoundException('No fixture with id "'.$id.'"" defined');
}
Expand All @@ -87,6 +95,8 @@ public function getFixtureById(string $id): UniqueEntityInterface
*/
public function getFixturesInUnloadableOrder(): array
{
$this->skipIfMissingDependency();

$entities = [];

$orderedKeys = $this->entityMap;
Expand All @@ -100,6 +110,8 @@ public function getFixturesInUnloadableOrder(): array

private function getFixturesDirectory(): string
{
$this->skipIfMissingDependency();

/** @var KernelInterface $kernel */
$kernel = $this->getContainer()->get('kernel');
$pluginDirectory = $kernel->locateResource('@CustomObjectsBundle');
Expand All @@ -110,4 +122,11 @@ private function getFixturesDirectory(): string

return $pluginDirectory.'/Tests/Functional/DataFixtures/ORM/Data';
}

private function skipIfMissingDependency(): void
{
if (!self::$container->has('fidry_alice_data_fixtures.loader.doctrine')) {
$this->markTestSkipped('This test requires the theofidry/alice-data-fixtures package');
}
}
}
10 changes: 10 additions & 0 deletions Tests/Functional/EventListener/CampaignConditionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,23 @@
use MauticPlugin\CustomObjectsBundle\Tests\Functional\DataFixtures\Traits\CustomObjectsTrait;
use PHPUnit\Framework\Assert;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy;

class CampaignConditionTest extends MauticMysqlTestCase
{
use CustomObjectsTrait;

public function testConditionForm(): void
{
$session = self::$container->get('session');
// @phpstan-ignore-next-line Fixing "cannot serialize anonymous function in \Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage::save()
$session->__construct(new MockArraySessionStorage());

$sessionAuthenticationStrategy = self::$container->get('security.authentication.session_strategy');
// @phpstan-ignore-next-line Prevent clearing CSRF token storage in \Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy::onAuthentication()
$sessionAuthenticationStrategy->__construct(SessionAuthenticationStrategy::MIGRATE);

$customObject = $this->createCustomObjectWithAllFields(self::$container, 'Campaign test object');
$crawler = $this->client->request(
Request::METHOD_GET,
Expand Down
2 changes: 1 addition & 1 deletion Tests/Unit/Helper/QueryFilterFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class QueryFilterFactoryTest extends TestCase
*/
private $segmentFilter;

private string $prefix = '';
private ?string $prefix = '';

public function setUp(): void
{
Expand Down
4 changes: 4 additions & 0 deletions Tests/Unit/Model/CustomItemImportModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ protected function setUp(): void
$this->descriptionField->method('getTypeObject')->willReturn($textareaType);
$this->dateField->method('getId')->willReturn(34);
$this->dateField->method('getTypeObject')->willReturn($dateTimeType);

if (!method_exists(LeadRepository::class, 'exists')) {
$this->markTestSkipped();
}
}

public function testImportForCreated(): void
Expand Down
Loading

0 comments on commit 9599090

Please sign in to comment.