diff --git a/.editorconfig b/.editorconfig index 898c45c9..bad52845 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,3 +9,6 @@ max_line_length = 160 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.github/workflows/security.yaml b/.github/workflows/security.yaml new file mode 100644 index 00000000..329983e8 --- /dev/null +++ b/.github/workflows/security.yaml @@ -0,0 +1,23 @@ +on: + schedule: + - cron: '0 12 * * *' + workflow_dispatch: + +jobs: + job: + name: "Security" + runs-on: "ubuntu-latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + with: + show-progress: false + + - name: "Setup PHP" + uses: "shivammathur/setup-php@v2" + with: + php-version: '7.4.1' + + - name: "Run composer audit" + run: "composer audit --no-dev --locked" diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 00000000..682363ef --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,104 @@ +name: "Tests" + +concurrency: + group: "tests-${{ github.head_ref || github.run_id }}" + cancel-in-progress: true + +on: + pull_request: + push: + branches: [master] + +jobs: + tests: + name: "PHP ${{ matrix.php }} | PostgreSQL ${{ matrix.postgresql }}" + runs-on: "ubuntu-latest" + container: + image: "php:${{ matrix.php-version }}-cli-alpine" + env: + DATABASE_URL: "postgresql://main:main@postgresql:5432/main?serverVersion=${{ matrix.postgresql }}&charset=utf8" + services: + postgresql: + image: "postgres:${{ matrix.postgresql-version }}-alpine" + env: + POSTGRES_USER: main + POSTGRES_PASSWORD: main + POSTGRES_DB: main + + strategy: + fail-fast: false + matrix: + php: + - "7.4" + postgresql: + - "11" + include: + - php: "7.4" + php-version: "7.4.1" + - postgresql: "11" + postgresql-version: "11.7" + + steps: + - name: "Install OS dependencies" + run: "apk add --no-cache bash git icu-dev libzip-dev unzip zip" + + - name: "Adjust allowed PHP memory" + run: echo 'memory_limit = -1' > $PHP_INI_DIR/conf.d/memory-limit.ini; + + - name: "Install PHP extensions" + shell: bash + run: | + wget https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions --quiet -O /usr/local/bin/install-php-extensions + chmod +x /usr/local/bin/install-php-extensions + install-php-extensions intl pdo_pgsql zip + + - name: "Install composer" + run: curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin --filename=composer --version=2.6.6 + + - name: "Checkout" + uses: "actions/checkout@v4" + with: + ref: "${{ github.event.ref }}" + show-progress: false + + - name: "Install composer dependencies" + uses: "ramsey/composer-install@v2" + + - name: "Validate composer dependencies" + run: "composer validate" + + - name: "Check code style" + run: "composer check-cs" + + - name: "Run PHPStan" + run: "composer phpstan" + + - name: "Lint twig" + run: "bin/console lint:twig templates --show-deprecations" + + - name: "Run migrations" + run: "bin/console doctrine:migrations:migrate --no-interaction" + + - name: "Setup messenger transports" + run: "bin/console messenger:setup-transports" + + - name: "Validate database schema" + run: "bin/console doctrine:schema:validate" + + - name: "Set git committer info" + shell: bash + run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR_ID}+${GITHUB_ACTOR}@users.noreply.github.com" + + - name: "Run unit tests" + run: "composer phpunit:unit" + + - name: "Run integration tests" + run: "composer phpunit:integration" + + - name: "Run functional tests" + run: "composer phpunit:functional" + + - name: "Warmup prod cache" + run: "bin/console cache:warmup --env=prod" diff --git a/buddy.yml b/buddy.yml index 4cb539ba..b3e7f706 100644 --- a/buddy.yml +++ b/buddy.yml @@ -1,108 +1,3 @@ -- pipeline: "test" - trigger_mode: "ON_EVERY_PUSH" - ref_name: "refs/*" - ref_type: "WILDCARD" - fetch_all_refs: true - trigger_condition: "ALWAYS" - actions: - - action: "Execute: composer tests" - type: "BUILD" - working_directory: "/buddy/repman" - docker_image_name: "library/php" - docker_image_tag: "7.4.1" - execute_commands: - - "composer validate" - - "composer install" - - "rm -rf var/cache" - - "composer reset-db" - - "composer tests" - - "bash <(curl -s https://codecov.io/bash)" - setup_commands: - - "apt-get update && apt-get install -y git zip" - - "curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer" - - "" - - "# php ext pdo_pgsql" - - "apt-get install -y libpq-dev" - - "docker-php-ext-configure pdo_pgsql --with-pdo-pgsql" - - "docker-php-ext-install pdo_pgsql" - - "" - - "# coverage driver" - - "pecl install pcov && docker-php-ext-enable pcov" - - "" - - "# intl" - - "apt-get install -y libicu-dev && \\" - - " docker-php-ext-configure intl && \\" - - " docker-php-ext-install intl" - - "" - - "# zip" - - "apt-get install -y zip unzip libzip-dev" - - "docker-php-ext-configure zip" - - "docker-php-ext-install zip" - - " " - - "echo \"memory_limit=-1\" >> /usr/local/etc/php/conf.d/buddy.ini" - - "git config --global user.email \"buddy@repman.io\"" - "git config --global user.name \"buddy.works\"" - services: - - type: "POSTGRE_SQL" - version: "11.6-alpine" - connection: - host: "postgres" - port: 5432 - user: "main" - password: "main" - db: "main" - volume_mappings: - - "/:/buddy/repman" - trigger_condition: "ALWAYS" - shell: "BASH" - - action: "Run repman/deploy" - type: "RUN_NEXT_PIPELINE" - comment: "Triggered by $BUDDY_PIPELINE_NAME execution #$BUDDY_EXECUTION_ID" - trigger_condition: "VAR_IS" - trigger_variable_value: "master" - trigger_variable_key: "BUDDY_EXECUTION_BRANCH" - revision: "INHERIT" - next_project_name: "repman" - next_pipeline_name: "deploy" - variables: - - key: "DATABASE_URL" - value: "postgresql://main:main@postgres:5432/main?serverVersion=11&charset=utf8" - id: 352921 - description: "" -- pipeline: "security" - trigger_mode: "SCHEDULED" - ref_name: "master" - ref_type: "BRANCH" - priority: "NORMAL" - start_date: "2020-02-05T07:00:00Z" - delay: 1440 - fetch_all_refs: true - trigger_condition: "ALWAYS" - actions: - - action: "Execute: composer security" - type: "BUILD" - working_directory: "/buddy/repman" - docker_image_name: "library/php" - docker_image_tag: "7.4.1" - execute_commands: - - "/local-php-security-checker" - setup_commands: - - "curl -L https://github.com/fabpot/local-php-security-checker/releases/download/v1.0.0/local-php-security-checker_1.0.0_linux_amd64 --output local-php-security-checker" - - "chmod 0755 local-php-security-checker" - volume_mappings: - - "/:/buddy/repman" - trigger_condition: "ALWAYS" - shell: "BASH" - - action: "Send notification to Telegram" - type: "TELEGRAM" - trigger_time: "ON_FAILURE" - content: "[#$BUDDY_EXECUTION_ID] $BUDDY_PIPELINE_NAME failed execution by [$BUDDY_INVOKER_NAME]($BUDDY_INVOKER_URL)" - parse_mode: "MARKDOWN" - trigger_condition: "ALWAYS" - integration_hash: "5f4f3794fd5a7366872df494" - variables: - - key: "DATABASE_URL" - value: "postgresql://main:main@postgres:5432/main?serverVersion=11&charset=utf8" - pipeline: "setup" trigger_mode: "MANUAL" ref_name: "refs/heads/*" diff --git a/composer.json b/composer.json index 2cce648e..a94ccc0d 100644 --- a/composer.json +++ b/composer.json @@ -164,10 +164,21 @@ ], "phpstan": [ "bin/console cache:clear --env=test", - "phpstan analyse --level=max" + "phpstan analyse --level=max --memory-limit=-1" ], "phpunit": [ - "phpunit --colors=always" + "@phpunit:unit", + "@phpunit:integration", + "@phpunit:functional" + ], + "phpunit:unit": [ + "phpunit --colors=always --testsuite=unit" + ], + "phpunit:integration": [ + "phpunit --colors=always --testsuite=integration" + ], + "phpunit:functional": [ + "phpunit --colors=always --testsuite=functional" ], "proxy-setup": [ "symfony proxy:start", diff --git a/composer.lock b/composer.lock index 177d9b4d..988f3b0a 100644 --- a/composer.lock +++ b/composer.lock @@ -259,12 +259,12 @@ } }, "autoload": { - "psr-4": { - "Aws\\": "src/" - }, "files": [ "src/functions.php" - ] + ], + "psr-4": { + "Aws\\": "src/" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -733,12 +733,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Clue\\StreamFilter\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "Clue\\StreamFilter\\": "src/" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -3877,12 +3877,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "Laminas\\Code\\": "src/" - }, "files": [ "polyfill/ReflectionEnumPolyfill.php" - ] + ], + "psr-4": { + "Laminas\\Code\\": "src/" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -4749,12 +4749,12 @@ } }, "autoload": { - "psr-4": { - "JmesPath\\": "src/" - }, "files": [ "src/JmesPath.php" - ] + ], + "psr-4": { + "JmesPath\\": "src/" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -5426,12 +5426,12 @@ } }, "autoload": { - "psr-4": { - "Http\\Message\\": "src/" - }, "files": [ "src/filters.php" - ] + ], + "psr-4": { + "Http\\Message\\": "src/" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -10135,15 +10135,15 @@ }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { "Symfony\\Component\\Intl\\": "" }, "classmap": [ "Resources/stubs" ], - "files": [ - "Resources/functions.php" - ], "exclude-from-classmap": [ "/Tests/" ] @@ -11633,12 +11633,12 @@ } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Uuid\\": "" - }, "files": [ "bootstrap.php" - ] + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -14586,12 +14586,12 @@ }, "type": "library", "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" - }, "files": [ "src/DeepCopy/deep_copy.php" - ] + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } }, "notification-url": "https://repo.repman.io/downloads", "license": [ @@ -14920,6 +14920,7 @@ "issues": "https://github.com/PHP-CS-Fixer/diff/issues", "source": "https://github.com/PHP-CS-Fixer/diff/tree/v1.3.1" }, + "abandoned": true, "time": "2020-10-14T08:39:05+00:00" }, { @@ -15915,11 +15916,11 @@ } }, "autoload": { - "classmap": [ - "src/" - ], "files": [ "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" ] }, "notification-url": "https://repo.repman.io/downloads", @@ -17497,5 +17498,5 @@ "ext-zip": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/tests/Unit/Service/Downloader/ReactDownloaderTest.php b/tests/Unit/Service/Downloader/ReactDownloaderTest.php index f6d8b2a1..0e9b3f68 100644 --- a/tests/Unit/Service/Downloader/ReactDownloaderTest.php +++ b/tests/Unit/Service/Downloader/ReactDownloaderTest.php @@ -43,6 +43,9 @@ public function testLastModified(): void $downloader->run(); } + /** + * @doesNotPerformAssertions + */ public function testAsyncContent(): void { $downloader = new ReactDownloader(); diff --git a/tests/Unit/Service/PackageSynchronizer/ComposerPackageSynchronizerTest.php b/tests/Unit/Service/PackageSynchronizer/ComposerPackageSynchronizerTest.php index 79f6039a..0dae3124 100644 --- a/tests/Unit/Service/PackageSynchronizer/ComposerPackageSynchronizerTest.php +++ b/tests/Unit/Service/PackageSynchronizer/ComposerPackageSynchronizerTest.php @@ -136,8 +136,10 @@ public function testSynchronizePackageWithGitLabToken(): void $path = $this->baseDir.'/buddy/p/repman-io/repman.json'; @unlink($path); - $this->synchronizer->synchronize(PackageMother::withOrganizationAndToken('gitlab', $this->resourcesDir.'artifacts', 'buddy')); + $package = PackageMother::withOrganizationAndToken('gitlab', $this->resourcesDir.'artifacts', 'buddy'); + $this->synchronizer->synchronize($package); + self::assertTrue($package->isSynchronizedSuccessfully(), (string) $this->getProperty($package, 'lastSyncError')); self::assertFileExists($path); $json = unserialize((string) file_get_contents($path)); @@ -150,8 +152,10 @@ public function testSynchronizePackageWithGitHubToken(): void $path = $this->baseDir.'/buddy/p/repman-io/repman.json'; @unlink($path); - $this->synchronizer->synchronize(PackageMother::withOrganizationAndToken('github', $this->resourcesDir.'artifacts', 'buddy')); + $package = PackageMother::withOrganizationAndToken('github', $this->resourcesDir.'artifacts', 'buddy'); + $this->synchronizer->synchronize($package); + self::assertTrue($package->isSynchronizedSuccessfully(), (string) $this->getProperty($package, 'lastSyncError')); self::assertFileExists($path); $json = unserialize((string) file_get_contents($path)); @@ -164,8 +168,10 @@ public function testSynchronizePackageWithBitbucketToken(): void $path = $this->baseDir.'/buddy/p/repman-io/repman.json'; @unlink($path); - $this->synchronizer->synchronize(PackageMother::withOrganizationAndToken('bitbucket', $this->resourcesDir.'artifacts', 'buddy')); + $package = PackageMother::withOrganizationAndToken('bitbucket', $this->resourcesDir.'artifacts', 'buddy'); + $this->synchronizer->synchronize($package); + self::assertTrue($package->isSynchronizedSuccessfully(), (string) $this->getProperty($package, 'lastSyncError')); self::assertFileExists($path); $json = unserialize((string) file_get_contents($path)); diff --git a/tests/Unit/Service/Security/SensioLabsSecurityCheckerTest.php b/tests/Unit/Service/Security/SensioLabsSecurityCheckerTest.php index bac027b3..a47028d9 100644 --- a/tests/Unit/Service/Security/SensioLabsSecurityCheckerTest.php +++ b/tests/Unit/Service/Security/SensioLabsSecurityCheckerTest.php @@ -141,20 +141,32 @@ public function testUpdateWhenRepoExist(): void private function updateAdvisoriesDatabaseRepo(): void { $this->filesystem->copy($this->repoDir.'/aws/aws-sdk-php/CVE-2015-5723.yaml', $this->repoDir.'/google/google-sdk-php/CVE-2015-5723.yaml'); - (new Process(['git', 'add', '.'], $this->repoDir))->run(); - (new Process(['git', '-c', 'commit.gpgsign=false', 'commit', '-a', '-m', 'New CVE discovered'], $this->repoDir))->run(); + $this->executeCommandInRepoDir(['git', 'add', '.']); + $this->executeCommandInRepoDir(['git', '-c', 'commit.gpgsign=false', 'commit', '-a', '-m', 'New CVE discovered']); } private function createAdvisoriesDatabaseRepo(): void { $this->filesystem->mkdir($this->repoDir); - (new Process(['git', 'init'], $this->repoDir))->run(); + $this->executeCommandInRepoDir(['git', 'init']); $this->filesystem->mirror( __DIR__.'/../../../Resources/fixtures/security/security-advisories', $this->repoDir ); - (new Process(['git', 'add', '.'], $this->repoDir))->run(); - (new Process(['git', '-c', 'commit.gpgsign=false', 'commit', '-a', '-m', 'AD repo'], $this->repoDir))->run(); + $this->executeCommandInRepoDir(['git', 'add', '-A']); + $this->executeCommandInRepoDir(['git', '-c', 'commit.gpgsign=false', 'commit', '-a', '-m', 'Add repo']); + } + + /** + * @param list $command + */ + private function executeCommandInRepoDir(array $command): void + { + $process = new Process($command, $this->repoDir); + $process->run(); + if (!$process->isSuccessful()) { + throw new \RuntimeException(sprintf('Command \'%s\' failed with exit code %d%s', $process->getCommandLine(), $process->getExitCode(), PHP_EOL.$process->getOutput())); + } } private function synchronizeAdvisoriesDatabase(): void