The clean & modern RSS server that doesn't give you any crap. https://thearsse.com/
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.

RoboFile.php 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <?php
  2. use Robo\Result;
  3. const BASE = __DIR__.\DIRECTORY_SEPARATOR;
  4. const BASE_TEST = BASE."tests".\DIRECTORY_SEPARATOR;
  5. define("IS_WIN", defined("PHP_WINDOWS_VERSION_MAJOR"));
  6. define("IS_MAC", php_uname("s") === "Darwin");
  7. function norm(string $path): string {
  8. $out = realpath($path);
  9. if (!$out) {
  10. $out = str_replace(["/", "\\"], \DIRECTORY_SEPARATOR, $path);
  11. }
  12. return $out;
  13. }
  14. class RoboFile extends \Robo\Tasks {
  15. /** Runs the typical test suite
  16. *
  17. * Arguments passed to the task are passed on to PHPUnit. Thus one may, for
  18. * example, run the following command and get the expected results:
  19. *
  20. * ./robo test --testsuite TTRSS --exclude-group slow --testdox
  21. *
  22. * Please see the PHPUnit documentation for available options.
  23. */
  24. public function test(array $args): Result {
  25. return $this->runTests(escapeshellarg(\PHP_BINARY), "typical", $args);
  26. }
  27. /** Runs the full test suite
  28. *
  29. * This includes pedantic tests which may help to identify problems.
  30. * See help for the "test" task for more details.
  31. */
  32. public function testFull(array $args): Result {
  33. return $this->runTests(escapeshellarg(\PHP_BINARY), "full", $args);
  34. }
  35. /**
  36. * Runs a quick subset of the test suite
  37. *
  38. * See help for the "test" task for more details.
  39. */
  40. public function testQuick(array $args): Result {
  41. return $this->runTests(escapeshellarg(\PHP_BINARY), "quick", $args);
  42. }
  43. /** Produces a code coverage report
  44. *
  45. * By default this task produces an HTML-format coverage report in
  46. * tests/coverage/. Additional reports may be produced by passing
  47. * arguments to this task as one would to PHPUnit.
  48. *
  49. * Robo first tries to use phpdbg and will fall back to Xdebug if available.
  50. * Because Xdebug slows down non-coverage tasks, however, phpdbg is highly
  51. * recommended if debugging facilities are not otherwise needed.
  52. */
  53. public function coverage(array $args): Result {
  54. // run tests with code coverage reporting enabled
  55. $exec = $this->findCoverageEngine();
  56. return $this->runTests($exec, "coverage", array_merge(["--coverage-html", BASE_TEST."coverage"], $args));
  57. }
  58. /** Produces a code coverage report, with redundant tests
  59. *
  60. * Depending on the environment, some tests that normally provide
  61. * coverage may be skipped, while working alternatives are normally
  62. * suppressed for reasons of time. This coverage report will try to
  63. * run all tests which may cover code.
  64. *
  65. * See also help for the "coverage" task for more details.
  66. */
  67. public function coverageFull(array $args): Result {
  68. // run tests with code coverage reporting enabled
  69. $exec = $this->findCoverageEngine();
  70. return $this->runTests($exec, "typical", array_merge(["--coverage-html", BASE_TEST."coverage"], $args));
  71. }
  72. /** Runs the coding standards fixer */
  73. public function clean($opts = ['demo|d' => false]): Result {
  74. $t = $this->taskExec(norm(BASE."vendor/bin/php-cs-fixer"));
  75. $t->arg("fix");
  76. if ($opts['demo']) {
  77. $t->args("--dry-run", "--diff")->option("--diff-format", "udiff");
  78. }
  79. return $t->run();
  80. }
  81. protected function findCoverageEngine(): string {
  82. if (IS_WIN) {
  83. $dbg = dirname(\PHP_BINARY)."\\phpdbg.exe";
  84. $dbg = file_exists($dbg) ? $dbg : "";
  85. } else {
  86. $dbg = trim(`which phpdbg 2>/dev/null`);
  87. }
  88. if ($dbg) {
  89. return escapeshellarg($dbg)." -qrr";
  90. } else {
  91. $ext = IS_WIN ? "dll" : (IS_MAC ? "dylib" : "so");
  92. return escapeshellarg(\PHP_BINARY)." -d zend_extension=xdebug.$ext";
  93. }
  94. }
  95. protected function blackhole(bool $all = false): string {
  96. $hole = IS_WIN ? "nul" : "/dev/null";
  97. return $all ? ">$hole 2>&1" : "2>$hole";
  98. }
  99. protected function runTests(string $executor, string $set, array $args) : Result {
  100. switch ($set) {
  101. case "typical":
  102. $set = ["--exclude-group", "optional"];
  103. break;
  104. case "quick":
  105. $set = ["--exclude-group", "optional,slow"];
  106. break;
  107. case "coverage":
  108. $set = ["--exclude-group", "optional,coverageOptional"];
  109. break;
  110. case "full":
  111. $set = [];
  112. break;
  113. default:
  114. throw new \Exception;
  115. }
  116. $execpath = norm(BASE."vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit");
  117. $confpath = realpath(BASE_TEST."phpunit.dist.xml") ?: norm(BASE_TEST."phpunit.xml");
  118. $this->taskServer(8000)->host("localhost")->dir(BASE_TEST."docroot")->rawArg("-n")->arg(BASE_TEST."server.php")->rawArg($this->blackhole())->background()->run();
  119. return $this->taskExec($executor)->option("-d", "zend.assertions=1")->arg($execpath)->option("-c", $confpath)->args(array_merge($set, $args))->run();
  120. }
  121. /** Packages a given commit of the software into a release tarball
  122. *
  123. * The version to package may be any Git tree-ish identifier: a tag, a branch,
  124. * or any commit hash. If none is provided on the command line, Robo will prompt
  125. * for a commit to package; the default is "head".
  126. *
  127. * Note that while it is possible to re-package old versions, the resultant tarball
  128. * may not be equivalent due to subsequent changes in the exclude list, or because
  129. * of new tooling.
  130. */
  131. public function package(string $version = null): Result {
  132. // establish which commit to package
  133. $version = $version ?? $this->askDefault("Commit to package:", "HEAD");
  134. $archive = BASE."arsse-$version.tar.gz";
  135. // start a collection
  136. $t = $this->collectionBuilder();
  137. // create a temporary directory
  138. $dir = $t->tmpDir().\DIRECTORY_SEPARATOR;
  139. // create a Git worktree for the selected commit in the temp location
  140. $t->taskExec("git worktree add ".escapeshellarg($dir)." ".escapeshellarg($version));
  141. // perform Composer installation in the temp location with dev dependencies
  142. $t->taskComposerInstall()->dir($dir);
  143. // generate the manual
  144. $t->taskExec(escapeshellarg($dir."robo")." manual")->dir($dir);
  145. // perform Composer installation in the temp location for final output
  146. $t->taskComposerInstall()->dir($dir)->noDev()->optimizeAutoloader()->arg("--no-scripts");
  147. // delete unwanted files
  148. $t->taskFilesystemStack()->remove([
  149. $dir.".git",
  150. $dir.".gitignore",
  151. $dir.".gitattributes",
  152. $dir."composer.json",
  153. $dir."composer.lock",
  154. $dir.".php_cs.dist",
  155. $dir."phpdoc.dist.xml",
  156. $dir."build.xml",
  157. $dir."RoboFile.php",
  158. $dir."CONTRIBUTING.md",
  159. $dir."docs",
  160. $dir."tests",
  161. $dir."vendor-bin",
  162. $dir."vendor/bin",
  163. $dir."robo",
  164. $dir."robo.bat",
  165. $dir."package.json",
  166. $dir."yarn.lock",
  167. $dir."postcss.config.js",
  168. ]);
  169. // generate a sample configuration file
  170. $t->taskExec(escapeshellarg(\PHP_BINARY)." arsse.php conf save-defaults config.defaults.php")->dir($dir);
  171. // package it all up
  172. $t->taskPack($archive)->addDir("arsse", $dir);
  173. // execute the collection
  174. $out = $t->run();
  175. // clean the Git worktree list
  176. $this->_exec("git worktree prune");
  177. return $out;
  178. }
  179. /** Generates static manual pages in the "manual" directory
  180. *
  181. * The resultant files are suitable for offline viewing and inclusion into release builds
  182. */
  183. public function manual(array $args): Result {
  184. $execpath = escapeshellarg(norm(BASE."vendor/bin/daux"));
  185. $t = $this->collectionBuilder();
  186. $t->taskExec($execpath)->arg("generate")->option("-d", BASE."manual")->args($args);
  187. $t->taskDeleteDir(BASE."manual/daux_libraries");
  188. $t->taskDeleteDir(BASE."manual/theme");
  189. $t->taskDeleteDir(BASE."manual/themes/src");
  190. return $t->run();
  191. }
  192. /** Serves a live view of the manual using the built-in Web server */
  193. public function manualLive(array $args): Result {
  194. $execpath = escapeshellarg(norm(BASE."vendor/bin/daux"));
  195. return $this->taskExec($execpath)->arg("serve")->args($args)->run();
  196. }
  197. /** Rebuilds the entire manual theme
  198. *
  199. * This requires Node and Yarn to be installed, and only needs to be done when
  200. * Daux's theme changes
  201. */
  202. public function manualTheme(array $args): Result {
  203. $postcss = escapeshellarg(norm(BASE."node_modules/.bin/postcss"));
  204. $themesrc = norm(BASE."docs/theme/src/").\DIRECTORY_SEPARATOR;
  205. $themeout = norm(BASE."docs/theme/arsse/").\DIRECTORY_SEPARATOR;
  206. $dauxjs = norm(BASE."vendor-bin/daux/vendor/daux/daux.io/themes/daux/js/").\DIRECTORY_SEPARATOR;
  207. // start a collection; this stops after the first failure
  208. $t = $this->collectionBuilder();
  209. // install dependencies via Yarn
  210. $t->taskExec("yarn install");
  211. // compile the stylesheet
  212. $t->taskExec($postcss)->arg($themesrc."arsse.scss")->option("-o", $themeout."arsse.css");
  213. // copy JavaScript files from the Daux theme
  214. foreach (glob($dauxjs."daux*.js") as $file) {
  215. $t->taskFilesystemStack()->copy($file, $themeout.basename($file), true);
  216. }
  217. // execute the collection
  218. return $t->run();
  219. }
  220. }