diff --git a/Dockerfile b/Dockerfile index f986772..904f3d3 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM php:7.4 +FROM php:8.2-cli WORKDIR /code diff --git a/cli.php b/cli.php index 97b8f6f..38b8d0d 100644 --- a/cli.php +++ b/cli.php @@ -12,6 +12,7 @@ use Keboola\Console\Command\DescribeOrganizationWorkspaces; use Keboola\Console\Command\LineageEventsExport; use Keboola\Console\Command\MassDedup; +use Keboola\Console\Command\MassDeleteProjectWorkspaces; use Keboola\Console\Command\MassProjectEnableDynamicBackends; use Keboola\Console\Command\MassProjectExtendExpiration; use Keboola\Console\Command\MassProjectQueueMigration; @@ -59,4 +60,5 @@ $application->add(new RemoveUserFromOrganizationProjects()); $application->add(new ReactivateSchedules()); $application->add(new DescribeOrganizationWorkspaces()); +$application->add(new MassDeleteProjectWorkspaces()); $application->run(); diff --git a/composer.json b/composer.json index 9b5d552..be7f3a8 100644 --- a/composer.json +++ b/composer.json @@ -1,16 +1,16 @@ { "name": "keboola/cli-utils", "require": { - "php": "^7.4", + "php": "^8.2", "symfony/console": "^3.1", - "keboola/sandboxes-api-php-client": "^6.25", + "keboola/sandboxes-api-php-client": "^6.31", "keboola/storage-api-client": "^14", "keboola/kbc-manage-api-php-client": "^7", - "symfony/event-dispatcher": "4.1.*", + "symfony/event-dispatcher": "6.4.*", "keboola/job-queue-api-php-client": "^2.2" }, "require-dev": { - "squizlabs/php_codesniffer": "2.*" + "squizlabs/php_codesniffer": "3.*" }, "authors": [ { diff --git a/composer.lock b/composer.lock index 3a0c1e0..5bc83b7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "87d565ff4970d63e9b93a535ab589930", + "content-hash": "1cb691a3a5beacf61fd6bf492bf0438b", "packages": [ { "name": "aws/aws-crt-php", @@ -1030,35 +1030,33 @@ }, { "name": "keboola/sandboxes-api-php-client", - "version": "6.25.0", + "version": "6.31.0", "source": { "type": "git", "url": "https://github.com/keboola/sandboxes-api-php-client.git", - "reference": "bf8f0a4e26f019314c3fbdcc63900a23d4ec66e8" + "reference": "739084bc3fb50a780f33c1981af7bc72f43f0215" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/keboola/sandboxes-api-php-client/zipball/bf8f0a4e26f019314c3fbdcc63900a23d4ec66e8", - "reference": "bf8f0a4e26f019314c3fbdcc63900a23d4ec66e8", + "url": "https://api.github.com/repos/keboola/sandboxes-api-php-client/zipball/739084bc3fb50a780f33c1981af7bc72f43f0215", + "reference": "739084bc3fb50a780f33c1981af7bc72f43f0215", "shasum": "" }, "require": { "ext-json": "*", "guzzlehttp/guzzle": "~6.0|~7.0", - "php": ">=7.4", - "psr/log": "^1.1", - "symfony/validator": "^4.2 !=4.4.33|^5.4|^6.0" + "php": "^8.2", + "psr/log": "^1.1|^2.0|^3.0", + "symfony/validator": "^6.0|^7.0" }, "require-dev": { - "keboola/coding-standard": "^13.0.0", - "keboola/kbc-manage-api-php-client": "^7.0", - "keboola/storage-api-client": "^10.6.0", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/phpstan": "^1.5.0", - "phpstan/phpstan-phpunit": "^1.0.0", - "phpunit/phpunit": "^9.0", - "squizlabs/php_codesniffer": "^3.0", - "vlucas/phpdotenv": "^4.1" + "keboola/coding-standard": "^15.0", + "keboola/kbc-manage-api-php-client": "^7.1", + "keboola/storage-api-client": "^14.15", + "phpstan/phpstan": "^1.10", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.6", + "vlucas/phpdotenv": "^5.6" }, "type": "library", "autoload": { @@ -1082,9 +1080,9 @@ "sandboxes" ], "support": { - "source": "https://github.com/keboola/sandboxes-api-php-client/tree/6.25.0" + "source": "https://github.com/keboola/sandboxes-api-php-client/tree/6.31.0" }, - "time": "2023-08-07T14:39:54+00:00" + "time": "2025-02-19T07:20:50+00:00" }, { "name": "keboola/storage-api-client", @@ -1458,6 +1456,56 @@ }, "time": "2016-08-06T20:24:11+00:00" }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, { "name": "psr/http-client", "version": "1.0.2", @@ -2263,41 +2311,41 @@ }, { "name": "symfony/event-dispatcher", - "version": "v4.1.12", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "51be1b61dfe04d64a260223f2b81475fa8066b97" + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/51be1b61dfe04d64a260223f2b81475fa8066b97", - "reference": "51be1b61dfe04d64a260223f2b81475fa8066b97", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", + "reference": "0ffc48080ab3e9132ea74ef4e09d8dcf26bf897e", "shasum": "" }, "require": { - "php": "^7.1.3" + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2.5|^3" }, "conflict": { - "symfony/dependency-injection": "<3.4" + "symfony/dependency-injection": "<5.4", + "symfony/service-contracts": "<2.5" }, - "require-dev": { - "psr/log": "~1.0", - "symfony/config": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/expression-language": "~3.4|~4.0", - "symfony/stopwatch": "~3.4|~4.0" + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" }, - "suggest": { - "symfony/dependency-injection": "", - "symfony/http-kernel": "" + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "4.1-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" @@ -2320,12 +2368,102 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony EventDispatcher Component", + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.4.13" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:18:03+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v4.1.12" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, - "time": "2019-01-16T18:35:49+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", @@ -2557,17 +2695,17 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php73", + "name": "symfony/polyfill-php80", "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9", - "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", "shasum": "" }, "require": { @@ -2588,7 +2726,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php73\\": "" + "Symfony\\Polyfill\\Php80\\": "" }, "classmap": [ "Resources/stubs" @@ -2599,6 +2737,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -2608,7 +2750,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -2617,7 +2759,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" }, "funding": [ { @@ -2636,17 +2778,17 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php80", + "name": "symfony/polyfill-php81", "version": "v1.27.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", "shasum": "" }, "require": { @@ -2667,7 +2809,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" + "Symfony\\Polyfill\\Php81\\": "" }, "classmap": [ "Resources/stubs" @@ -2678,10 +2820,6 @@ "MIT" ], "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -2691,7 +2829,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -2700,7 +2838,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" }, "funding": [ { @@ -2719,30 +2857,27 @@ "time": "2022-11-03T14:55:06+00:00" }, { - "name": "symfony/polyfill-php81", - "version": "v1.27.0", + "name": "symfony/polyfill-php83", + "version": "v1.31.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + "url": "https://github.com/symfony/polyfill-php83.git", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/2fb86d65e2d424369ad2905e83b236a8805ba491", + "reference": "2fb86d65e2d424369ad2905e83b236a8805ba491", "shasum": "" }, "require": { - "php": ">=7.1" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -2750,7 +2885,7 @@ "bootstrap.php" ], "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" + "Symfony\\Polyfill\\Php83\\": "" }, "classmap": [ "Resources/stubs" @@ -2770,7 +2905,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 8.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -2779,7 +2914,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.31.0" }, "funding": [ { @@ -2795,7 +2930,7 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2024-09-09T11:45:10+00:00" }, { "name": "symfony/process", @@ -2939,71 +3074,55 @@ }, { "name": "symfony/validator", - "version": "v5.4.26", + "version": "v6.4.20", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "77533f12c6dd5c766f1e1689de4ef4d1eac4af71" + "reference": "9314555aceb8d8ce8abda81e1e47e439258d9309" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/77533f12c6dd5c766f1e1689de4ef4d1eac4af71", - "reference": "77533f12c6dd5c766f1e1689de4ef4d1eac4af71", + "url": "https://api.github.com/repos/symfony/validator/zipball/9314555aceb8d8ce8abda81e1e47e439258d9309", + "reference": "9314555aceb8d8ce8abda81e1e47e439258d9309", "shasum": "" }, "require": { - "php": ">=7.2.5", - "symfony/deprecation-contracts": "^2.1|^3", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php73": "~1.0", - "symfony/polyfill-php80": "^1.16", - "symfony/polyfill-php81": "^1.22", - "symfony/translation-contracts": "^1.1|^2|^3" + "symfony/polyfill-php83": "^1.27", + "symfony/translation-contracts": "^2.5|^3" }, "conflict": { "doctrine/annotations": "<1.13", - "doctrine/cache": "<1.11", "doctrine/lexer": "<1.1", - "symfony/dependency-injection": "<4.4", - "symfony/expression-language": "<5.1", - "symfony/http-kernel": "<4.4", - "symfony/intl": "<4.4", - "symfony/property-info": "<5.3", - "symfony/translation": "<4.4", - "symfony/yaml": "<4.4" + "symfony/dependency-injection": "<5.4", + "symfony/expression-language": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/intl": "<5.4", + "symfony/property-info": "<5.4", + "symfony/translation": "<5.4.35|>=6.0,<6.3.12|>=6.4,<6.4.3|>=7.0,<7.0.3", + "symfony/yaml": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.13|^2", - "doctrine/cache": "^1.11|^2.0", "egulias/email-validator": "^2.1.10|^3|^4", - "symfony/cache": "^4.4|^5.0|^6.0", - "symfony/config": "^4.4|^5.0|^6.0", - "symfony/console": "^4.4|^5.0|^6.0", - "symfony/dependency-injection": "^4.4|^5.0|^6.0", - "symfony/expression-language": "^5.1|^6.0", - "symfony/finder": "^4.4|^5.0|^6.0", - "symfony/http-client": "^4.4|^5.0|^6.0", - "symfony/http-foundation": "^4.4|^5.0|^6.0", - "symfony/http-kernel": "^4.4|^5.0|^6.0", - "symfony/intl": "^4.4|^5.0|^6.0", - "symfony/mime": "^4.4|^5.0|^6.0", - "symfony/property-access": "^4.4|^5.0|^6.0", - "symfony/property-info": "^5.3|^6.0", - "symfony/translation": "^4.4|^5.0|^6.0", - "symfony/yaml": "^4.4|^5.0|^6.0" - }, - "suggest": { - "egulias/email-validator": "Strict (RFC compliant) email validation", - "psr/cache-implementation": "For using the mapping cache.", - "symfony/config": "", - "symfony/expression-language": "For using the Expression validator and the ExpressionLanguageSyntax constraints", - "symfony/http-foundation": "", - "symfony/intl": "", - "symfony/property-access": "For accessing properties within comparison constraints", - "symfony/property-info": "To automatically add NotNull and Type constraints", - "symfony/translation": "For translating validation errors.", - "symfony/yaml": "" + "symfony/cache": "^5.4|^6.0|^7.0", + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/console": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/expression-language": "^5.4|^6.0|^7.0", + "symfony/finder": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/intl": "^5.4|^6.0|^7.0", + "symfony/mime": "^5.4|^6.0|^7.0", + "symfony/property-access": "^5.4|^6.0|^7.0", + "symfony/property-info": "^5.4|^6.0|^7.0", + "symfony/translation": "^5.4.35|~6.3.12|^6.4.3|^7.0.3", + "symfony/yaml": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -3011,7 +3130,8 @@ "Symfony\\Component\\Validator\\": "" }, "exclude-from-classmap": [ - "/Tests/" + "/Tests/", + "/Resources/bin/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3031,7 +3151,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v5.4.26" + "source": "https://github.com/symfony/validator/tree/v6.4.20" }, "funding": [ { @@ -3047,70 +3167,43 @@ "type": "tidelift" } ], - "time": "2023-07-26T15:05:40+00:00" + "time": "2025-03-14T14:22:58+00:00" } ], "packages-dev": [ { "name": "squizlabs/php_codesniffer", - "version": "2.9.2", + "version": "3.12.0", "source": { "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745" + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/2acf168de78487db620ab4bc524135a13cfe6745", - "reference": "2acf168de78487db620ab4bc524135a13cfe6745", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/2d1b63db139c3c6ea0c927698e5160f8b3b8d630", + "reference": "2d1b63db139c3c6ea0c927698e5160f8b3b8d630", "shasum": "" }, "require": { "ext-simplexml": "*", "ext-tokenizer": "*", "ext-xmlwriter": "*", - "php": ">=5.1.2" + "php": ">=5.4.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" }, "bin": [ - "scripts/phpcs", - "scripts/phpcbf" + "bin/phpcbf", + "bin/phpcs" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "3.x-dev" } }, - "autoload": { - "classmap": [ - "CodeSniffer.php", - "CodeSniffer/CLI.php", - "CodeSniffer/Exception.php", - "CodeSniffer/File.php", - "CodeSniffer/Fixer.php", - "CodeSniffer/Report.php", - "CodeSniffer/Reporting.php", - "CodeSniffer/Sniff.php", - "CodeSniffer/Tokens.php", - "CodeSniffer/Reports/", - "CodeSniffer/Tokenizers/", - "CodeSniffer/DocGenerators/", - "CodeSniffer/Standards/AbstractPatternSniff.php", - "CodeSniffer/Standards/AbstractScopeSniff.php", - "CodeSniffer/Standards/AbstractVariableSniff.php", - "CodeSniffer/Standards/IncorrectPatternException.php", - "CodeSniffer/Standards/Generic/Sniffs/", - "CodeSniffer/Standards/MySource/Sniffs/", - "CodeSniffer/Standards/PEAR/Sniffs/", - "CodeSniffer/Standards/PSR1/Sniffs/", - "CodeSniffer/Standards/PSR2/Sniffs/", - "CodeSniffer/Standards/Squiz/Sniffs/", - "CodeSniffer/Standards/Zend/Sniffs/" - ] - }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" @@ -3118,31 +3211,59 @@ "authors": [ { "name": "Greg Sherwood", - "role": "lead" + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" } ], "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", "keywords": [ "phpcs", - "standards" + "standards", + "static analysis" ], "support": { - "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", - "source": "https://github.com/squizlabs/PHP_CodeSniffer", - "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" }, - "time": "2018-11-07T22:31:41+00:00" + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + }, + { + "url": "https://thanks.dev/u/gh/phpcsstandards", + "type": "thanks_dev" + } + ], + "time": "2025-03-18T05:04:51+00:00" } ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^7.4" + "php": "^8.2" }, - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/src/Keboola/Console/Command/MassDeleteProjectWorkspaces.php b/src/Keboola/Console/Command/MassDeleteProjectWorkspaces.php new file mode 100644 index 0000000..72d57ce --- /dev/null +++ b/src/Keboola/Console/Command/MassDeleteProjectWorkspaces.php @@ -0,0 +1,205 @@ +setName('manage:mass-delete-project-workspaces') + ->setDescription('Delete all project workspaces based on given list in file. [Works only for SNFLK now].') + ->addArgument(self::ARGUMENT_STACK_SUFFIX, InputArgument::REQUIRED, 'stack suffix "keboola.com, eu-central-1.keboola.com"') + ->addArgument(self::ARGUMENT_SOURCE_FILE, InputArgument::REQUIRED, 'Source csv with "project id,workspace schema" columns and no header.') + ->addOption(self::OPTION_FORCE, 'f', InputOption::VALUE_NONE, 'Write changes'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $connectionUrl = 'https://connection.' . $input->getArgument(self::ARGUMENT_STACK_SUFFIX); + $sandboxesUrl = 'https://sandboxes.' . $input->getArgument(self::ARGUMENT_STACK_SUFFIX); + $jobsUrl = 'https://queue.' . $input->getArgument(self::ARGUMENT_STACK_SUFFIX); + $sourceFile = $input->getArgument(self::ARGUMENT_SOURCE_FILE); + $output->writeln(sprintf('Fetching projects from "%s"', $sourceFile)); + $force = $input->getOption(self::OPTION_FORCE); + + // map by project id + /** + * @var array{ + * string, + * string[], + * } $map + */ + $map = []; + $csv = new CsvFile($sourceFile); + foreach ($csv as $line) { + if (count($line) !== 2) { + throw new InvalidArgumentException('File must contain exactly two columns.'); + } + if (!is_numeric($line[0])) { + throw new InvalidArgumentException(sprintf('Project id "%s" is not numeric.', $line[0])); + } + if (!str_starts_with($line[1], 'WORKSPACE_')) { + throw new InvalidArgumentException(sprintf('Workspace "%s" does not start with "WORKSPACE_".', $line[1])); + } + + if (array_key_exists($line[0], $map)) { + $map[$line[0]][] = $line[1]; + } else { + $map[$line[0]] = [$line[1]]; + } + } + + // testing override +// $map = [ +// '232' => [ +// 'WORKSPACE_832798053', +// 'WORKSPACE_965913339', +// ], +// ]; + + foreach ($map as $projectId => $workspacesSchemasToDelete) { + $helper = $this->getHelper('question'); + $question = new Question(sprintf( + 'Paste storage token for project "%s" to continue.' . PHP_EOL, + $projectId, + )); + $storageToken = $helper->ask($input, $output, $question); + + $storageClient = new Client([ + 'token' => $storageToken, + 'url' => $connectionUrl, + ]); + $sandboxesClient = new SandboxesClient( + $sandboxesUrl, + $storageToken + ); + $jobsClient = new QueueClient( + $jobsUrl, + $storageToken + ); + + $branchesClient = new DevBranches($storageClient); + + $jobs = []; + foreach ($branchesClient->listBranches() as $branch) { + $output->writeln(sprintf('Checking branch "%s" for sandboxes.', $branch['id'])); + $branchId = (string) $branch['id']; + if ($branch['isDefault']) { + $branchId = null; + } + /** @var Sandbox $sandbox */ + foreach ($sandboxesClient->list((new ListOptions())->setBranchId($branchId)) as $sandbox) { + $schema = $sandbox->getWorkspaceDetails()['connection']['schema'] ?? null; + if (!in_array($schema, $workspacesSchemasToDelete, true)) { + continue; + } + $output->writeln(sprintf( + 'Sandbox "%s" with schema "%s" found.', + $sandbox->getId(), + $schema, + )); + + // remove found schema from map + unset($map[$projectId][array_search($schema, $map[$projectId], true)]); + + if ($force) { + $job = $jobsClient->createJob(new JobData( + 'keboola.sandboxes', + null, + [ + 'parameters' => [ + 'task' => 'delete', + 'id' => $sandbox->getId(), + ], + ], + )); + + $job['sandbox'] = $sandbox; + $jobs[] = $job; + + $output->writeln(sprintf( + 'Created delete job "%s" for project "%s"', + $job['id'], + $projectId + )); + } else { + $output->writeln(sprintf( + '[DRY-RUN] Created delete job "%s" for project "%s"', + '', + $projectId + )); + } + } + } + + $output->writeln('Waiting for delete jobs to finish.'); + while (count($jobs) > 0) { + foreach ($jobs as $i => $job) { + $jobRes = $jobsClient->getJob((string) $job['id']); + if ($jobRes['isFinished'] === true) { + $output->writeln(sprintf( + 'Delete job "%s" for sandbox "%s" with schema "%s" finished with status "%s"', + $job['id'], + $job['sandbox']->getId(), + $job['sandbox']->getWorkspaceDetails()['connection']['schema'], + $jobRes['status'] + )); + unset($jobs[$i]); + } + } + sleep(2); + } + + foreach ($branchesClient->listBranches() as $branch) { + $output->writeln(sprintf('Checking branch "%s" for storage workspaces.', $branch['id'])); + $workspacesClient = new Workspaces( + $storageClient->getBranchAwareClient($branch['id']) + ); + foreach ($workspacesClient->listWorkspaces() as $workspace) { + if (!in_array($workspace['connection']['schema'], $map[$projectId], true)) { + continue; + } + // remove found schema from map + unset($map[$projectId][array_search($workspace['connection']['schema'], $map[$projectId], true)]); + if ($force) { + $output->writeln(sprintf('Deleting workspace "%s" with schema "%s"', $workspace['id'], $workspace['connection']['schema'])); + $workspacesClient->deleteWorkspace($workspace['id'], [], true); + } else { + $output->writeln(sprintf('[DRY-RUN] Deleting workspace "%s" with schema "%s"', $workspace['id'], $workspace['connection']['schema'])); + } + } + } + + if (count($map[$projectId]) !== 0) { + $output->writeln([ + 'Following schemas were not found (are deleted or needs to be deleted manually):', + implode(', ', $map[$projectId]), + ]); + } + } + } +}