diff --git a/Dockerfile b/Dockerfile index 79f5d5c..a3b5305 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,8 @@ RUN apt -y update && \ apt install -y \ libicu-dev \ libxml2-dev \ - zlib1g-dev && \ + zlib1g-dev \ + graphviz && \ docker-php-ext-install \ pdo_mysql \ intl \ diff --git a/composer.json b/composer.json index f0b4407..73e48e7 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ "snc/redis-bundle": "~2.0.6", "symfony/symfony": "~4.0", "symfony/monolog-bundle": "~3.1|~4.0", - "symfony/swiftmailer-bundle": "^3.1|~4.0" + "symfony/swiftmailer-bundle": "^3.1|~4.0", + "graphp/graphviz": "^0.2.1" }, "require-dev": { "doctrine/doctrine-fixtures-bundle": "~3.0|~4.0", diff --git a/composer.lock b/composer.lock index 2f8d1eb..3f90eef 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,53 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9839915134c8e8fd2c6b6b786b59fb99", + "content-hash": "7e0c1ad64b421b364a3dcf30c0096ae3", "packages": [ + { + "name": "clue/graph", + "version": "v0.9.0", + "source": { + "type": "git", + "url": "https://github.com/clue/graph.git", + "reference": "0336a4d5229fa61a20ccceaeab25e52ac9542700" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/clue/graph/zipball/0336a4d5229fa61a20ccceaeab25e52ac9542700", + "reference": "0336a4d5229fa61a20ccceaeab25e52ac9542700", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "graphp/algorithms": "Common graph algorithms, such as Dijkstra and Moore-Bellman-Ford (shortest path), minimum spanning tree (MST), Kruskal, Prim and many more..", + "graphp/graphviz": "GraphViz graph drawing / DOT output" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fhaculty\\Graph\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A mathematical graph/network library written in PHP", + "homepage": "https://github.com/clue/graph", + "keywords": [ + "edge", + "graph", + "mathematical", + "network", + "vertex" + ], + "time": "2015-03-07T18:11:31+00:00" + }, { "name": "doctrine/annotations", "version": "v1.6.0", @@ -1154,6 +1199,98 @@ ], "time": "2016-10-17T18:31:11+00:00" }, + { + "name": "graphp/algorithms", + "version": "v0.8.1", + "source": { + "type": "git", + "url": "https://github.com/graphp/algorithms.git", + "reference": "81db4049c35730767ec8f97fb5c4844234b86cef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/graphp/algorithms/zipball/81db4049c35730767ec8f97fb5c4844234b86cef", + "reference": "81db4049c35730767ec8f97fb5c4844234b86cef", + "shasum": "" + }, + "require": { + "clue/graph": "~0.9.0|~0.8.0", + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Graphp\\Algorithms\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christian Lück", + "email": "christian@lueck.tv" + } + ], + "description": "Common mathematical graph algorithms", + "homepage": "https://github.com/graphp/algorithms", + "keywords": [ + "Graph algorithms", + "dijkstra", + "kruskal", + "minimum spanning tree", + "moore-bellman-ford", + "prim", + "shortest path" + ], + "time": "2015-03-08T10:12:01+00:00" + }, + { + "name": "graphp/graphviz", + "version": "v0.2.1", + "source": { + "type": "git", + "url": "https://github.com/graphp/graphviz.git", + "reference": "2676522dfcd907fd3cb52891ea64a052c4ac4c2a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/graphp/graphviz/zipball/2676522dfcd907fd3cb52891ea64a052c4ac4c2a", + "reference": "2676522dfcd907fd3cb52891ea64a052c4ac4c2a", + "shasum": "" + }, + "require": { + "clue/graph": "~0.9.0|~0.8.0", + "graphp/algorithms": "~0.8.0", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Graphp\\GraphViz\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "GraphViz graph drawing for mathematical graph/network", + "homepage": "https://github.com/graphp/graphviz", + "keywords": [ + "dot output", + "graph drawing", + "graph image", + "graphviz" + ], + "time": "2015-03-08T10:30:28+00:00" + }, { "name": "jdorn/sql-formatter", "version": "v1.2.17", @@ -2054,12 +2191,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "e1c50ad6aac15aa5c76762f39fb6926b5f7fc1d2" + "reference": "46efa7cf127bfe6289e05b546db0442598f47359" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/e1c50ad6aac15aa5c76762f39fb6926b5f7fc1d2", - "reference": "e1c50ad6aac15aa5c76762f39fb6926b5f7fc1d2", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/46efa7cf127bfe6289e05b546db0442598f47359", + "reference": "46efa7cf127bfe6289e05b546db0442598f47359", "shasum": "" }, "conflict": { @@ -2168,7 +2305,7 @@ "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "sylius/sylius": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "symfony/dependency-injection": ">=2,<2.0.17", - "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.19|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2", "symfony/http-foundation": ">=2,<2.7.49|>=2.8,<2.8.44|>=3,<3.3.18|>=3.4,<3.4.14|>=4,<4.0.14|>=4.1,<4.1.3", "symfony/http-kernel": ">=2,<2.3.29|>=2.4,<2.5.12|>=2.6,<2.6.8", @@ -2176,14 +2313,14 @@ "symfony/polyfill": ">=1,<1.10", "symfony/polyfill-php55": ">=1,<1.10", "symfony/routing": ">=2,<2.0.19", - "symfony/security": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security": ">=2,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.19|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/security-bundle": ">=2,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<2.8.37|>=3,<3.3.17|>=3.4,<3.4.7|>=4,<4.0.7", "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", "symfony/security-guard": ">=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", - "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.19|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/serializer": ">=2,<2.0.11", - "symfony/symfony": ">=2,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.19|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/symfony": ">=2,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", "symfony/translation": ">=2,<2.0.17", "symfony/validator": ">=2,<2.0.24|>=2.1,<2.1.12|>=2.2,<2.2.5|>=2.3,<2.3.3", "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", @@ -2247,20 +2384,20 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2018-12-07T09:18:50+00:00" + "time": "2018-12-09T09:52:28+00:00" }, { "name": "sensio/framework-extra-bundle", - "version": "v5.2.2", + "version": "v5.2.3", "source": { "type": "git", "url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git", - "reference": "9ef408febe2f12e70118ef61c6515035a06c5830" + "reference": "1032c7077fd1a6f24f98b5a8377938000859f35d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/9ef408febe2f12e70118ef61c6515035a06c5830", - "reference": "9ef408febe2f12e70118ef61c6515035a06c5830", + "url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/1032c7077fd1a6f24f98b5a8377938000859f35d", + "reference": "1032c7077fd1a6f24f98b5a8377938000859f35d", "shasum": "" }, "require": { @@ -2279,7 +2416,7 @@ "symfony/finder": "^3.3|^4.0", "symfony/monolog-bridge": "^3.0|^4.0", "symfony/monolog-bundle": "^3.2", - "symfony/phpunit-bridge": "^3.3|^4.0", + "symfony/phpunit-bridge": "^3.4.19|^4.1.8", "symfony/psr-http-message-bridge": "^0.3", "symfony/security-bundle": "^3.3|^4.0", "symfony/twig-bundle": "^3.3|^4.0", @@ -2318,7 +2455,7 @@ "annotations", "controllers" ], - "time": "2018-10-26T14:09:02+00:00" + "time": "2018-11-30T18:25:56+00:00" }, { "name": "snc/redis-bundle", diff --git a/config/routing.yml b/config/routing.yml index 2f13067..f803412 100644 --- a/config/routing.yml +++ b/config/routing.yml @@ -2,6 +2,10 @@ ApiBundle: resource: "@Api/Resources/config/routing.yml" prefix: /api +IntegrationBundle: + resource: "@Integration/Resources/config/routing.yml" + prefix: /integration + WebhookBundle: resource: "@Webhook/Resources/config/routing.yml" prefix: /webhook diff --git a/integration/example/bitbucket.yml b/integration/example/bitbucket.yml index 1052470..2a58a3d 100644 --- a/integration/example/bitbucket.yml +++ b/integration/example/bitbucket.yml @@ -8,12 +8,15 @@ integration: pullrequest-opened: label: Pull request opened description: ... + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' pullrequest-reviewed: label: Pull request reviewed description: ... + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' pullrequest-merged: label: Pull request merged description: ... + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' achievements: pull-request-streak-badge: @@ -21,6 +24,7 @@ integration: description: Perform three times an action on any pull request. Can be awarded multiple times. points: 50 actions: [pullrequest-opened, pullrequest-reviewed, pullrequest-merged] + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' validators: pull-request-streak-validator: @@ -52,4 +56,4 @@ integration: arguments: - username - - sveneisenschmidt: alex.doe \ No newline at end of file + sveneisenschmidt: alex.doe diff --git a/integration/example/jira.yml b/integration/example/jira.yml index 02ef37d..5e1a1c9 100644 --- a/integration/example/jira.yml +++ b/integration/example/jira.yml @@ -8,12 +8,15 @@ integration: issue-created: label: Create an issue description: ... + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' issue-updated: label: Update an issue description: ... + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' issue-closed: label: Close an issue description: ... + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' achievements: issue-action-streak-badge: @@ -21,13 +24,15 @@ integration: description: Work with issues en mass. points: 50 actions: [issue-created, issue-updated, issue-closed] + imageUrl: 'https://avatars.dicebear.com/v2/identicon/3968.svg' validators: issue-action-streak-validator: type: expression arguments: - "actions.count()%10 == 0" # expression - - ['issue-action-streak-badge'] # supported achievements + - "actions.count()/10" # expression + - [issue-action-streak-badge] # supported achievements - true # multiple: true webhooks: @@ -35,7 +40,7 @@ integration: jira: type: chain arguments: - - [ jira-payload, jira-actions, jira-users ] + - [jira-payload, jira-actions, jira-users] # The JiraProcessor brings an optional way to interpret payloads further # to map actions e.g. a updated task can be also an closed task, in this particular case # the processor should set the action jira.issue_closed instead of another action if @@ -59,4 +64,4 @@ integration: arguments: - username - - sveneisenschmidt: alex.doe \ No newline at end of file + sveneisenschmidt: alex.doe diff --git a/src/App/Api/EventListener/KernelExceptionListener.php b/src/App/Api/EventListener/KernelExceptionListener.php index 4b98d50..d295bc8 100644 --- a/src/App/Api/EventListener/KernelExceptionListener.php +++ b/src/App/Api/EventListener/KernelExceptionListener.php @@ -18,6 +18,7 @@ public function __construct(ResponseSerializer $serializer) public function onKernelException(GetResponseForExceptionEvent $event) { + return; $exception = $event->getException(); $response = $this->serializer->createResponse([ 'exception' => get_class($exception), diff --git a/src/App/Integration/Controller/GraphController.php b/src/App/Integration/Controller/GraphController.php new file mode 100644 index 0000000..4120578 --- /dev/null +++ b/src/App/Integration/Controller/GraphController.php @@ -0,0 +1,93 @@ +setAttribute('graphviz.graph.rankdir', 'LR'); + + // Actions + foreach ($engine->findActionDefinitionAny() as $actionDefinition) { + /** @var ActionDefinitionInterface $actionDefinition */ + $actionDefinitionVertex = $graph->createVertex($actionDefinition->getName()); + $actionDefinitionVertex->setAttribute('graphviz.shape', 'Mrecord'); + $actionDefinitionVertex->setAttribute('graphviz.label', GraphViz::raw(sprintf( + '"Action | %s"', + $actionDefinition->getLabel() + ))); + } + + // Achievements + foreach ($engine->findAchievementDefinitionAny() as $achievementDefinition) { + /** @var AchievementDefinitionInterface $achievementDefinition */ + $achievementDefinitionVertex = $graph->createVertex($achievementDefinition->getName()); + $achievementDefinitionVertex->setAttribute('graphviz.shape', 'Mrecord'); + $achievementDefinitionVertex->setAttribute('graphviz.label', GraphViz::raw(sprintf( + '"Achievement | %s"', + $achievementDefinition->getLabel() + ))); + + foreach ($achievementDefinition->getActionDefinitions() as $actionDefinition) { + /** @var ActionDefinitionInterface $actionDefinition */ + $actionDefinitionVertex = $graph->getVertex($actionDefinition->getName()); + $actionDefinitionVertex->createEdgeTo($achievementDefinitionVertex); + } + } + + // Validators + foreach ($engine->getAchievementValidators() as $achievementValidator) { + /** @var AchievementValidatorInterface $achievementValidator */ + + foreach ($engine->findAchievementDefinitionAny() as $achievementDefinition) { + /** @var AchievementDefinitionInterface $achievementDefinition */ + if ($achievementValidator->supports($achievementDefinition)) { + $achievementValidatorVertex = $graph->createVertex(sprintf( + 'validator.%s.%s', + spl_object_id($achievementDefinition), + $achievementDefinition->getLabel() + )); + $achievementValidatorVertex->setAttribute('graphviz.shape', 'Mrecord'); + $achievementValidatorVertex->setAttribute('graphviz.label', GraphViz::raw(sprintf( + '"Validator | For: %s"', + $achievementDefinition->getLabel() + ))); + + + $achievementDefinitionVertex = $graph->getVertex($achievementDefinition->getName()); + $achievementDefinitionVertex->createEdgeTo($achievementValidatorVertex); + $achievementDefinitionVertex->setAttribute('graphviz.tailport', 'middle'); + $achievementDefinitionVertex->setAttribute('graphviz.headport', 'right'); + } + } + } + + $graphviz = new GraphViz(); + $html = $graphviz->createImageHtml($graph); + + return new Response($html); + } +} diff --git a/src/App/Integration/Resources/config/routing.yml b/src/App/Integration/Resources/config/routing.yml new file mode 100644 index 0000000..856fff5 --- /dev/null +++ b/src/App/Integration/Resources/config/routing.yml @@ -0,0 +1,3 @@ +Annotations: + resource: "@Integration/Controller" + type: annotation diff --git a/src/App/Integration/Resources/config/services.yml b/src/App/Integration/Resources/config/services.yml index 7020d77..f402e52 100644 --- a/src/App/Integration/Resources/config/services.yml +++ b/src/App/Integration/Resources/config/services.yml @@ -8,6 +8,10 @@ services: resource: '../../Command' tags: ['console.command'] + App\Integration\Controller\: + resource: '../../Controller' + tags: ['controller.service_arguments'] + App\Integration\Service\InstallerService: public: true