mirror of
https://github.com/Mactronique/cua.git
synced 2026-03-24 04:42:11 +01:00
Compare commits
58 Commits
v1.0.0-alp
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de248f9e99 | ||
|
|
8052a36be3 | ||
|
|
04d2367a5e | ||
|
|
89bed3d960 | ||
|
|
812b5387f6 | ||
|
|
f4a8152053 | ||
|
|
6ec2fd5806 | ||
|
|
b556ad9568 | ||
|
|
7d2baabd1a | ||
|
|
dcbced5fe4 | ||
|
|
96662abf51 | ||
|
|
ae89109ab6 | ||
|
|
307cfb2f04 | ||
|
|
612fe7852a | ||
|
|
e7bdbd0790 | ||
|
|
1d4fd0656b | ||
|
|
ae1e87c6cc | ||
|
|
58789c1e0a | ||
|
|
5d0c92665c | ||
|
|
79f9f15a06 | ||
|
|
254127e34c | ||
|
|
7d43b3c5ea | ||
|
|
26d41642c7 | ||
|
|
a61a8d8f36 | ||
|
|
eed13c5f07 | ||
|
|
3385fbc916 | ||
|
|
52d4c4e99f | ||
|
|
bcf7916ba0 | ||
|
|
eb9d8fc485 | ||
|
|
160cdbce8f | ||
|
|
0116f8d256 | ||
|
|
ff01918aee | ||
|
|
ac1f1f50a3 | ||
|
|
1b08598a46 | ||
|
|
88e575c6f8 | ||
|
|
50382f5b19 | ||
|
|
e35bb667ce | ||
|
|
9a3a3b3cc1 | ||
|
|
cd881c58f6 | ||
|
|
fb72e329a2 | ||
|
|
175aa45824 | ||
|
|
93bfa1e3f9 | ||
|
|
fa28a40610 | ||
|
|
e70da32c3f | ||
|
|
ea189abd17 | ||
|
|
27ee261a2e | ||
|
|
df6efdf0c6 | ||
|
|
e075f1f99b | ||
|
|
2eff40b37d | ||
|
|
534664411a | ||
|
|
0406c36867 | ||
|
|
05fc077820 | ||
|
|
91c070ee79 | ||
|
|
dae8e8ec82 | ||
|
|
a661046463 | ||
|
|
21b914a7ce | ||
|
|
92b3345a5c | ||
|
|
27e3d11329 |
97
.atoum.php
Normal file
97
.atoum.php
Normal file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
This file will automatically be included before EACH run.
|
||||
|
||||
Use it to configure atoum or anything that needs to be done before EACH run.
|
||||
|
||||
More information on documentation:
|
||||
[en] http://docs.atoum.org/en/latest/chapter3.html#configuration-files
|
||||
[fr] http://docs.atoum.org/fr/latest/lancement_des_tests.html#fichier-de-configuration
|
||||
*/
|
||||
use mageekguy\atoum\reports;
|
||||
use mageekguy\atoum\reports\coverage;
|
||||
use mageekguy\atoum\writers\std;
|
||||
use \mageekguy\atoum;
|
||||
|
||||
$report = $script->addDefaultReport();
|
||||
|
||||
/*
|
||||
LOGO
|
||||
|
||||
// This will add the atoum logo before each run.
|
||||
$report->addField(new atoum\report\fields\runner\atoum\logo());
|
||||
|
||||
// This will add a green or red logo after each run depending on its status.
|
||||
$report->addField(new atoum\report\fields\runner\result\logo());
|
||||
*/
|
||||
|
||||
/*
|
||||
CODE COVERAGE SETUP
|
||||
|
||||
// Please replace in next line "Project Name" by your project name and "/path/to/destination/directory" by your destination directory path for html files.
|
||||
$coverageField = new atoum\report\fields\runner\coverage\html('Project Name', '/path/to/destination/directory');
|
||||
|
||||
// Please replace in next line http://url/of/web/site by the root url of your code coverage web site.
|
||||
$coverageField->setRootUrl('http://url/of/web/site');
|
||||
|
||||
$report->addField($coverageField);
|
||||
*/
|
||||
|
||||
/*
|
||||
TEST EXECUTION SETUP
|
||||
|
||||
// Please replace in next line "/path/to/your/tests/units/classes/directory" by your unit test's directory.
|
||||
$runner->addTestsFromDirectory('path/to/your/tests/units/classes/directory');
|
||||
*/
|
||||
|
||||
/*
|
||||
TEST GENERATOR SETUP
|
||||
|
||||
$testGenerator = new atoum\test\generator();
|
||||
|
||||
// Please replace in next line "/path/to/your/tests/units/classes/directory" by your unit test's directory.
|
||||
$testGenerator->setTestClassesDirectory('path/to/your/tests/units/classes/directory');
|
||||
|
||||
// Please replace in next line "your\project\namespace\tests\units" by your unit test's namespace.
|
||||
$testGenerator->setTestClassNamespace('your\project\namespace\tests\units');
|
||||
|
||||
// Please replace in next line "/path/to/your/classes/directory" by your classes directory.
|
||||
$testGenerator->setTestedClassesDirectory('path/to/your/classes/directory');
|
||||
|
||||
// Please replace in next line "your\project\namespace" by your project namespace.
|
||||
$testGenerator->setTestedClassNamespace('your\project\namespace');
|
||||
|
||||
// Please replace in next line "path/to/your/tests/units/runner.php" by path to your unit test's runner.
|
||||
$testGenerator->setRunnerPath('path/to/your/tests/units/runner.php');
|
||||
|
||||
$script->getRunner()->setTestGenerator($testGenerator);
|
||||
*/
|
||||
|
||||
if (!is_dir(__DIR__.'/build/tests') && !mkdir(__DIR__.'/build/tests/', 0777, true) && !is_dir(__DIR__.'/build/tests')) {
|
||||
throw new \Exception("Unable to make directory ".__DIR__.'/build/tests/', 1);
|
||||
}
|
||||
if (!is_dir(__DIR__.'/build/coverage') && !mkdir(__DIR__.'/build/coverage/', 0777, true) && !is_dir(__DIR__.'/build/coverage')) {
|
||||
throw new \Exception("Unable to make directory ".__DIR__.'/build/coverage/', 1);
|
||||
}
|
||||
|
||||
$xunit = new atoum\reports\asynchronous\xunit();
|
||||
$runner->addReport($xunit);
|
||||
|
||||
$writer = new atoum\writers\file(__DIR__.'/build/tests/atoum.xunit.xml');
|
||||
$xunit->addWriter($writer);
|
||||
|
||||
$clover = new atoum\reports\asynchronous\clover();
|
||||
$runner->addReport($clover);
|
||||
|
||||
$writerClover = new atoum\writers\file(__DIR__.'/build/tests/atoum.clover.xml');
|
||||
$clover->addWriter($writerClover);
|
||||
|
||||
$coverage = new coverage\html();
|
||||
$coverage->addWriter(new std\out());
|
||||
$coverage->setOutPutDirectory(__DIR__ . '/build/coverage');
|
||||
$runner->addReport($coverage);
|
||||
|
||||
|
||||
$script->addTestsFromDirectory(__DIR__.'/tests/Units');
|
||||
|
||||
19
.bootstrap.atoum.php
Normal file
19
.bootstrap.atoum.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
This file will automatically be included before EACH test if -bf/--bootstrap-file argument is not used.
|
||||
|
||||
Use it to initialize the tested code, add autoloader, require mandatory file, or anything that needs to be done before EACH test.
|
||||
|
||||
More information on documentation:
|
||||
[en] http://docs.atoum.org/en/latest/chapter3.html#bootstrap-file
|
||||
[fr] http://docs.atoum.org/fr/latest/lancement_des_tests.html#fichier-de-bootstrap
|
||||
*/
|
||||
|
||||
/*
|
||||
AUTOLOADER
|
||||
*/
|
||||
|
||||
// composer
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@@ -1,2 +1,6 @@
|
||||
vendor/
|
||||
cua.yml
|
||||
/vendor/
|
||||
cua.yml
|
||||
/build
|
||||
/*.yml
|
||||
/*.yaml
|
||||
!/.travis.yml
|
||||
|
||||
49
.travis.yml
Normal file
49
.travis.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
language: php
|
||||
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
- 7.3
|
||||
- nightly
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- vendor
|
||||
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- COMPOSER_PREFER="--prefer-stable"
|
||||
- COMPOSER_PREFER="--prefer-lowest"
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: nightly
|
||||
- php: 7.4snapshot
|
||||
- php: 5.6
|
||||
exclude:
|
||||
- php: 7.0
|
||||
env: COMPOSER_PREFER="--prefer-lowest"
|
||||
- php: 7.1
|
||||
env: COMPOSER_PREFER="--prefer-lowest"
|
||||
- php: 7.2
|
||||
env: COMPOSER_PREFER="--prefer-lowest"
|
||||
- php: 7.3
|
||||
env: COMPOSER_PREFER="--prefer-lowest"
|
||||
- php: 7.1
|
||||
env: COMPOSER_PREFER="--prefer-stable"
|
||||
- php: 7.2
|
||||
env: COMPOSER_PREFER="--prefer-stable"
|
||||
- php: 7.3
|
||||
env: COMPOSER_PREFER="--prefer-stable"
|
||||
- php: 7.4snapshot
|
||||
env: COMPOSER_PREFER="--prefer-lowest"
|
||||
- php: nightly
|
||||
env: COMPOSER_PREFER="--prefer-lowest"
|
||||
|
||||
script:
|
||||
- composer update -o $COMPOSER_PREFER
|
||||
- vendor/bin/atoum
|
||||
18
ChangeLog.md
Normal file
18
ChangeLog.md
Normal file
@@ -0,0 +1,18 @@
|
||||
Change log
|
||||
==========
|
||||
|
||||
# 2.0.0
|
||||
|
||||
* Add security check
|
||||
* Enable to check one specific project found in the project configuration
|
||||
* Allow to check one custom project not found in project configuration
|
||||
* Move source file in src directory
|
||||
* Add DBAL configuration provider
|
||||
* Add Redmine configuration provider (experimental)
|
||||
* Add DBAL Storage for dependencies and security issues
|
||||
* Add reporting the PHP version and PHP extension dependencies from composer.lock
|
||||
|
||||
# 1.0.0
|
||||
|
||||
* First version
|
||||
* Check dependencies update, remove and deprecated
|
||||
BIN
Cua_Exemple_SQLite.db
Normal file
BIN
Cua_Exemple_SQLite.db
Normal file
Binary file not shown.
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Mactronique
|
||||
Copyright (c) 2016-2018 Jean-Baptiste Nahan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
39
Makefile
39
Makefile
@@ -1,2 +1,37 @@
|
||||
check:
|
||||
docker-compose run --rm tool bash -ci 'php5dismod xdebug && composer self-update && ./cua check'
|
||||
##
|
||||
## This file is part of Composer Update Analyser package.
|
||||
##
|
||||
## @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
## @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
## @license MIT
|
||||
##
|
||||
|
||||
.PHONY: check security console run-tests
|
||||
|
||||
check: vendor cua.yml
|
||||
docker-compose run --rm tool bash -ci 'phpdismod xdebug && php composer.phar self-update && ./cua check $(c)'
|
||||
|
||||
security: vendor cua.yml
|
||||
docker-compose run --rm tool bash -ci 'phpdismod xdebug && ./cua security $(c)'
|
||||
|
||||
console:
|
||||
docker-compose run --rm tool bash
|
||||
|
||||
run-tests: vendor
|
||||
docker-compose run --rm tool bash -ci 'vendor/bin/atoum'
|
||||
|
||||
vendor: composer.lock
|
||||
docker-compose run --rm tool bash -ci 'phpdismod xdebug && php composer.phar self-update && php composer.phar install -o --prefer-dist'
|
||||
|
||||
composer.lock: composer.json composer.phar
|
||||
docker-compose run --rm tool bash -ci 'phpdismod xdebug && php composer.phar self-update && php composer.phar update -o --prefer-dist'
|
||||
|
||||
composer.phar:
|
||||
$(eval EXPECTED_SIGNATURE = "$(shell wget -q -O - https://composer.github.io/installer.sig)")
|
||||
$(eval ACTUAL_SIGNATURE = "$(shell php -r "copy('https://getcomposer.org/installer', 'composer-setup.php'); echo hash_file('SHA384', 'composer-setup.php');")")
|
||||
@if [ "$(EXPECTED_SIGNATURE)" != "$(ACTUAL_SIGNATURE)" ]; then echo "Invalid signature"; exit 1; fi
|
||||
php composer-setup.php
|
||||
rm composer-setup.php
|
||||
|
||||
cua.yml: cua.yml.dist
|
||||
cp cua.yml.dist cua.yml
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Persistence;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
|
||||
interface Persistence {
|
||||
|
||||
/**
|
||||
* @param array $content Content to save
|
||||
* @param array $config custom config
|
||||
*/
|
||||
public function save(array $content, array $config = null);
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Persistence;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
|
||||
class YamlFile implements Persistence{
|
||||
/**
|
||||
* @var string default plath of file
|
||||
*/
|
||||
private $filePath;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config){
|
||||
$this->filePath = $config['path'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $content Content to save
|
||||
* @param array $config custom config
|
||||
*/
|
||||
public function save(array $content, array $config = null)
|
||||
{
|
||||
$content = Yaml::dump($content, 100);
|
||||
file_put_contents(($config !== null)? $config['path']:$this->filePath, $content);
|
||||
}
|
||||
}
|
||||
214
README.md
214
README.md
@@ -1,14 +1,27 @@
|
||||
# cua
|
||||
Composer Update Analyser
|
||||
Composer Update Analyzer
|
||||
|
||||
This utility can read the `composer.lock` for get all library used by your project and run `composer update --dry-run` for get all necessary install, update or remove actions.
|
||||
[](https://travis-ci.org/Mactronique/cua) [](https://opensource.org/licenses/MIT)
|
||||
|
||||
The output can is a `yaml` file or DBAL table.
|
||||
This utility can
|
||||
* Read the `composer.lock` to get all library used by your project and run `composer update --dry-run` to get all necessary install, update or remove actions.
|
||||
* Run security-checker to get all library actually installed with know security issues. __This feature send the `composer.lock` file at the remote service__.
|
||||
|
||||
The output can be a `yaml` file or DBAL table.
|
||||
|
||||
## Requirements
|
||||
|
||||
* composer
|
||||
* php 5.5+
|
||||
* [composer](https://getcomposer.org/)
|
||||
* [PHP 5.6+](http://php.net)
|
||||
* [security-checker](https://security.symfony.com/)
|
||||
|
||||
## Recommended software
|
||||
|
||||
> For Linux only.
|
||||
|
||||
* [Docker](https://docs.docker.com/install/)
|
||||
* [Docker compose](https://docs.docker.com/compose/install/)
|
||||
* [Make](https://en.wikipedia.org/wiki/Makefile)
|
||||
|
||||
## Install
|
||||
|
||||
@@ -17,50 +30,191 @@ The output can is a `yaml` file or DBAL table.
|
||||
|
||||
## Configure
|
||||
|
||||
Create an file `cua.yml` at root cua folder.
|
||||
Add a file `cua.yml` (or copy the `cual.yml.dist` file) at the root cua folder.
|
||||
|
||||
Put content:
|
||||
|
||||
Put content :
|
||||
```
|
||||
projects:
|
||||
project_name: /path/to/project
|
||||
composer_path: /usr/local/bin/composer # the path to composer
|
||||
composer_path: /usr/local/bin/composer # the path to the composer executable
|
||||
security_checker_path: /usr/bin/security-checker # The path to security-checker executable
|
||||
# (set 'internal' if you want use the Internal Security Checker)
|
||||
persistance:
|
||||
format: DbalPersistance # Persistence
|
||||
parameters:
|
||||
dbname: 'deps' # DBAL Database name
|
||||
user: 'root' # DBAL database username
|
||||
password: 'root' # DBALbatabase user password
|
||||
host: 'localhost' # DBAL server name or ip
|
||||
driver: 'pdo_mysql' # DBAL Driver name
|
||||
table_name: 'dependencies' # the table name for DBAL persistance
|
||||
path: ./all.yml # for YamlFile only
|
||||
dbname: 'deps' # DBAL Database name
|
||||
user: 'root' # DBAL database username
|
||||
password: 'root' # DBALbatabase user password
|
||||
host: 'localhost' # DBAL server name or IP
|
||||
driver: 'pdo_mysql' # DBAL Driver name
|
||||
table_name: 'dependencies' # the table name for DBAL persistence
|
||||
table_name_security: 'security' # the table name for DBAL persistence
|
||||
|
||||
path: ./all.yml # for YamlFile only
|
||||
path_security: ./all_security.yml # for YamlFile only
|
||||
|
||||
project_provider:
|
||||
type: file
|
||||
parameters:
|
||||
path: projects.yml # Location of the file project list of root cua install
|
||||
```
|
||||
|
||||
### DBAL Table creation
|
||||
Add a file `project.yml` (or copy the `project.yml.dist` file) at the root cua folder.
|
||||
|
||||
If you use MySQL for persist, you can use the file `Sql/Create_Table.sql` for create table in your database.
|
||||
Put content:
|
||||
|
||||
```
|
||||
projects:
|
||||
'project_name':
|
||||
path: /path/to/project
|
||||
check_dependencies: true # Optional, by default : true
|
||||
lock_path: ./composer.lock # Optional, by default : ./composer.lock. Set the location of composer.lock file from the project path.
|
||||
check_security: false # Optional, by default : false. Enable this project for command security
|
||||
php_path: php7.2 # Optional, by default : php. The php executable name (or path) for run security-checker and composer
|
||||
```
|
||||
|
||||
### Store in file
|
||||
|
||||
In the `cua.yml` file, set the property `persistance.format` to the `YamlFile`.
|
||||
|
||||
Define two properties `path` and `path_security` with the path when you want store the result.
|
||||
|
||||
> Note : The content is overwritten for each execution.
|
||||
|
||||
Configuration example:
|
||||
|
||||
```
|
||||
[...]
|
||||
persistance:
|
||||
format: YamlFile # Persistence
|
||||
parameters:
|
||||
path: ./all.yml # The content of library update
|
||||
path_security: ./all_security.yml # The content of security issues
|
||||
[...]
|
||||
```
|
||||
|
||||
### Store in Relational Databases (with DBAL)
|
||||
|
||||
In the `cua.yml` file, set the property `persistance.format` to the `DbalPersistance`.
|
||||
|
||||
All script for creating tables in your database is in this folder `src/Sql/`. If your RDBMS is not present, you cal use on script and update it for your usage.
|
||||
|
||||
The parameters are the same for [Doctrine DBAL](https://www.doctrine-project.org/projects/doctrine-dbal/en/2.9/reference/configuration.html) with two additional fields `table_name` and `table_name_security`.
|
||||
|
||||
> Note : The PHP used for running the cua application do need the driver for the database.
|
||||
|
||||
Configuration example:
|
||||
|
||||
```
|
||||
[...]
|
||||
persistance:
|
||||
format: DbalPersistance # Persistence
|
||||
parameters:
|
||||
dbname: 'deps' # DBAL Database name
|
||||
user: 'root' # DBAL database username
|
||||
password: 'root' # DBALbatabase user password
|
||||
host: 'localhost' # DBAL server name or IP
|
||||
driver: 'pdo_mysql' # DBAL Driver name
|
||||
table_name: 'dependencies' # the table name for the dependencies DBAL persistence
|
||||
table_name_security: 'security' # the table name for the security DBAL persistence
|
||||
[...]
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
### Use with Redmine Cua Plugin (deprecated)
|
||||
|
||||
open console, go to cua root folder and type :
|
||||
Set the format to `RedmineCuaPersistance` and `table_name` to `cua_dependencies`
|
||||
|
||||
In this case, the `project_name` set into the config file do the same project identifier from redmine.
|
||||
|
||||
|
||||
### File Project Provider
|
||||
|
||||
This file contains all configuration for each project.
|
||||
|
||||
Set the property `project_provider.type` to `file`.
|
||||
|
||||
Set the property `project_provider.parameters.path` to the name of file contains all projects configuration.
|
||||
|
||||
> Note : The file path is relative to the cua installation folder.
|
||||
|
||||
Exemple of configuration:
|
||||
|
||||
```
|
||||
[...]
|
||||
project_provider:
|
||||
type: file
|
||||
parameters:
|
||||
path: projects.yml # Location of the file project list of root cua install
|
||||
```
|
||||
|
||||
|
||||
### Dbal Project Provider
|
||||
|
||||
You can store the configuration into a database. The SQL script present into the folder `src/Sql` contains the table `projects` description.
|
||||
|
||||
The table fields descriptions:
|
||||
* The field `code` of type string and 10 characters maximum of length is needed and contain a unique identity for the project
|
||||
* The field `name` of type string and 100 characters maximum of length is needed and contain user-friendly project name
|
||||
* The field `path` of type string and 255 characters maximum of length is needed and contain the path to the root project folder
|
||||
* The field `lock_path` of type string and 255 characters maximum of length is needed and contain the relative path (from the root project path) to the `composer.lock` file.
|
||||
* The field `php_path` of type string and 255 characters maximum of length is needed and contain the PHP executable name or full path.
|
||||
* The field `private_dependencies` of type text is optional. If defined this field do contain a JSON representation of the array. This array contains all private dependency name. Used only for the security check.
|
||||
* The field `private_dependencies_strategy` of type string and 10 characters maximum of length is optional, the default value is `remove`. The value can be `remove` or `hash`. This defines the behavior for the private dependency before send the `composer.lock` file for security checks.
|
||||
* The field `check_dependencies` of type tinyint(1) is optional, if defined to 1, enable the dependency check for this project.
|
||||
* The field `check_security` of type tinyint(1) is optional, if defined to 1, enable the security check for this project.
|
||||
* The field `updated_at` of type datetime is needed and contains the last update date and time.
|
||||
|
||||
Example of configuration:
|
||||
|
||||
```
|
||||
[...]
|
||||
project_provider:
|
||||
type: file
|
||||
parameters:
|
||||
working_dir: /sources # The root folder used in prefix for project path
|
||||
db:
|
||||
dbname: 'deps' # DBAL Database name
|
||||
user: 'root' # DBAL database username
|
||||
password: 'root' # DBALbatabase user password
|
||||
host: 'localhost' # DBAL server name or IP
|
||||
driver: 'pdo_mysql' # DBAL Driver name
|
||||
table_name: projects # The table name for read the project configuration
|
||||
```
|
||||
|
||||
|
||||
## Check project configuration
|
||||
|
||||
Open console, go to the cua root folder and type :
|
||||
|
||||
```
|
||||
php ./cua project:list
|
||||
```
|
||||
|
||||
This command print a table with all project configured and details.
|
||||
|
||||
## Usage for check dependencies
|
||||
|
||||
Open console, go to the cua root folder and type :
|
||||
|
||||
```
|
||||
php ./cua check
|
||||
```
|
||||
|
||||
This command launch the process for all setting project and store in persistance.
|
||||
This command launch the process for all setting project and store in persistence.
|
||||
|
||||
## Usage for check security
|
||||
|
||||
Open console, go to the cua root folder and type :
|
||||
|
||||
```
|
||||
php ./cua security
|
||||
```
|
||||
|
||||
This command launch the process for all setting project and store in persistence.
|
||||
|
||||
|
||||
|
||||
# Contribute
|
||||
|
||||
If you whant contribute, please fork my repo, add feature or fix bugs and create new pull request.
|
||||
|
||||
|
||||
# Todo
|
||||
|
||||
[ ] Add script for create table on other Database (postgre, mssql, etc.).
|
||||
|
||||
[ ] Get PHP and extentions requirements by project.
|
||||
If you want to contribute, please fork my repo, add features or fix bugs and create a new pull request.
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Service;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
|
||||
class InstalledLibraryService {
|
||||
|
||||
/**
|
||||
* Construct the service
|
||||
* @param string $composerPath
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger = null){
|
||||
$this->logger = ($logger === null)? new NullLogger():$logger;
|
||||
}
|
||||
|
||||
public function getInstalledLibrary($projectPath){
|
||||
$finder = new Finder();
|
||||
|
||||
$libraries = [];
|
||||
$composer = $finder->in($projectPath)->files()->name('composer.lock');
|
||||
foreach ($composer as $file) {
|
||||
$json = json_decode($file->getContents(), true);
|
||||
|
||||
foreach ($json['packages'] as $value) {
|
||||
$libraries[$value['name']] = $value['version'];
|
||||
}
|
||||
}
|
||||
return $libraries;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
|
||||
## FOR MySQL
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `dependencies` (
|
||||
`id` int(11) NOT NULL,
|
||||
`project` varchar(50) NOT NULL,
|
||||
`library` varchar(250) NOT NULL,
|
||||
`version` varchar(250) NOT NULL,
|
||||
`state` varchar(20) NOT NULL,
|
||||
`to_library` varchar(250) DEFAULT NULL,
|
||||
`to_version` varchar(250) DEFAULT NULL,
|
||||
`deprecated` tinyint(1) DEFAULT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `dependencies`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `idx_proj_lib` (`project`,`library`(191)) USING BTREE,
|
||||
ADD KEY `idx_plv` (`project`,`library`(191),`version`(191));
|
||||
|
||||
ALTER TABLE `dependencies`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
70
UPGRADE_TO_2.0.md
Normal file
70
UPGRADE_TO_2.0.md
Normal file
@@ -0,0 +1,70 @@
|
||||
UPGRADE FROM 1.0 to 2.0
|
||||
=======================
|
||||
|
||||
The version 2.0 rewrite the configuration and split the file in two files.
|
||||
|
||||
# Rewrite the configuration
|
||||
|
||||
Read the `projects` part from the 1.0 cua config file do move into an new file.
|
||||
|
||||
|
||||
This is an example to split the old v1.0 config file:
|
||||
|
||||
## v1.0 config file `cua.yml`
|
||||
|
||||
```
|
||||
projects:
|
||||
project_name: /path/to/project
|
||||
composer_path: /usr/local/bin/composer # the path to composer
|
||||
persistance:
|
||||
format: DbalPersistance # Persistence
|
||||
parameters:
|
||||
dbname: 'deps' # DBAL Database name
|
||||
user: 'root' # DBAL database username
|
||||
password: 'root' # DBALbatabase user password
|
||||
host: 'localhost' # DBAL server name or ip
|
||||
driver: 'pdo_mysql' # DBAL Driver name
|
||||
table_name: 'dependencies' # the table name for DBAL persistance
|
||||
path: ./all.yml # for YamlFile only
|
||||
```
|
||||
|
||||
## Generate the v2.0 config file
|
||||
|
||||
v2.0 config file `cua.yml` is same as v1.0 without the `projets` configuration key:
|
||||
```
|
||||
composer_path: /usr/local/bin/composer # the path to composer
|
||||
persistance:
|
||||
format: DbalPersistance # Persistence
|
||||
parameters:
|
||||
dbname: 'deps' # DBAL Database name
|
||||
user: 'root' # DBAL database username
|
||||
password: 'root' # DBALbatabase user password
|
||||
host: 'localhost' # DBAL server name or ip
|
||||
driver: 'pdo_mysql' # DBAL Driver name
|
||||
table_name: 'dependencies' # the table name for DBAL persistance
|
||||
path: ./all.yml # for YamlFile only
|
||||
```
|
||||
|
||||
Add the project source for use the projet YAML configuration file:
|
||||
```
|
||||
project_provider:
|
||||
type: file
|
||||
parameters:
|
||||
path: projects.yml # Location of the file project list from root cua install
|
||||
```
|
||||
|
||||
## Generate the 2.0 project configuration file
|
||||
|
||||
v2.0 project file configuration with the v1.0 `projets` configuration key:
|
||||
```
|
||||
projects:
|
||||
project_name: /path/to/project
|
||||
```
|
||||
|
||||
Il the new file, set the value of the `project name key` to the `path` key like this:
|
||||
|
||||
```
|
||||
projects:
|
||||
project_name:
|
||||
path: /path/to/project
|
||||
```
|
||||
@@ -1,32 +1,55 @@
|
||||
{
|
||||
"name": "matronique/cua",
|
||||
"type": "library",
|
||||
"description": "This application can manage many project composer update",
|
||||
"keywords": ["composer", "update", "dependecies", "management"],
|
||||
"homepage": "https://github.com/macintoshplus/ComposerUpdateAnalyser",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jean-Baptiste Nahan",
|
||||
"email": "jbnahan@gmail.com",
|
||||
"homepage": "http://nahan.fr"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Mactronique\\CUA\\": ""
|
||||
}
|
||||
},
|
||||
"bin": ["cua"],
|
||||
"require": {
|
||||
"php": ">=5.5",
|
||||
"symfony/console": "^3.0",
|
||||
"symfony/yaml": "^3.0",
|
||||
"symfony/config": "^3.0",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/process": "^3.0",
|
||||
"symfony/var-dumper": "^3.0",
|
||||
"symfony/finder": "^3.0",
|
||||
"doctrine/dbal": "^2.5"
|
||||
"name": "mactronique/cua",
|
||||
"type": "project",
|
||||
"description": "This application can manage many project composer update",
|
||||
"keywords": [
|
||||
"composer",
|
||||
"update",
|
||||
"dependecies",
|
||||
"management"
|
||||
],
|
||||
"homepage": "https://github.com/Mactronique/cua",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jean-Baptiste Nahan",
|
||||
"email": "814683+macintoshplus@users.noreply.github.com"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Mactronique\\CUA\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Mactronique\\CUA\\Tests\\Units\\": "tests/Units"
|
||||
}
|
||||
},
|
||||
"bin": [
|
||||
"cua"
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.6 || ^7.0",
|
||||
"symfony/console": "^3.0 || ^4.0",
|
||||
"symfony/yaml": "^3.0 || ^4.0",
|
||||
"symfony/config": "^3.0 || ^4.0",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/process": "^3.0 || ^4.0",
|
||||
"symfony/var-dumper": "^3.0 || ^4.0",
|
||||
"symfony/finder": "^3.0 || ^4.0",
|
||||
"doctrine/dbal": "^2.5",
|
||||
"sensiolabs/security-checker": "^5.0 || ^6.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"atoum/atoum": "^3.0 || dev-master",
|
||||
"atoum/reports-extension": "*"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "v2.x-dev",
|
||||
"dev-v1.x": "v1.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
677
composer.lock
generated
677
composer.lock
generated
File diff suppressed because it is too large
Load Diff
8
cua
8
cua
@@ -1,6 +1,12 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
// TestWebService.php
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
require __DIR__.'/vendor/autoload.php';
|
||||
|
||||
|
||||
13
cua.yml.dist
Normal file
13
cua.yml.dist
Normal file
@@ -0,0 +1,13 @@
|
||||
composer_path: composer # the path to the composer executable
|
||||
security_checker_path: security-checker # The path to security-checker executable or 'internal' for use the integrated checker
|
||||
|
||||
persistance:
|
||||
format: YamlFile
|
||||
parameters:
|
||||
path: ./all.yml # for YamlFile only
|
||||
path_security: ./all_security.yml # for YamlFile only
|
||||
|
||||
project_provider:
|
||||
type: file
|
||||
parameters:
|
||||
path: projects.yml # Location of the file project list of root cua install
|
||||
@@ -1,5 +1,10 @@
|
||||
tool:
|
||||
image: macintoshplus/composer:latest
|
||||
volumes:
|
||||
- ./:/src
|
||||
- /var/www:/var/www
|
||||
version: '2'
|
||||
services:
|
||||
tool:
|
||||
image: macintoshplus/php:php72
|
||||
volumes:
|
||||
- ./:/sources
|
||||
- /var/www:/var/www
|
||||
- /home/jbnahan/.config/composer/vendor/bin/composer:/usr/local/bin/composer
|
||||
dns:
|
||||
- 8.8.8.8
|
||||
|
||||
9
projects.yml.dist
Normal file
9
projects.yml.dist
Normal file
@@ -0,0 +1,9 @@
|
||||
projects:
|
||||
'cua':
|
||||
path: ./
|
||||
check_dependencies: true # Optional, by default : true
|
||||
lock_path: ./composer.lock # Optional, by default : ./composer.lock. Set the location of composer.lock file from the project path.
|
||||
check_security: false # Optional, by default : false. Enable this project for command security
|
||||
php_path: php # Optional, by default : php. The php executable name (or path) for run security-checker and composer
|
||||
private_dependencies: ~
|
||||
private_dependencies_strategy: remove
|
||||
@@ -3,32 +3,32 @@
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Command;
|
||||
|
||||
use Mactronique\CUA\Service\CheckUpdateService;
|
||||
use Mactronique\CUA\Service\InstalledLibraryService;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
|
||||
class CheckCommand extends Command
|
||||
class CheckDependenciesCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('check')
|
||||
->setDescription('Execute les tests')
|
||||
->setDescription('Run dependencies check')
|
||||
->addArgument(
|
||||
'name',
|
||||
InputArgument::OPTIONAL,
|
||||
'Nom du projet à vérifier'
|
||||
'The project name to check'
|
||||
)
|
||||
->addOption(
|
||||
'composer',
|
||||
@@ -62,33 +62,57 @@ class CheckCommand extends Command
|
||||
if (!file_exists($composerPath)) {
|
||||
throw new \Exception('Invalid composer path '.$composerPath, 1);
|
||||
}
|
||||
$service = new \Mactronique\CUA\Service\CheckUpdateService($composerPath);
|
||||
|
||||
$service = new CheckUpdateService($composerPath);
|
||||
|
||||
$projects = $this->getApplication()->getProjects();
|
||||
|
||||
//Chargement du projet via la ligne de commande
|
||||
$customName = $input->getArgument('name');
|
||||
// Check one project found in configuration
|
||||
if (null !== $customName && !$input->getOption('project')) {
|
||||
if (!isset($projects[$customName])) {
|
||||
throw new \Exception(sprintf('The name of project %s is not configured', $customName), 1);
|
||||
}
|
||||
$output->writeln(sprintf('Check for one specific project <info>"%s"</info>', $customName));
|
||||
$projects = [$customName => $projects[$customName]];
|
||||
}
|
||||
|
||||
//Load the project config from the commmand line
|
||||
if ($input->getOption('project')) {
|
||||
if (null === $input->getArgument('name')) {
|
||||
if (null === $customName) {
|
||||
throw new \Exception('Please set the name of project', 1);
|
||||
}
|
||||
$projects = [$input->getArgument('name') => $input->getOption('project')];
|
||||
$customPath = $input->getOption('project');
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
'Check for one custom project <info>"%s"</info> at <info>"%s"</info>',
|
||||
$customName,
|
||||
$customPath
|
||||
)
|
||||
);
|
||||
$projects = [$customName => ['path' => $customPath, 'check_dependencies' => true, 'php_path'=>'php']];
|
||||
}
|
||||
|
||||
//Pas de fichier de config donc fichier de sortie obligatoire
|
||||
if ($input->hasParameterOption(['--no-config'], true) && null === $input->getOption('output')) {
|
||||
throw new \Exception("Please set the output file option -o or --output", 1);
|
||||
throw new \Exception('Please set the output file option -o or --output', 1);
|
||||
}
|
||||
|
||||
$outputFile = $input->getOption('output');
|
||||
$installedService = new \Mactronique\CUA\Service\InstalledLibraryService();
|
||||
$installedService = new InstalledLibraryService();
|
||||
|
||||
foreach ($projects as $projectName => $projectPath) {
|
||||
|
||||
foreach ($projects as $projectName => $projectConf) {
|
||||
$projectPath = $projectConf['path'];
|
||||
$output->writeln(sprintf('Check <info>%s</info> at <comment>%s</comment>', $projectName, $projectPath));
|
||||
$resultProject = $service->checkcomposerUpdate($projectPath);
|
||||
|
||||
if (!$projectConf['check_dependencies']) {
|
||||
$output->writeln('<info>Skip</info>');
|
||||
continue;
|
||||
}
|
||||
|
||||
if($resultProject['error']!= ''){
|
||||
$output->writeln(sprintf("<error> %s </error>", $resultProject['error']));
|
||||
$resultProject = $service->checkcomposerUpdate($projectPath, $projectConf['php_path']);
|
||||
|
||||
if ($resultProject['error'] != '') {
|
||||
$output->writeln(sprintf('<error> %s </error>', $resultProject['error']));
|
||||
}
|
||||
|
||||
$output->writeln(sprintf(
|
||||
149
src/Command/CheckSecurityCommand.php
Normal file
149
src/Command/CheckSecurityCommand.php
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Command;
|
||||
|
||||
use Mactronique\CUA\Service\SecurityCheckService;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class CheckSecurityCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('security')
|
||||
->setDescription('Run security check')
|
||||
->addArgument(
|
||||
'name',
|
||||
InputArgument::OPTIONAL,
|
||||
'Nom du projet à vérifier'
|
||||
)
|
||||
->addOption(
|
||||
'checker',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'The path to security-checker'
|
||||
)
|
||||
->addOption(
|
||||
'project',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'The path to project'
|
||||
)
|
||||
->addOption(
|
||||
'lock_path',
|
||||
null,
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'The composer.lock path relative to project',
|
||||
'./composer.lock'
|
||||
)
|
||||
->addOption(
|
||||
'output',
|
||||
'o',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'The path to output file'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$securityChecker = $this->getApplication()->getSecurityChecker();
|
||||
|
||||
if ($input->getOption('checker')) {
|
||||
$securityChecker = $input->getOption('checker');
|
||||
}
|
||||
|
||||
if (!file_exists($securityChecker) && $securityChecker !== SecurityCheckService::INTERNAL) {
|
||||
throw new \Exception('Invalid security-checker path '.$securityChecker, 1);
|
||||
}
|
||||
$service = new \Mactronique\CUA\Service\SecurityCheckService($securityChecker);
|
||||
|
||||
$projects = $this->getApplication()->getProjects();
|
||||
|
||||
//Chargement du projet via la ligne de commande
|
||||
if ($input->getOption('project')) {
|
||||
if (null === $input->getArgument('name')) {
|
||||
throw new \Exception('Please set the name of project', 1);
|
||||
}
|
||||
$projects = [$input->getArgument('name') => ['path' => $input->getOption('project'), 'check_security'=> true, 'lock_path'=>$input->getOption('lock_path'), 'php_path'=>'php']];
|
||||
}
|
||||
|
||||
//Pas de fichier de config donc fichier de sortie obligatoire
|
||||
if ($input->hasParameterOption(['--no-config'], true) && null === $input->getOption('output')) {
|
||||
throw new \Exception('Please set the output file option -o or --output', 1);
|
||||
}
|
||||
|
||||
$outputFile = $input->getOption('output');
|
||||
$installedService = new \Mactronique\CUA\Service\InstalledLibraryService();
|
||||
|
||||
foreach ($projects as $projectName => $projectConf) {
|
||||
$projectPath = $projectConf['path'];
|
||||
$lockPath = $projectConf['lock_path'];
|
||||
|
||||
$output->writeln(sprintf('Check Security <info>%s</info> at <comment>%s</comment>', $projectName, $projectPath));
|
||||
|
||||
if (!$projectConf['check_security']) {
|
||||
$output->writeln('<info>Skip</info>');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($projectConf['private_dependencies']) && count($projectConf['private_dependencies'])) {
|
||||
$tmpPath = tempnam(sys_get_temp_dir(), 'cua');
|
||||
$lock = file_get_contents($projectPath.'/'.$lockPath);
|
||||
|
||||
foreach ($projectConf['private_dependencies'] as $libraryName) {
|
||||
$findName = sprintf('"%s"', $libraryName);
|
||||
if (false === $pos = mb_strpos($lock, $findName)) {
|
||||
$output->writeln('Private dependency not found in composer.lock : <info>'.$findName.'</info> ');
|
||||
continue;
|
||||
}
|
||||
$result = mb_ereg_replace(''.$findName.'', sprintf('"%s"', md5($libraryName.uniqid())), $lock);
|
||||
if ($result === false) {
|
||||
$output->writeln('<error>Error in remplacement of private library</error>');
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false !== $pos = mb_strpos($result, $findName)) {
|
||||
$output->writeln('<error>Error : The new lock file contains always the replaced private library '.$findName.'</error>');
|
||||
}
|
||||
|
||||
$lock = $result;
|
||||
}
|
||||
file_put_contents($tmpPath, $lock);
|
||||
$lockPath = $tmpPath;
|
||||
|
||||
$output->writeln('Replace lock file by modified version : <info>'.$lockPath.'</info>');
|
||||
}
|
||||
|
||||
$resultProject = $service->checkSecurity($projectPath, $lockPath, $projectConf['php_path']);
|
||||
if (isset($tmpPath)) {
|
||||
@unlink($tmpPath);
|
||||
}
|
||||
|
||||
if ($resultProject['error'] != '') {
|
||||
$output->writeln(sprintf('<error> %s </error>', $resultProject['error']));
|
||||
continue;
|
||||
}
|
||||
|
||||
$output->writeln(sprintf(
|
||||
'Result <error> %d </error> dependency with security issue',
|
||||
count($resultProject['result'])
|
||||
));
|
||||
|
||||
$this->getApplication()->setProjectSecurityResult($projectName, $resultProject['result']);
|
||||
$this->getApplication()->saveSecurityResult($outputFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
60
src/Command/ProjectListCommand.php
Normal file
60
src/Command/ProjectListCommand.php
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Helper\Table;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
|
||||
|
||||
class ProjectListCommand extends Command
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('project:list')
|
||||
->setDescription('Get configured project list')
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$projects = $this->getApplication()->getProjects();
|
||||
|
||||
//Pas de fichier de config donc fichier de sortie obligatoire
|
||||
if ($input->hasParameterOption(['--no-config'], true)) {
|
||||
throw new \Exception('Unable to get the project list without configuration', 1);
|
||||
}
|
||||
$outputStyle = new OutputFormatterStyle('red', 'yellow', array());
|
||||
$output->getFormatter()->setStyle('caution', $outputStyle);
|
||||
|
||||
$table = new Table($output);
|
||||
$table->setHeaders(['Project Name', 'Location', 'Check Dependencies', 'Check Security', 'PHP Bin', 'composer.lock path']);
|
||||
|
||||
foreach ($projects as $projectName => $projectConf) {
|
||||
$projectPath = $projectConf['path'];
|
||||
if (!is_dir($projectPath)) {
|
||||
$projectPath = '<error>'.$projectPath.'</error>';
|
||||
$lock_path = '<caution>'.$projectConf['lock_path'].'</caution>';
|
||||
} else {
|
||||
$lock_path = realpath($projectConf['path']).'/'.$projectConf['lock_path'];
|
||||
$lock_path = file_exists($lock_path) ? $projectConf['lock_path'] : '<error>'.$projectConf['lock_path'].'</error>';
|
||||
}
|
||||
|
||||
$table->addRow([$projectName, $projectPath, $projectConf['check_dependencies'] ? 'true':'<error>false</error>', $projectConf['check_security'] ? 'true':'<error>false</error>', $projectConf['php_path'], $lock_path]);
|
||||
}
|
||||
|
||||
$table->render();
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Configuration;
|
||||
@@ -22,13 +22,6 @@ class MainConfiguration implements ConfigurationInterface
|
||||
// ... add node definitions to the root of the tree
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('projects')
|
||||
->isRequired()
|
||||
->cannotBeEmpty()
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('scalar')
|
||||
->end()
|
||||
->end()
|
||||
->arrayNode('persistance')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
@@ -43,6 +36,23 @@ class MainConfiguration implements ConfigurationInterface
|
||||
->scalarNode('composer_path')
|
||||
->defaultValue('/usr/bin/composer')
|
||||
->end()
|
||||
->scalarNode('security_checker_path')
|
||||
->defaultValue('/usr/bin/security-checker')
|
||||
->end()
|
||||
->arrayNode('project_provider')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->enumNode('type')
|
||||
->defaultValue('file')
|
||||
->values(array('file', 'redmine'))
|
||||
->end()
|
||||
->arrayNode('parameters')
|
||||
->defaultValue([])
|
||||
->prototype('variable')
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
62
src/Configuration/ProjectConfiguration.php
Normal file
62
src/Configuration/ProjectConfiguration.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Configuration;
|
||||
|
||||
use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
|
||||
|
||||
class ProjectConfiguration implements ConfigurationInterface
|
||||
{
|
||||
public function getConfigTreeBuilder()
|
||||
{
|
||||
$treeBuilder = new TreeBuilder();
|
||||
$rootNode = $treeBuilder->root('main');
|
||||
|
||||
// ... add node definitions to the root of the tree
|
||||
$rootNode
|
||||
->children()
|
||||
->arrayNode('projects')
|
||||
->normalizeKeys(false)
|
||||
->useAttributeAsKey('name')
|
||||
->prototype('array')
|
||||
->addDefaultsIfNotSet()
|
||||
->children()
|
||||
->scalarNode('path')
|
||||
->cannotBeEmpty()
|
||||
->end()
|
||||
->scalarNode('lock_path')
|
||||
->defaultValue('./composer.lock')
|
||||
->end()
|
||||
->booleanNode('check_dependencies')
|
||||
->defaultTrue()
|
||||
->end()
|
||||
->booleanNode('check_security')
|
||||
->defaultFalse()
|
||||
->end()
|
||||
->scalarNode('php_path')
|
||||
->defaultValue('php')
|
||||
->end()
|
||||
->arrayNode('private_dependencies')
|
||||
->prototype('scalar')
|
||||
->end()
|
||||
->end()
|
||||
->enumNode('private_dependencies_strategy')
|
||||
->defaultValue('remove')
|
||||
->values(array('remove', 'hash'))
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
->end()
|
||||
;
|
||||
|
||||
return $treeBuilder;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Mactronique\CUA\Command\CheckCommand;
|
||||
use Mactronique\CUA\Configuration\MainConfiguration;
|
||||
use Mactronique\CUA\Command\CheckDependenciesCommand;
|
||||
use Mactronique\CUA\Command\CheckSecurityCommand;
|
||||
use Mactronique\CUA\Command\ProjectListCommand;
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
@@ -20,12 +30,18 @@ class CuaApplication extends Application
|
||||
|
||||
private $persistance;
|
||||
|
||||
private $results;
|
||||
private $projectsProvider;
|
||||
|
||||
private $results = [];
|
||||
|
||||
private $securityResults = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('Composer Update Analyser', '0.1');
|
||||
$this->add(new CheckCommand());
|
||||
parent::__construct('Composer Update Analyser', '1.1.0');
|
||||
$this->add(new CheckDependenciesCommand());
|
||||
$this->add(new CheckSecurityCommand());
|
||||
$this->add(new ProjectListCommand());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +92,7 @@ class CuaApplication extends Application
|
||||
|
||||
public function getProjects()
|
||||
{
|
||||
return $this->config['projects'];
|
||||
return $this->projectsProvider->getProjects();
|
||||
}
|
||||
|
||||
public function setProjectResult($projectName, array $content)
|
||||
@@ -97,14 +113,39 @@ class CuaApplication extends Application
|
||||
return $this->config['composer_path'];
|
||||
}
|
||||
|
||||
public function definePersistance($name, $parameters){
|
||||
public function setProjectSecurityResult($projectName, array $content)
|
||||
{
|
||||
$this->securityResults[$projectName] = $content;
|
||||
}
|
||||
|
||||
public function saveSecurityResult($path = null)
|
||||
{
|
||||
$this->persistance->saveSecurity($this->securityResults, $path);
|
||||
}
|
||||
|
||||
public function getSecurityChecker()
|
||||
{
|
||||
return $this->config['security_checker_path'];
|
||||
}
|
||||
|
||||
public function definePersistance($name, $parameters)
|
||||
{
|
||||
$className = 'Mactronique\\CUA\\Persistence\\'.$name;
|
||||
if(!class_exists($className)){
|
||||
throw new \Exception("Unable to load this persistance class: ".$className, 1);
|
||||
if (!class_exists($className)) {
|
||||
throw new \Exception('Unable to load this persistance class: '.$className, 1);
|
||||
}
|
||||
$this->persistance = new $className($parameters);
|
||||
}
|
||||
|
||||
protected function defineProjectProvider($config)
|
||||
{
|
||||
$className = 'Mactronique\\CUA\\ProjectProvider\\'.ucfirst($config['type']).'Provider';
|
||||
if (!class_exists($className)) {
|
||||
throw new \Exception('Unable to load this project provider class: '.$className, 1);
|
||||
}
|
||||
$this->projectsProvider = new $className($config['parameters']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default input definition.
|
||||
*
|
||||
@@ -123,13 +164,15 @@ class CuaApplication extends Application
|
||||
*/
|
||||
private function boot(InputInterface $input)
|
||||
{
|
||||
$this->config = ['output' => null, 'projects' => [], 'composer_path' => null];
|
||||
if (!$input->hasParameterOption(['--no-config'], true)) {
|
||||
$configFile = __DIR__.'/cua.yml';
|
||||
$this->loadConfigurationFile($configFile);
|
||||
|
||||
$this->definePersistance($this->config['persistance']['format'], $this->config['persistance']['parameters']);
|
||||
$this->config = ['output' => null, 'projects' => [], 'composer_path' => null, 'security_checker_path'=> null];
|
||||
if ($input->hasParameterOption(['--no-config'], true)) {
|
||||
return;
|
||||
}
|
||||
$configFile = __DIR__.'/../cua.yml';
|
||||
$this->loadConfigurationFile($configFile);
|
||||
|
||||
$this->definePersistance($this->config['persistance']['format'], $this->config['persistance']['parameters']);
|
||||
$this->defineProjectProvider($this->config['project_provider']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3,13 +3,14 @@
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Persistence;
|
||||
|
||||
class DbalPersistance implements Persistence
|
||||
class DbalPersistence implements Persistence
|
||||
{
|
||||
/**
|
||||
* @var string default plath of file
|
||||
@@ -18,12 +19,15 @@ class DbalPersistance implements Persistence
|
||||
|
||||
private $connexion;
|
||||
|
||||
private $updated;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->updated = [];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,11 +40,62 @@ class DbalPersistance implements Persistence
|
||||
$this->connexion->connect();
|
||||
|
||||
foreach ($content as $key => $data) {
|
||||
if (in_array($key, $this->updated)) {
|
||||
continue;
|
||||
}
|
||||
$this->removeAll($key);
|
||||
$this->installedLib($key, $data['installed']);
|
||||
$this->installLib($key, $data['install']);
|
||||
$this->updateLib($key, $data['update']);
|
||||
$this->removeLib($key, $data['uninstall']);
|
||||
$this->abandonedLib($key, $data['abandoned']);
|
||||
$this->updated[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
public function saveSecurity(array $content, array $config = null)
|
||||
{
|
||||
$this->connexion = \Doctrine\DBAL\DriverManager::getConnection($this->config);
|
||||
$this->connexion->connect();
|
||||
|
||||
foreach ($content as $project => $securitydata) {
|
||||
$data = ['state' => 'fixed'];
|
||||
$data['updated_at'] = new \DateTime();
|
||||
|
||||
$this->connexion->update($this->config['table_name_security'], $data, ['project' => $project, 'state' => 'open'], ['string', 'datetime', 'string', 'string']);
|
||||
|
||||
if (count($securitydata) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($securitydata as $library => $infos) {
|
||||
$list = json_encode($infos['advisories']);
|
||||
if ($this->checkSecurityExist($project, $library, $infos['version'])) {
|
||||
$this->connexion->update(
|
||||
$this->config['table_name_security'],
|
||||
[
|
||||
'details' => $list,
|
||||
'state' => 'open',
|
||||
'updated_at' => new \DateTime(),
|
||||
],
|
||||
['project' => $project, 'library'=>$library, 'version'=>$infos['version']],
|
||||
['string', 'string', 'datetime', 'string', 'string', 'string']
|
||||
);
|
||||
} else {
|
||||
$this->connexion->insert(
|
||||
$this->config['table_name_security'],
|
||||
[
|
||||
'details' => $list,
|
||||
'state' => 'open',
|
||||
'updated_at' => new \DateTime(),
|
||||
'project' => $project,
|
||||
'library'=>$library,
|
||||
'version'=>$infos['version']
|
||||
],
|
||||
['string', 'string', 'datetime', 'string', 'string', 'string']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,4 +219,26 @@ class DbalPersistance implements Persistence
|
||||
|
||||
$this->connexion->update($this->config['table_name'], $data, $key, ['string', 'string', 'string', 'string', 'datetime', 'string', 'string']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all dependency to deleted.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
private function removeAll($project)
|
||||
{
|
||||
$data = ['state' => 'removed', 'to_library' => null, 'to_version' => null];
|
||||
$data['updated_at'] = new \DateTime();
|
||||
|
||||
$this->connexion->update($this->config['table_name'], $data, ['project' => $project], ['string', 'string', 'string', 'datetime', 'string']);
|
||||
}
|
||||
|
||||
|
||||
private function checkSecurityExist($project, $library, $version)
|
||||
{
|
||||
$result = $this->connexion->executeQuery('SELECT count(*) as nombre FROM '.$this->config['table_name_security'].' WHERE project= ? AND library=? AND version=?', [$project, $library, $version], ['string', 'string', 'string']);
|
||||
$nb = $result->fetch();
|
||||
|
||||
return $nb['nombre'] != 0;
|
||||
}
|
||||
}
|
||||
26
src/Persistence/Persistence.php
Normal file
26
src/Persistence/Persistence.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Persistence;
|
||||
|
||||
interface Persistence
|
||||
{
|
||||
/**
|
||||
* @param array $content Content to save
|
||||
* @param array $config custom config
|
||||
*/
|
||||
public function save(array $content, array $config = null);
|
||||
|
||||
/**
|
||||
* @param array $content Content to save
|
||||
* @param array $config custom config
|
||||
*/
|
||||
public function saveSecurity(array $content, array $config = null);
|
||||
}
|
||||
298
src/Persistence/RedmineCuaPersistence.php
Normal file
298
src/Persistence/RedmineCuaPersistence.php
Normal file
@@ -0,0 +1,298 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Persistence;
|
||||
|
||||
class RedmineCuaPersistence implements Persistence
|
||||
{
|
||||
/**
|
||||
* @var string default plath of file
|
||||
*/
|
||||
private $config;
|
||||
|
||||
private $connexion;
|
||||
|
||||
private $updated;
|
||||
|
||||
private $projectCodeCache;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
$this->updated = [];
|
||||
$this->projectCodeCache = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $content Content to save
|
||||
* @param array $config custom config
|
||||
*/
|
||||
public function save(array $content, array $config = null)
|
||||
{
|
||||
$this->connexion = \Doctrine\DBAL\DriverManager::getConnection($this->config);
|
||||
//Debug des requettes SQL :
|
||||
//$this->connexion->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
|
||||
$this->connexion->connect();
|
||||
|
||||
foreach ($content as $key => $data) {
|
||||
if (in_array($key, $this->updated)) {
|
||||
continue;
|
||||
}
|
||||
$projectId = $this->convertProjectCode($key);
|
||||
$this->removeAll($projectId);
|
||||
$this->installedLib($projectId, $data['installed']);
|
||||
$this->installLib($projectId, $data['install']);
|
||||
$this->updateLib($projectId, $data['update']);
|
||||
$this->removeLib($projectId, $data['uninstall']);
|
||||
$this->abandonedLib($projectId, $data['abandoned']);
|
||||
$this->updated[] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function saveSecurity(array $content, array $config = null)
|
||||
{
|
||||
$this->connexion = \Doctrine\DBAL\DriverManager::getConnection($this->config);
|
||||
$this->connexion->connect();
|
||||
|
||||
foreach ($content as $project => $securitydata) {
|
||||
$projectId = $this->convertProjectCode($project);
|
||||
$data = ['state' => 'fixed'];
|
||||
$data['updated_at'] = new \DateTime();
|
||||
|
||||
$this->connexion->update($this->config['table_name_security'], $data, ['project_id' => $projectId, 'state' => 'open'], ['string', 'datetime', 'integer', 'string']);
|
||||
if (count($securitydata) === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($securitydata as $library => $infos) {
|
||||
dump($library, $infos);
|
||||
$list = json_encode($infos['advisories']);
|
||||
if ($this->checkSecurityExist($projectId, $library, $infos['version'])) {
|
||||
$this->connexion->update(
|
||||
$this->config['table_name_security'],
|
||||
[
|
||||
'details' => $list,
|
||||
'state' => 'open',
|
||||
'updated_at' => new \DateTime(),
|
||||
],
|
||||
['project_id' => $projectId, 'library'=>$library, 'version'=>$infos['version']],
|
||||
['string', 'string', 'datetime', 'integer', 'string', 'string']
|
||||
);
|
||||
} else {
|
||||
$this->connexion->insert(
|
||||
$this->config['table_name_security'],
|
||||
[
|
||||
'details' => $list,
|
||||
'state' => 'open',
|
||||
'updated_at' => new \DateTime(),
|
||||
'project_id' => $projectId,
|
||||
'library'=>$library,
|
||||
'version'=>$infos['version']
|
||||
],
|
||||
['string', 'string', 'datetime', 'integer', 'string', 'string']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the installed library.
|
||||
*
|
||||
* @param string $projet
|
||||
* @param array $installed library list
|
||||
*/
|
||||
private function installedLib($project, array $installed)
|
||||
{
|
||||
foreach ($installed as $library => $version) {
|
||||
$dbData = ['project_id' => $project, 'library' => $library, 'version' => $version, 'state' => 'installed', 'to_library' => null, 'to_version' => null];
|
||||
if ($this->checkExist($project, $library)) {
|
||||
$this->update($dbData);
|
||||
continue;
|
||||
}
|
||||
$this->insert($dbData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the library to install.
|
||||
*
|
||||
* @param string $projet
|
||||
* @param array $install library list
|
||||
*/
|
||||
private function installLib($project, array $install)
|
||||
{
|
||||
foreach ($install as $data) {
|
||||
$dbData = ['project_id' => $project, 'library' => $data['library'], 'version' => $data['version'], 'state' => 'install', 'to_library' => null, 'to_version' => null];
|
||||
if ($this->checkExist($project, $data['library'])) {
|
||||
$this->update($dbData);
|
||||
continue;
|
||||
}
|
||||
$this->insert($dbData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the library to update.
|
||||
*
|
||||
* @param string $projet
|
||||
* @param array $update library list
|
||||
*/
|
||||
private function updateLib($project, array $update)
|
||||
{
|
||||
foreach ($update as $data) {
|
||||
$dbData = ['project_id' => $project, 'library' => $data['from_library'], 'version' => $data['from_version'], 'state' => 'update', 'to_library' => $data['to_library'], 'to_version' => $data['to_version']];
|
||||
if ($this->checkExist($project, $data['from_library'])) {
|
||||
$this->update($dbData);
|
||||
continue;
|
||||
}
|
||||
$this->insert($dbData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the library to remove.
|
||||
*
|
||||
* @param string $projet
|
||||
* @param array $remove library list
|
||||
*/
|
||||
private function removeLib($project, array $remove)
|
||||
{
|
||||
foreach ($remove as $data) {
|
||||
$dbData = ['project_id' => $project, 'library' => $data['library'], 'version' => $data['version'], 'state' => 'remove', 'to_library' => null, 'to_version' => null];
|
||||
if ($this->checkExist($project, $data['library'])) {
|
||||
$this->update($dbData);
|
||||
continue;
|
||||
}
|
||||
$this->insert($dbData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the abandoned library.
|
||||
*
|
||||
* @param string $projet
|
||||
* @param array $abandonned library list
|
||||
*/
|
||||
private function abandonedLib($project, array $abandonned)
|
||||
{
|
||||
foreach ($abandonned as $key => $library) {
|
||||
$this->connexion->update($this->config['table_name'], ['deprecated' => true], ['project_id' => $project, 'library' => $library], ['deprecated' => 'boolean', 'project_id' => 'integer', 'library' => 'string']);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkExist($project, $library)
|
||||
{
|
||||
$result = $this->connexion->executeQuery('SELECT count(*) as nombre FROM '.$this->config['table_name'].' WHERE project_id= ? AND library=?', [$project, $library], ['integer', 'string']);
|
||||
$nb = $result->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
return intval($nb['nombre']) != 0;
|
||||
}
|
||||
|
||||
private function checkSecurityExist($project, $library, $version)
|
||||
{
|
||||
$result = $this->connexion->executeQuery('SELECT count(*) as nombre FROM '.$this->config['table_name_security'].' WHERE project_id= ? AND library=? AND version=?', [$project, $library, $version], ['integer', 'string', 'string']);
|
||||
$nb = $result->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
return intval($nb['nombre']) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data list of field (key) with value.
|
||||
*/
|
||||
private function insert(array $data)
|
||||
{
|
||||
$data['deprecated'] = false;
|
||||
$data['updated_at'] = new \DateTime();
|
||||
|
||||
$this->connexion->insert(
|
||||
$this->config['table_name'],
|
||||
$data,
|
||||
[
|
||||
'project_id' => 'integer',
|
||||
'library' => 'string',
|
||||
'version' => 'string',
|
||||
'state' => 'string',
|
||||
'to_library' => 'string',
|
||||
'to_version' => 'string',
|
||||
'deprecated' => 'boolean',
|
||||
'updated_at' => 'datetime',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data list of field (key) with value.
|
||||
*/
|
||||
private function update(array $data)
|
||||
{
|
||||
$data['updated_at'] = new \DateTime();
|
||||
$key['project_id'] = $data['project_id'];
|
||||
$key['library'] = $data['library'];
|
||||
unset($data['project_id']);
|
||||
unset($data['library']);
|
||||
if (array_key_exists('deprecated', $data)) {
|
||||
unset($data['deprecated']);
|
||||
}
|
||||
|
||||
$this->connexion->update(
|
||||
$this->config['table_name'],
|
||||
$data,
|
||||
$key,
|
||||
[
|
||||
'version' => 'string',
|
||||
'state' => 'string',
|
||||
'to_library' => 'string',
|
||||
'to_version' => 'string',
|
||||
'updated_at' => 'datetime',
|
||||
'library' => 'string',
|
||||
'project_id' => 'integer'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all dependency to deleted.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
private function removeAll($project)
|
||||
{
|
||||
$data = ['state' => 'removed', 'to_library' => null, 'to_version' => null];
|
||||
$data['updated_at'] = new \DateTime();
|
||||
|
||||
$this->connexion->update($this->config['table_name'], $data, ['project_id' => $project], ['string', 'string', 'string', 'datetime', 'integer']);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the index for the project code.
|
||||
*/
|
||||
private function convertProjectCode($projectCode)
|
||||
{
|
||||
if (array_key_exists($projectCode, $this->projectCodeCache)) {
|
||||
return $this->projectCodeCache[$projectCode];
|
||||
}
|
||||
|
||||
$result = $this->connexion->executeQuery('SELECT id FROM projects WHERE identifier = ?', [$projectCode], ['string']);
|
||||
$rows = $result->fetchAll();
|
||||
if (count($rows) == 0) {
|
||||
$this->projectCodeCache[$projectCode] = null;
|
||||
|
||||
return;
|
||||
}
|
||||
$this->projectCodeCache[$projectCode] = intval($rows[0]['id']);
|
||||
|
||||
return $this->projectCodeCache[$projectCode];
|
||||
}
|
||||
}
|
||||
55
src/Persistence/YamlFile.php
Normal file
55
src/Persistence/YamlFile.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Persistence;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class YamlFile implements Persistence
|
||||
{
|
||||
/**
|
||||
* @var string default path of file
|
||||
*/
|
||||
private $filePath;
|
||||
/**
|
||||
* @var string default path of file
|
||||
*/
|
||||
private $fileSecurityPath;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
*/
|
||||
public function __construct(array $config)
|
||||
{
|
||||
$this->filePath = $config['path'];
|
||||
$this->fileSecurityPath = $config['path_security'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $content Content to save
|
||||
* @param array $config custom config
|
||||
*/
|
||||
public function save(array $content, array $config = null)
|
||||
{
|
||||
$content = Yaml::dump($content, 100);
|
||||
file_put_contents(($config !== null && isset($config['path']))? $config['path']:$this->filePath, $content);
|
||||
}
|
||||
|
||||
|
||||
public function saveSecurity(array $content, array $config = null)
|
||||
{
|
||||
$content = Yaml::dump($content, 100);
|
||||
file_put_contents(($config !== null && isset($config['path_security']))? $config['path_security']:$this->fileSecurityPath, $content);
|
||||
}
|
||||
}
|
||||
83
src/ProjectProvider/DbalProvider.php
Normal file
83
src/ProjectProvider/DbalProvider.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\ProjectProvider;
|
||||
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
use Mactronique\CUA\Configuration\ProjectConfiguration;
|
||||
|
||||
class DbalProvider implements ProjectProviderInterface
|
||||
{
|
||||
private $config;
|
||||
|
||||
private $projects;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
if (null !== $config || !is_array($config)) {
|
||||
throw new \Exception("The configuration is not set or not an array", 1);
|
||||
}
|
||||
|
||||
$this->config = $config;
|
||||
|
||||
if (!isset($config['working_dir']) || !is_dir($config['working_dir'])) {
|
||||
throw new \Exception("working_dir configuration key is not set or not exists", 1);
|
||||
}
|
||||
|
||||
if (!isset($config['db']) || !is_array($config['db'])) {
|
||||
throw new \Exception("db configuration key is not set or is not an array", 1);
|
||||
}
|
||||
|
||||
if (!isset($config['table_name']) || !is_string($config['table_name'])) {
|
||||
throw new \Exception("table_name configuration key is not set or is not a string", 1);
|
||||
}
|
||||
}
|
||||
|
||||
public function getProjects()
|
||||
{
|
||||
if (null !== $this->projects && is_array($this->projects)) {
|
||||
return $this->projects;
|
||||
}
|
||||
|
||||
$connexion = \Doctrine\DBAL\DriverManager::getConnection($this->config['db']);
|
||||
$connexion->connect();
|
||||
|
||||
$config = [];
|
||||
$result = $connexion->executeQuery(sprintf("SELECT code, name, path, check_dependencies, check_security, lock_path, php_path, private_dependencies FROM %s WHERE check_dependencies = '1' or check_security = '1'", $this->config['db']['table_name']));
|
||||
while ($ligne = $result->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$conf = [
|
||||
'path' => $this->config['working_dir'].DIRECTORY_SEPARATOR.$ligne['path'],
|
||||
'check_dependencies' => boolval($ligne['check_dependencies']),
|
||||
'check_security' => boolval($ligne['check_security']),
|
||||
];
|
||||
|
||||
if (!empty($ligne['private_dependencies'])) {
|
||||
$conf['private_dependencies'] = json_decode($ligne['private_dependencies'], true);
|
||||
// JSON decode silent error
|
||||
if ($conf['private_dependencies'] === false) {
|
||||
$conf['private_dependencies'] = null;
|
||||
}
|
||||
}
|
||||
if (!empty($ligne['lock_path'])) {
|
||||
$conf['lock_path'] = $ligne['lock_path'];
|
||||
}
|
||||
if (!empty($ligne['php_path'])) {
|
||||
$conf['php_path'] = $ligne['php_path'];
|
||||
}
|
||||
$config[$ligne['code']] = $conf;
|
||||
}
|
||||
|
||||
$configs = [['projects' => $config]];
|
||||
$processor = new Processor();
|
||||
$configuration = new ProjectConfiguration();
|
||||
$this->projects = $processor->processConfiguration($configuration, $configs)['projects'];
|
||||
|
||||
return $this->projects;
|
||||
}
|
||||
}
|
||||
48
src/ProjectProvider/FileProvider.php
Normal file
48
src/ProjectProvider/FileProvider.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\ProjectProvider;
|
||||
|
||||
use Mactronique\CUA\Configuration\ProjectConfiguration;
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class FileProvider implements ProjectProviderInterface
|
||||
{
|
||||
private $config;
|
||||
|
||||
private $projects;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
if (!isset($config['path'])) {
|
||||
throw new \Exception("The path of file project is not set !", 1);
|
||||
}
|
||||
}
|
||||
|
||||
public function getProjects()
|
||||
{
|
||||
if (null !== $this->projects && is_array($this->projects)) {
|
||||
return $this->projects;
|
||||
}
|
||||
$filePath = __DIR__.'/../../'.$this->config['path'];
|
||||
if (!file_exists($filePath)) {
|
||||
throw new \Exception("Unable to load file : ".$filePath, 1);
|
||||
}
|
||||
$config = Yaml::parse(file_get_contents($filePath));
|
||||
|
||||
$configs = [$config];
|
||||
$processor = new Processor();
|
||||
$configuration = new ProjectConfiguration();
|
||||
$this->projects = $processor->processConfiguration($configuration, $configs)['projects'];
|
||||
|
||||
return $this->projects;
|
||||
}
|
||||
}
|
||||
19
src/ProjectProvider/ProjectProviderInterface.php
Normal file
19
src/ProjectProvider/ProjectProviderInterface.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\ProjectProvider;
|
||||
|
||||
interface ProjectProviderInterface
|
||||
{
|
||||
/**
|
||||
* return the list of project with configuration
|
||||
* @return array
|
||||
*/
|
||||
public function getProjects();
|
||||
}
|
||||
66
src/ProjectProvider/RedmineProvider.php
Normal file
66
src/ProjectProvider/RedmineProvider.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\ProjectProvider;
|
||||
|
||||
use Symfony\Component\Config\Definition\Processor;
|
||||
use Mactronique\CUA\Configuration\ProjectConfiguration;
|
||||
|
||||
class RedmineProvider implements ProjectProviderInterface
|
||||
{
|
||||
private $config;
|
||||
|
||||
private $projects;
|
||||
|
||||
public function __construct($config)
|
||||
{
|
||||
$this->config = $config;
|
||||
if (!isset($config['working_dir']) || !is_dir($config['working_dir'])) {
|
||||
throw new \Exception("working_dir configuration key is not set or not exists", 1);
|
||||
}
|
||||
|
||||
if (!isset($config['db']) || !is_array($config['db'])) {
|
||||
throw new \Exception("db configuration key is not set or is not an array", 1);
|
||||
}
|
||||
}
|
||||
|
||||
public function getProjects()
|
||||
{
|
||||
if (null !== $this->projects && is_array($this->projects)) {
|
||||
return $this->projects;
|
||||
}
|
||||
|
||||
$connexion = \Doctrine\DBAL\DriverManager::getConnection($this->config['db']);
|
||||
$connexion->connect();
|
||||
|
||||
$config = [];
|
||||
$result = $connexion->executeQuery(sprintf("SELECT s.*, p.identifier as pid FROM `%s` s LEFT JOIN `projects` p ON s.project_id = p.id LEFT JOIN `repositories` r ON s.project_id = r.project_id WHERE p.status= '1' and r.is_default = '1'", $this->config['db']['table_name']));
|
||||
while ($ligne = $result->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$conf = [
|
||||
'path' => $this->config['working_dir'].'/'.$ligne['pid'],
|
||||
'check_dependencies' => boolval($ligne['check_update']),
|
||||
'check_security' => boolval($ligne['check_security']),
|
||||
];
|
||||
if (!empty($ligne['lock_path'])) {
|
||||
$conf['lock_path'] = $ligne['lock_path'];
|
||||
}
|
||||
if (!empty($ligne['php_bin'])) {
|
||||
$conf['php_path'] = $ligne['php_bin'];
|
||||
}
|
||||
$config[$ligne['pid']] = $conf;
|
||||
}
|
||||
|
||||
$configs = [['projects' => $config]];
|
||||
$processor = new Processor();
|
||||
$configuration = new ProjectConfiguration();
|
||||
$this->projects = $processor->processConfiguration($configuration, $configs)['projects'];
|
||||
|
||||
return $this->projects;
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <jbnahan@gmail.com>
|
||||
* @copyright 2016 - Jean-Baptiste Nahan
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Service;
|
||||
@@ -15,25 +15,32 @@ use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
|
||||
class CheckUpdateService
|
||||
{
|
||||
|
||||
class CheckUpdateService {
|
||||
/**
|
||||
* @var LoggerInterface|NullLogger
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $composerPath;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $composerPath;
|
||||
|
||||
/**
|
||||
* Construct the service
|
||||
* @param string $composerPath
|
||||
*/
|
||||
public function __construct($composerPath, LoggerInterface $logger = null){
|
||||
$this->composerPath = $composerPath;
|
||||
$this->logger = ($logger === null)? new NullLogger():$logger;
|
||||
}
|
||||
/**
|
||||
* Construct the service
|
||||
* @param string $composerPath
|
||||
*/
|
||||
public function __construct($composerPath, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->composerPath = $composerPath;
|
||||
$this->logger = ($logger === null)? new NullLogger():$logger;
|
||||
}
|
||||
|
||||
public function checkComposerUpdate($projectPath){
|
||||
$resultProject = [
|
||||
public function checkComposerUpdate($projectPath, $php_path)
|
||||
{
|
||||
$resultProject = [
|
||||
'install' => [],
|
||||
'uninstall' => [],
|
||||
'update' => [],
|
||||
@@ -41,17 +48,17 @@ class CheckUpdateService {
|
||||
'error' => '',
|
||||
];
|
||||
|
||||
$process = new Process($this->composerPath.' update --dry-run --no-ansi');
|
||||
$process = new Process($php_path.' '.$this->composerPath.' update --dry-run --no-ansi');
|
||||
$process->setWorkingDirectory($projectPath);
|
||||
$process->setTimeout(300);
|
||||
try {
|
||||
$process->mustRun();
|
||||
} catch (ProcessFailedException $e) {
|
||||
$this->logger->error('Process Fail', ['projectPath'=>$projectPath, 'exception'=>$e]);
|
||||
$this->logger->error('Process Fail', ['projectPath'=>$projectPath, 'exception'=>$e]);
|
||||
$resultProject['error'] = $process->getErrorOutput();
|
||||
return $resultProject;
|
||||
} catch (ProcessTimedOutException $e) {
|
||||
$this->logger->error('Process time out', ['projectPath'=>$projectPath, 'exception'=>$e]);
|
||||
$this->logger->error('Process time out', ['projectPath'=>$projectPath, 'exception'=>$e]);
|
||||
$resultProject['error'] = 'Time out '.$e->getMessage();
|
||||
return $resultProject;
|
||||
}
|
||||
@@ -87,5 +94,5 @@ class CheckUpdateService {
|
||||
$resultProject['abandoned'] = $abandoned[1];
|
||||
}
|
||||
return $resultProject;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
51
src/Service/InstalledLibraryService.php
Normal file
51
src/Service/InstalledLibraryService.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
namespace Mactronique\CUA\Service;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
class InstalledLibraryService
|
||||
{
|
||||
/**
|
||||
* Construct the service.
|
||||
*
|
||||
* @param string $composerPath
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger = null)
|
||||
{
|
||||
$this->logger = ($logger === null) ? new NullLogger() : $logger;
|
||||
}
|
||||
|
||||
public function getInstalledLibrary($projectPath)
|
||||
{
|
||||
$finder = new Finder();
|
||||
|
||||
$libraries = [];
|
||||
$composer = $finder->in($projectPath)->files()->name('composer.lock');
|
||||
foreach ($composer as $file) {
|
||||
$json = json_decode($file->getContents(), true);
|
||||
|
||||
foreach ($json['packages'] as $value) {
|
||||
$libraries[$value['name']] = $value['version'];
|
||||
}
|
||||
if (!isset($json['platform'])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($json['platform'] as $platform => $version) {
|
||||
$libraries[$platform] = $version;
|
||||
}
|
||||
}
|
||||
|
||||
return $libraries;
|
||||
}
|
||||
}
|
||||
127
src/Service/SecurityCheckService.php
Normal file
127
src/Service/SecurityCheckService.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Service;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
use SensioLabs\Security\SecurityChecker;
|
||||
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\ProcessFailedException;
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
|
||||
class SecurityCheckService
|
||||
{
|
||||
const INTERNAL = 'internal';
|
||||
|
||||
/** @var string */
|
||||
private $securityCheckPath;
|
||||
|
||||
/** @var LoggerInterface */
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* SecurityCheckService constructor.
|
||||
* @param string $securityCheckPath
|
||||
* @param LoggerInterface|null $logger
|
||||
*/
|
||||
public function __construct($securityCheckPath, LoggerInterface $logger = null)
|
||||
{
|
||||
$this->securityCheckPath = $securityCheckPath;
|
||||
$this->logger = ($logger === null)? new NullLogger():$logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $projectPath
|
||||
* @param string $lockPath
|
||||
* @param string $phpPath
|
||||
* @return array
|
||||
*/
|
||||
public function checkSecurity($projectPath, $lockPath, $phpPath)
|
||||
{
|
||||
if (strtolower($this->securityCheckPath) === self::INTERNAL){
|
||||
return $this->checkSecurityInt($projectPath, $lockPath);
|
||||
}
|
||||
return $this->checkSecurityExt($projectPath, $lockPath, $phpPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check security with the integrated checker
|
||||
* @param string $projectPath
|
||||
* @param string $lockPath
|
||||
* @return array
|
||||
*/
|
||||
private function checkSecurityInt($projectPath, $lockPath)
|
||||
{
|
||||
$resultProject = [
|
||||
'error' => '',
|
||||
'result' => [],
|
||||
];
|
||||
|
||||
try {
|
||||
$result = (string) (new SecurityChecker())->check($lockPath);
|
||||
|
||||
return $this->processJson($result, $resultProject, $projectPath);
|
||||
} catch(\Exception $e) {
|
||||
$resultProject['error'] = $e->getMessage();
|
||||
}
|
||||
|
||||
return $resultProject;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use external checker
|
||||
* @param string $projectPath
|
||||
* @param string $lockPath
|
||||
* @param string $phpPath
|
||||
* @return array
|
||||
*/
|
||||
private function checkSecurityExt($projectPath, $lockPath, $phpPath)
|
||||
{
|
||||
$resultProject = [
|
||||
'error' => '',
|
||||
'result' => [],
|
||||
];
|
||||
$process = new Process($phpPath.' '.$this->securityCheckPath.' security:check '.$lockPath.' --format=json ');
|
||||
$process->setWorkingDirectory($projectPath);
|
||||
$process->setTimeout(3000);
|
||||
try {
|
||||
$returnCode = $process->run();
|
||||
$sortieErr = $process->getErrorOutput();
|
||||
if (strlen($sortieErr) > 0) {
|
||||
$resultProject['error'] = 'Result code' . $returnCode. "\n" . $sortieErr;
|
||||
}
|
||||
|
||||
return $this->processJson($process->getOutput(), $resultProject, $projectPath);
|
||||
} catch (ProcessTimedOutException $e) {
|
||||
$this->logger->error('Process time out', ['projectPath'=>$projectPath, 'exception'=>$e]);
|
||||
$resultProject['error'] = 'Time out '.$e->getMessage();
|
||||
return $resultProject;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $jsonString
|
||||
* @param array $resultProject
|
||||
* @param string $projectPath
|
||||
* @return mixed
|
||||
*/
|
||||
private function processJson($jsonString, $resultProject, $projectPath)
|
||||
{
|
||||
$datas = json_decode($jsonString, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
$this->logger->error('Json decode error', ['projectPath'=>$projectPath, 'json_error'=>json_last_error_msg()]);
|
||||
$resultProject['error'] .= 'Json decode error '.json_last_error_msg();
|
||||
return $resultProject;
|
||||
}
|
||||
$resultProject['result'] = $datas;
|
||||
return $resultProject;
|
||||
}
|
||||
}
|
||||
78
src/Sql/Create_Table_MSSQL.sql
Normal file
78
src/Sql/Create_Table_MSSQL.sql
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
--- FOR MSSQL
|
||||
|
||||
SET ANSI_NULLS ON
|
||||
GO
|
||||
|
||||
SET QUOTED_IDENTIFIER ON
|
||||
GO
|
||||
|
||||
if not exists (select * from sysobjects where name='dependencies' and xtype='U')
|
||||
CREATE TABLE [dbo].[dependencies](
|
||||
[id] [int] IDENTITY(1,1) NOT NULL,
|
||||
[project] [nvarchar](50) NOT NULL,
|
||||
[library] [nvarchar](250) NOT NULL,
|
||||
[version] [nvarchar](250) NOT NULL,
|
||||
[state] [nvarchar](20) NOT NULL,
|
||||
[to_library] [nvarchar](250) DEFAULT NULL,
|
||||
[to_version] [nvarchar](250) DEFAULT NULL,
|
||||
[deprecated] [bit] DEFAULT NULL,
|
||||
[updated_at] [datetime2](7) NOT NULL,
|
||||
CONSTRAINT [PK_dependencies] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[id] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||
) ON [PRIMARY]
|
||||
GO
|
||||
|
||||
if not exists (select * from sysobjects where name='idx_proj_lib' and xtype='UQ')
|
||||
ALTER TABLE [dbo].[dependencies] ADD CONSTRAINT [idx_proj_lib] UNIQUE NONCLUSTERED
|
||||
(
|
||||
[project] ASC,
|
||||
[library] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||
GO
|
||||
|
||||
if not exists (select * from sysobjects where name='security' and xtype='U')
|
||||
CREATE TABLE [dbo].[security](
|
||||
[id] [int] IDENTITY(1,1) NOT NULL,
|
||||
[project] [nvarchar](50) NOT NULL,
|
||||
[library] [nvarchar](255) NOT NULL,
|
||||
[version] [nvarchar](255) NOT NULL,
|
||||
[state] [nvarchar](20) NOT NULL,
|
||||
[details] [text] NOT NULL,
|
||||
[updated_at] [datetime2](7) NOT NULL,
|
||||
CONSTRAINT [PK_security] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[id] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
|
||||
GO
|
||||
|
||||
|
||||
if not exists (select * from sysobjects where name='projects' and xtype='U')
|
||||
CREATE TABLE [dbo].[projects] (
|
||||
[code] [nvarchar](10) NOT NULL,
|
||||
[name] [nvarchar](100) NOT NULL,
|
||||
[path] [nvarchar](255) NOT NULL,
|
||||
[lock_path] [nvarchar](255) NOT NULL,
|
||||
[php_path] [nvarchar](255) NOT NULL,
|
||||
[private_dependencies] [nvarchar](max) DEFAULT NULL,
|
||||
[private_dependencies_strategy] [nvarchar](10) DEFAULT 'remove',
|
||||
[check_dependencies] [bit] DEFAULT NULL,
|
||||
[check_security] [bit] DEFAULT NULL,
|
||||
[updated_at] [datetime2](7) NOT NULL
|
||||
CONSTRAINT [PK_project] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[code] ASC
|
||||
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
|
||||
) ON [PRIMARY]
|
||||
GO
|
||||
|
||||
66
src/Sql/Create_Table_MySQL.sql
Normal file
66
src/Sql/Create_Table_MySQL.sql
Normal file
@@ -0,0 +1,66 @@
|
||||
##
|
||||
## This file is part of Composer Update Analyser package.
|
||||
##
|
||||
## @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
## @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
## @license MIT
|
||||
##
|
||||
|
||||
## FOR MySQL
|
||||
|
||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||
SET time_zone = "+00:00";
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `dependencies` (
|
||||
`id` int(11) NOT NULL,
|
||||
`project` varchar(50) NOT NULL,
|
||||
`library` varchar(250) NOT NULL,
|
||||
`version` varchar(250) NOT NULL,
|
||||
`state` varchar(20) NOT NULL,
|
||||
`to_library` varchar(250) DEFAULT NULL,
|
||||
`to_version` varchar(250) DEFAULT NULL,
|
||||
`deprecated` tinyint(1) DEFAULT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `dependencies`
|
||||
ADD PRIMARY KEY (`id`),
|
||||
ADD UNIQUE KEY `idx_proj_lib` (`project`,`library`(191)) USING BTREE,
|
||||
ADD KEY `idx_plv` (`project`,`library`(191),`version`(191));
|
||||
|
||||
ALTER TABLE `dependencies`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `security` (
|
||||
`id` int(11) NOT NULL,
|
||||
`project` varchar(50) NOT NULL,
|
||||
`library` varchar(255) NOT NULL,
|
||||
`version` varchar(255) NOT NULL,
|
||||
`state` varchar(20) NOT NULL,
|
||||
`details` text NOT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `security`
|
||||
ADD PRIMARY KEY (`id`);
|
||||
|
||||
ALTER TABLE `security`
|
||||
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `projects` (
|
||||
`code` varchar(10) NOT NULL,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`path` varchar(255) NOT NULL,
|
||||
`lock_path` varchar(255) NOT NULL,
|
||||
`php_path` varchar(255) NOT NULL,
|
||||
`private_dependencies` text DEFAULT NULL,
|
||||
`private_dependencies_strategy` varchar(10) DEFAULT 'remove',
|
||||
`check_dependencies` tinyint(1) DEFAULT NULL,
|
||||
`check_security` tinyint(1) DEFAULT NULL,
|
||||
`updated_at` datetime NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
ALTER TABLE `projects`
|
||||
ADD PRIMARY KEY (`code`);
|
||||
45
src/Sql/Create_Table_PGSQL.sql
Normal file
45
src/Sql/Create_Table_PGSQL.sql
Normal file
@@ -0,0 +1,45 @@
|
||||
CREATE TABLE "dependencies" (
|
||||
"id" serial NOT NULL PRIMARY KEY,
|
||||
"project" varchar(50) NOT NULL,
|
||||
"library" varchar(250) NOT NULL,
|
||||
"version" varchar(250) NOT NULL,
|
||||
"state" varchar(20) NOT NULL,
|
||||
"to_library" varchar(250) NULL,
|
||||
"to_version" varchar(250) NULL,
|
||||
"deprecated" boolean NULL,
|
||||
"updated_at" timestamp NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX CONCURRENTLY idx_proj_lib
|
||||
ON dependencies (project, library);
|
||||
|
||||
ALTER TABLE dependencies
|
||||
ADD CONSTRAINT unique_proj_lib
|
||||
UNIQUE USING INDEX idx_proj_lib;
|
||||
|
||||
CREATE INDEX idx_plv
|
||||
ON dependencies (project, library, version);
|
||||
|
||||
CREATE TABLE "security" (
|
||||
"id" serial NOT NULL PRIMARY KEY,
|
||||
"project" varchar(50) NOT NULL,
|
||||
"library" varchar(250) NOT NULL,
|
||||
"version" varchar(250) NOT NULL,
|
||||
"state" varchar(20) NOT NULL,
|
||||
"details" text NOT NULL,
|
||||
"updated_at" timestamp NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE "projects" (
|
||||
"code" varchar(10) NOT NULL PRIMARY KEY,
|
||||
"name" varchar(100) NOT NULL,
|
||||
"path" varchar(255) NOT NULL,
|
||||
"lock_path" varchar(255) NOT NULL,
|
||||
"php_path" varchar(255) NOT NULL,
|
||||
"private_dependencies" text DEFAULT NULL,
|
||||
"private_dependencies_strategy" varchar(10) DEFAULT 'remove',
|
||||
"check_dependencies" boolean DEFAULT NULL,
|
||||
"check_security" boolean DEFAULT NULL,
|
||||
"updated_at" timestamp NOT NULL
|
||||
);
|
||||
36
src/Sql/Create_Table_SQLite.sql
Normal file
36
src/Sql/Create_Table_SQLite.sql
Normal file
@@ -0,0 +1,36 @@
|
||||
CREATE TABLE "dependencies" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"project" TEXT NOT NULL,
|
||||
"library" TEXT NOT NULL,
|
||||
"version" TEXT NOT NULL,
|
||||
"state" TEXT NOT NULL,
|
||||
"to_library" TEXT,
|
||||
"to_version" TEXT,
|
||||
"deprecated" INTEGER,
|
||||
"updated_at" TEXT NOT NULL
|
||||
);
|
||||
|
||||
|
||||
CREATE TABLE "security" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"projet" TEXT NOT NULL,
|
||||
"library" TEXT NOT NULL,
|
||||
"version" TEXT NOT NULL,
|
||||
"state" TEXT NOT NULL,
|
||||
"details" TEXT NOT NULL,
|
||||
"updated_at" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE "projects" (
|
||||
"code" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"path" TEXT NOT NULL,
|
||||
"lock_path" TEXT NOT NULL,
|
||||
"php_path" TEXT NOT NULL,
|
||||
"private_dependencies" TEXT,
|
||||
"private_dependencies_strategy" TEXT DEFAULT 'remove',
|
||||
"check_dependencies" INTEGER,
|
||||
"check_security" INTEGER,
|
||||
"updated_at" TEXT NOT NULL,
|
||||
PRIMARY KEY("code")
|
||||
);
|
||||
20
tests/Units/Persistence/YamlFile.php
Normal file
20
tests/Units/Persistence/YamlFile.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of Composer Update Analyser package.
|
||||
*
|
||||
* @author Jean-Baptiste Nahan <814683+macintoshplus@users.noreply.github.com>
|
||||
* @copyright 2016-2019 - Jean-Baptiste Nahan
|
||||
* @license MIT
|
||||
*/
|
||||
namespace Mactronique\CUA\Tests\Units\Persistence;
|
||||
|
||||
use atoum;
|
||||
|
||||
class YamlFile extends atoum
|
||||
{
|
||||
public function testInit()
|
||||
{
|
||||
$this->newTestedInstance(['path'=>'here', 'path_security'=>'here_security']);
|
||||
$this->assert('type')->object($this->testedInstance)->isInstanceOf('Mactronique\CUA\Persistence\Persistence');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user