diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 20f3af2..21429e7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,8 @@ -on: +--- + +name: build + +on: # yamllint disable-line rule:truthy push: branches: - master @@ -6,55 +10,54 @@ on: - '*.*.*' pull_request: null -name: build - jobs: test: name: Test PHP ${{ matrix.php-versions }} with Code Coverage runs-on: ubuntu-latest strategy: matrix: - php-versions: ['8.0', '8.1', '8.2', '8.3'] + php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout + - name: Install ODBC driver. + run: | + sudo curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list + sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 + + - name: 📦 Checkout uses: actions/checkout@v2 - - name: Setup DB services + - name: 🛠️ Setup DB services run: | cd tests docker compose up -d cd .. - - name: Setup PHP ${{ matrix.php-versions }} + - name: 🛠️ Setup PHP ${{ matrix.php-versions }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} coverage: pcov tools: pecl extensions: mbstring, pdo, pdo_sqlite, pdo_pgsql, pdo_sqlsrv, pdo_mysql - - name: Get Composer Cache Directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Restore Composer Cache - uses: actions/cache@v2 + + - name: Validate composer.json and composer.lock + run: composer validate --ansi --strict + + - name: 📥 Install dependencies with composer + uses: ramsey/composer-install@v3 with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install dependencies with composer - if: matrix.php-versions != '8.3' - run: composer update --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - name: Install dependencies with composer php 8.3 - if: matrix.php-versions == '8.3' - run: composer update --ignore-platform-reqs --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi - - name: Execute Tests + dependency-versions: "highest" + + - name: 🚀 Execute Tests run: | vendor/bin/phpunit --coverage-clover=coverage.clover - - name: Upload coverage to Codecov + + - name: 🦆 Upload coverage to Codecov continue-on-error: true # if is fork uses: codecov/codecov-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.clover - - name: Upload coverage to Scrutinizer + + - name: 🦆 Upload coverage to Scrutinizer continue-on-error: true # if is fork uses: sudo-bot/action-scrutinizer@latest with: @@ -64,32 +67,31 @@ jobs: name: SQLite PHP ${{ matrix.php-versions }} runs-on: ubuntu-latest strategy: - fail-fast: false matrix: - php-versions: ['8.0', '8.1'] + php-versions: ['8.0', '8.1', '8.2', '8.3', '8.4'] steps: - - name: Checkout + - name: 📦 Checkout uses: actions/checkout@v2 - - name: Setup PHP ${{ matrix.php-versions }} + - name: 🛠️ Setup PHP ${{ matrix.php-versions }} uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-versions }} coverage: pcov tools: pecl extensions: mbstring, pdo, pdo_sqlite - - name: Get Composer Cache Directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: Restore Composer Cache - uses: actions/cache@v2 + + - name: 🤖 Validate composer.json and composer.lock + run: composer validate --ansi --strict + + - name: 📥 Install dependencies with composer + uses: ramsey/composer-install@v3 with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} - restore-keys: ${{ runner.os }}-composer- - - name: Install Dependencies - run: composer install --no-interaction --prefer-dist - - name: Execute Tests + dependency-versions: "highest" + + - name: 🚀 Execute Tests env: DB: sqlite run: | - vendor/bin/phpunit tests/Schema/Driver/SQLite --colors=always + vendor/bin/phpunit --group driver-sqlite --colors=always + +... diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d1d132e..9d9912c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ To test Cycle ORM Schema Builder locally, download the `cycle/schema-builder` re ```bash $ cd tests/ -$ docker-composer up +$ docker compose up ``` To run full test suite: diff --git a/composer.json b/composer.json index 85e415c..73a0725 100644 --- a/composer.json +++ b/composer.json @@ -38,7 +38,7 @@ "require-dev": { "phpunit/phpunit": "^9.5", "spiral/tokenizer": "^2.8", - "vimeo/psalm": "^5.12", + "vimeo/psalm": "^5.12 || ^6.12", "symfony/console": "^6.0 || ^7.0", "spiral/code-style": "^2.2" }, diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 6804979..aeb576b 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -1,5 +1,5 @@ - + @@ -17,6 +17,17 @@ getOuterKey()]]> + + + + + + + + + + + @@ -25,13 +36,40 @@ + + + + ]]> + + + + + + + + + + + + + + + + + + + + + + + column)]]> type)]]> @@ -45,12 +83,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -58,33 +145,128 @@ target === null]]> type === null]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + entity->getFields()->getNames()]]> + + + + + + + entity->getFields()->getNames()]]> + + + + + + + entity->getFields()->getNames()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getColumns()]]> getColumns()]]> @@ -113,24 +295,80 @@ + + + + + + + + + + + + + + + + + + + + + + reflector->sortedTables()]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -151,14 +389,6 @@ - - - - - - - - children[$entity]]]> relations[$entity]]]> @@ -167,28 +397,61 @@ tables[$entity]['schema']]]> tables[$entity]['table']]]> + + + + + + + + + + + options->get(self::INDEX_CREATE)]]> + + + + + + + + + + options->get(self::INDEX_CREATE)]]> + + + + + + options->get(self::INDEX_CREATE)]]> + + + + + + options->get(Relation::THROUGH_ENTITY)]]> options->get(self::INDEX_CREATE)]]> @@ -204,6 +467,12 @@ + + + + + + @@ -223,6 +492,10 @@ + + + + options->get(Relation::MORPH_KEY)]]> options->get(Relation::NULLABLE)]]> @@ -230,6 +503,10 @@ + + + + options->get(Relation::MORPH_KEY)]]> options->get(Relation::NULLABLE)]]> @@ -270,6 +547,10 @@ + + + + options->get(self::INDEX_CREATE)]]> @@ -313,6 +594,12 @@ + + + + + + @@ -326,6 +613,9 @@ + + + @@ -375,6 +665,16 @@ + + + + + + + + + + @@ -384,12 +684,23 @@ + + + + + + + + + + + @@ -399,9 +710,6 @@ field->getAttributes())]]> - - - getEnumValues()[0]]]> diff --git a/src/Table/Column.php b/src/Table/Column.php index 65bd383..3e1d86e 100644 --- a/src/Table/Column.php +++ b/src/Table/Column.php @@ -59,6 +59,11 @@ public static function parse(Field $field): self return $column; } + /** + * Get column name. + * + * @psalm-suppress UnusedMethod + */ public function getName(): string { return $this->field->getColumn(); @@ -67,6 +72,7 @@ public function getName(): string /** * Get column type. * + * @psalm-suppress UnusedMethod */ public function getType(): string { @@ -140,11 +146,7 @@ public function render(AbstractColumn $column): void if ($this->hasDefault() && $this->getDefault() !== null) { $column->defaultValue($this->getDefault()); - return; - } - - if ($this->hasOption(self::OPT_CAST_DEFAULT)) { - // cast default value + } elseif ($this->hasOption(self::OPT_CAST_DEFAULT)) { $column->defaultValue($this->castDefault($column)); } diff --git a/tests/Schema/Driver/MySQL/ColumnTest.php b/tests/Schema/Driver/MySQL/ColumnTest.php index 6fe1f2a..5fa9291 100644 --- a/tests/Schema/Driver/MySQL/ColumnTest.php +++ b/tests/Schema/Driver/MySQL/ColumnTest.php @@ -36,4 +36,60 @@ public function testAttributesUnsigned(): void $this->assertTrue($table->column('name')->getAttributes()['unsigned']); $this->assertTrue($table->column('name')->isUnsigned()); } + + public function testUnsignedColumnWithAdditionalAttributes(): void + { + $comment = 'Foo Bar Baz'; + + $field = new Field(); + $field->setType('boolean'); + $field->setColumn('foo'); + $field->getAttributes()->set('comment', $comment); + $field->getAttributes()->set('unsigned', true); + + $table = $this->getStub(); + $column = Column::parse($field); + + $column->render($table->column('foo')); + + $table->save(); + + $table = $this->getStub(); + $this->assertTrue($table->hasColumn('foo')); + $this->assertArrayHasKey('comment', $table->column('foo')->getAttributes()); + $this->assertArrayHasKey('unsigned', $table->column('foo')->getAttributes()); + $this->assertSame($comment, $table->column('foo')->getAttributes()['comment']); + $this->assertSame($comment, $table->column('foo')->getComment()); + $this->assertTrue($table->column('foo')->getAttributes()['unsigned']); + $this->assertTrue($table->column('foo')->isUnsigned()); + } + + public function testUnsignedColumnWithAdditionalAttributesAndDefault(): void + { + $comment = 'Foo Bar Baz'; + + $field = new Field(); + $field->setType('boolean'); + $field->setColumn('foo'); + $field->getAttributes()->set('comment', $comment); + $field->getAttributes()->set('unsigned', true); + $field->getOptions()->set('default', false); + + $table = $this->getStub(); + $column = Column::parse($field); + + $column->render($table->column('foo')); + + $table->save(); + + $table = $this->getStub(); + $this->assertTrue($table->hasColumn('foo')); + $this->assertArrayHasKey('comment', $table->column('foo')->getAttributes()); + $this->assertArrayHasKey('unsigned', $table->column('foo')->getAttributes()); + $this->assertSame(0, $table->column('foo')->getDefaultValue()); + $this->assertSame($comment, $table->column('foo')->getAttributes()['comment']); + $this->assertSame($comment, $table->column('foo')->getComment()); + $this->assertTrue($table->column('foo')->getAttributes()['unsigned']); + $this->assertTrue($table->column('foo')->isUnsigned()); + } } diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b23e6b9..22af149 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -47,6 +47,7 @@ database: 'tempdb', host: '127.0.0.1', port: 11433, + trustServerCertificate: true, user: 'SA', password: 'YourStrong!Passw0rd', ),