Do you wish to register an account?
API client for Kitsu.io, with optional Anime collection, and optional Anilist syncing.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
5.9KB

  1. <?php declare(strict_types=1);
  2. use Robo\Tasks;
  3. if ( ! function_exists('glob_recursive'))
  4. {
  5. // Does not support flag GLOB_BRACE
  6. function glob_recursive($pattern, $flags = 0)
  7. {
  8. $files = glob($pattern, $flags);
  9. foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR|GLOB_NOSORT) as $dir)
  10. {
  11. $files = array_merge($files, glob_recursive($dir.'/'.basename($pattern), $flags));
  12. }
  13. return $files;
  14. }
  15. }
  16. /**
  17. * This is project's console commands configuration for Robo task runner.
  18. *
  19. * @see http://robo.li/
  20. */
  21. class RoboFile extends Tasks {
  22. /**
  23. * Directories used by analysis tools
  24. *
  25. * @var array
  26. */
  27. protected $taskDirs = [
  28. 'build/logs',
  29. 'build/pdepend',
  30. 'build/phpdox',
  31. ];
  32. /**
  33. * Directories to remove with the clean task
  34. *
  35. * @var array
  36. */
  37. protected $cleanDirs = [
  38. 'coverage',
  39. 'docs',
  40. 'phpdoc',
  41. 'build/logs',
  42. 'build/phpdox',
  43. 'build/pdepend'
  44. ];
  45. /**
  46. * Do static analysis tasks
  47. */
  48. public function analyze(): void
  49. {
  50. $this->prepare();
  51. $this->lint();
  52. $this->phploc(TRUE);
  53. $this->phpcs(TRUE);
  54. $this->phpmd(TRUE);
  55. $this->dependencyReport();
  56. $this->phpcpdReport();
  57. }
  58. /**
  59. * Run all tests, generate coverage, generate docs, generate code statistics
  60. */
  61. public function build(): void
  62. {
  63. $this->analyze();
  64. $this->coverage();
  65. $this->docs();
  66. }
  67. /**
  68. * Cleanup temporary files
  69. */
  70. public function clean(): void
  71. {
  72. $cleanFiles = [
  73. 'build/humbug.json',
  74. 'build/humbug-log.txt',
  75. ];
  76. array_map(static function ($file) {
  77. @unlink($file);
  78. }, $cleanFiles);
  79. // So the task doesn't complain,
  80. // make any 'missing' dirs to cleanup
  81. array_map(static function ($dir) {
  82. if ( ! is_dir($dir))
  83. {
  84. `mkdir -p {$dir}`;
  85. }
  86. }, $this->cleanDirs);
  87. $this->_cleanDir($this->cleanDirs);
  88. $this->_deleteDir($this->cleanDirs);
  89. }
  90. /**
  91. * Run unit tests and generate coverage reports
  92. */
  93. public function coverage(): void
  94. {
  95. $this->_run(['phpdbg -qrr -- vendor/bin/phpunit -c build']);
  96. }
  97. /**
  98. * Generate documentation with phpdox
  99. */
  100. public function docs(): void
  101. {
  102. $cmd_parts = [
  103. 'vendor/bin/phpdox',
  104. ];
  105. $this->_run($cmd_parts, ' && ');
  106. }
  107. /**
  108. * Verify that source files are valid
  109. */
  110. public function lint(): void
  111. {
  112. $files = $this->getAllSourceFiles();
  113. $chunks = array_chunk($files, (int)shell_exec('getconf _NPROCESSORS_ONLN'));
  114. foreach($chunks as $chunk)
  115. {
  116. $this->parallelLint($chunk);
  117. }
  118. }
  119. /**
  120. * Run the phpcs tool
  121. *
  122. * @param bool $report - if true, generates reports instead of direct output
  123. */
  124. public function phpcs($report = FALSE): void
  125. {
  126. $report_cmd_parts = [
  127. 'vendor/bin/phpcs',
  128. '--standard=./build/phpcs.xml',
  129. '--report-checkstyle=./build/logs/phpcs.xml',
  130. ];
  131. $normal_cmd_parts = [
  132. 'vendor/bin/phpcs',
  133. '--standard=./build/phpcs.xml',
  134. ];
  135. $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
  136. $this->_run($cmd_parts);
  137. }
  138. public function phpmd($report = FALSE): void
  139. {
  140. $report_cmd_parts = [
  141. 'vendor/bin/phpmd',
  142. './src',
  143. 'xml',
  144. 'cleancode,codesize,controversial,design,naming,unusedcode',
  145. '--exclude ParallelAPIRequest',
  146. '--reportfile ./build/logs/phpmd.xml'
  147. ];
  148. $normal_cmd_parts = [
  149. 'vendor/bin/phpmd',
  150. './src',
  151. 'ansi',
  152. 'cleancode,codesize,controversial,design,naming,unusedcode',
  153. '--exclude ParallelAPIRequest'
  154. ];
  155. $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
  156. $this->_run($cmd_parts);
  157. }
  158. /**
  159. * Run the phploc tool
  160. *
  161. * @param bool $report - if true, generates reports instead of direct output
  162. */
  163. public function phploc($report = FALSE): void
  164. {
  165. // Command for generating reports
  166. $report_cmd_parts = [
  167. 'vendor/bin/phploc',
  168. '--count-tests',
  169. '--log-csv=build/logs/phploc.csv',
  170. '--log-xml=build/logs/phploc.xml',
  171. 'src',
  172. 'tests'
  173. ];
  174. // Command for generating direct output
  175. $normal_cmd_parts = [
  176. 'vendor/bin/phploc',
  177. '--count-tests',
  178. 'src',
  179. 'tests'
  180. ];
  181. $cmd_parts = ($report) ? $report_cmd_parts : $normal_cmd_parts;
  182. $this->_run($cmd_parts);
  183. }
  184. /**
  185. * Create temporary directories
  186. */
  187. public function prepare(): void
  188. {
  189. array_map([$this, '_mkdir'], $this->taskDirs);
  190. }
  191. /**
  192. * Lint php files and run unit tests
  193. */
  194. public function test(): void
  195. {
  196. $this->lint();
  197. $this->_run(['phpunit']);
  198. }
  199. /**
  200. * Create pdepend reports
  201. */
  202. protected function dependencyReport(): void
  203. {
  204. $cmd_parts = [
  205. 'vendor/bin/pdepend',
  206. '--jdepend-xml=build/logs/jdepend.xml',
  207. '--jdepend-chart=build/pdepend/dependencies.svg',
  208. '--overview-pyramid=build/pdepend/overview-pyramid.svg',
  209. 'src'
  210. ];
  211. $this->_run($cmd_parts);
  212. }
  213. /**
  214. * Get the total list of source files, including tests
  215. *
  216. * @return array
  217. */
  218. protected function getAllSourceFiles(): array
  219. {
  220. $files = array_merge(
  221. glob_recursive('build/*.php'),
  222. glob_recursive('src/*.php'),
  223. glob_recursive('src/**/*.php'),
  224. glob_recursive('tests/*.php'),
  225. glob_recursive('tests/**/*.php'),
  226. glob('*.php')
  227. );
  228. $files = array_filter($files, static function(string $value) {
  229. return strpos($value, '__snapshots__') === FALSE;
  230. });
  231. sort($files);
  232. return $files;
  233. }
  234. /**
  235. * Run php's linter in one parallel task for the passed chunk
  236. *
  237. * @param array $chunk
  238. */
  239. protected function parallelLint(array $chunk): void
  240. {
  241. $task = $this->taskParallelExec()
  242. ->timeout(5)
  243. ->printed(FALSE);
  244. foreach($chunk as $file)
  245. {
  246. $task = $task->process("php -l {$file}");
  247. }
  248. $task->run();
  249. }
  250. /**
  251. * Generate copy paste detector report
  252. */
  253. protected function phpcpdReport(): void
  254. {
  255. $cmd_parts = [
  256. 'vendor/bin/phpcpd',
  257. '--log-pmd build/logs/pmd-cpd.xml',
  258. 'src'
  259. ];
  260. $this->_run($cmd_parts);
  261. }
  262. /**
  263. * Shortcut for joining an array of command arguments
  264. * and then running it
  265. *
  266. * @param array $cmd_parts - command arguments
  267. * @param string $join_on - what to join the command arguments with
  268. */
  269. protected function _run(array $cmd_parts, $join_on = ' '): void
  270. {
  271. $this->taskExec(implode($join_on, $cmd_parts))->run();
  272. }
  273. }