From c56731d935e75394631222d17fd0c73115f6c58a Mon Sep 17 00:00:00 2001 From: "John Paul E. Balandan, CPA" Date: Thu, 19 Dec 2024 20:26:34 +0800 Subject: [PATCH] Add Nexus API deployment --- .gitattributes | 1 + .github/workflows/deploy-nexus-api.yml | 83 ++++++++++++++++++++++++++ .php-cs-fixer.dist.php | 1 + api/.gitignore | 3 + api/apigen.neon | 13 ++++ api/composer.json | 11 ++++ api/src/AnalyserFilter.php | 51 ++++++++++++++++ api/src/RendererFilter.php | 80 +++++++++++++++++++++++++ 8 files changed, 243 insertions(+) create mode 100644 .github/workflows/deploy-nexus-api.yml create mode 100644 api/.gitignore create mode 100644 api/apigen.neon create mode 100644 api/composer.json create mode 100644 api/src/AnalyserFilter.php create mode 100644 api/src/RendererFilter.php diff --git a/.gitattributes b/.gitattributes index 551d8c1..f024c99 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ /.* export-ignore +/api/ export-ignore /bin/ export-ignore /infection.json5 export-ignore /phpstan-baseline.php diff --git a/.github/workflows/deploy-nexus-api.yml b/.github/workflows/deploy-nexus-api.yml new file mode 100644 index 0000000..c7fc4ac --- /dev/null +++ b/.github/workflows/deploy-nexus-api.yml @@ -0,0 +1,83 @@ +name: Deploy Nexus API + +on: + push: + branches: + - '1.x' + paths: + - src + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-22.04 + if: github.repository == 'NexusPHP/framework' + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + coverage: none + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup global variables + id: globals + run: | + echo "COMPOSER_CACHE_DIR=$(composer config cache-dir)" >> $GITHUB_OUTPUT + + - name: Cache Composer dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.globals.outputs.COMPOSER_CACHE_DIR }} + key: ${{ github.workflow }}-PHP_8.3-${{ hashFiles('**/composer.json') }} + restore-keys: | + ${{ github.workflow }}-PHP_8.3- + + - name: Install dependencies + run: | + echo ::group::composer update --ansi + composer update --ansi + echo ::endgroup:: + + echo ::group::composer update --ansi --working-dir api + composer update --ansi --working-dir api + echo ::endgroup:: + + - name: Setup Pages + id: pages + uses: actions/configure-pages@v5 + + - name: Generate Nexus API + run: api/vendor/bin/apigen src --ansi --output api/docs --title Nexus --config api/apigen.neon + + - name: Upload pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: api/docs + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + runs-on: ubuntu-22.04 + needs: build + + steps: + - name: Deploy Nexus API + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 7448acc..cdab6ff 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -29,6 +29,7 @@ ->files() ->in([ __DIR__.'/.github', + __DIR__.'/api', __DIR__.'/bin', __DIR__.'/src', __DIR__.'/tests', diff --git a/api/.gitignore b/api/.gitignore new file mode 100644 index 0000000..e204c0d --- /dev/null +++ b/api/.gitignore @@ -0,0 +1,3 @@ +/docs +/vendor +/composer.lock diff --git a/api/apigen.neon b/api/apigen.neon new file mode 100644 index 0000000..fd6e84e --- /dev/null +++ b/api/apigen.neon @@ -0,0 +1,13 @@ +parameters: + title: Nexus + +services: + analyzer.filter: + factory: Nexus\Api\AnalyserFilter + arguments: + excludeProtected: %excludeProtected% + excludePrivate: %excludePrivate% + excludeTagged: %excludeTagged% + + renderer.filter: + factory: Nexus\Api\RendererFilter diff --git a/api/composer.json b/api/composer.json new file mode 100644 index 0000000..abf81fa --- /dev/null +++ b/api/composer.json @@ -0,0 +1,11 @@ +{ + "require": { + "php": "^8.3", + "apigen/apigen": "dev-master" + }, + "autoload": { + "psr-4": { + "Nexus\\Api\\": "src/" + } + } +} diff --git a/api/src/AnalyserFilter.php b/api/src/AnalyserFilter.php new file mode 100644 index 0000000..c9e0228 --- /dev/null +++ b/api/src/AnalyserFilter.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Nexus\Api; + +use ApiGen\Analyzer\Filter; +use ApiGen\Info\ClassLikeInfo; +use ApiGen\Info\MemberInfo; +use PhpParser\Node; + +final class AnalyserFilter extends Filter +{ + public function filterClassLikeNode(Node\Stmt\ClassLike $node): bool + { + $name = $node->namespacedName?->toString(); + + if (null === $name) { + return false; + } + + return str_starts_with($name, 'Nexus\\'); + } + + public function filterFunctionNode(Node\Stmt\Function_ $node): bool + { + $name = $node->namespacedName?->toString(); + + if (null === $name) { + return false; + } + + return str_starts_with($name, 'Nexus\\'); + } + + public function filterMemberInfo(ClassLikeInfo $classLike, MemberInfo $member): bool + { + $name = $classLike->name->full; + + return str_starts_with($name, 'Nexus\\'); + } +} diff --git a/api/src/RendererFilter.php b/api/src/RendererFilter.php new file mode 100644 index 0000000..1608e46 --- /dev/null +++ b/api/src/RendererFilter.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace Nexus\Api; + +use ApiGen\Index\NamespaceIndex; +use ApiGen\Info\ClassLikeInfo; +use ApiGen\Renderer\Filter; + +final class RendererFilter extends Filter +{ + public function filterNamespacePage(NamespaceIndex $namespace): bool + { + foreach ($namespace->children as $child) { + if ($this->filterNamespacePage($child)) { + return true; + } + } + + foreach ($namespace->class as $class) { + if ($this->filterClassLikePage($class)) { + return true; + } + } + + foreach ($namespace->interface as $interface) { + if ($this->filterClassLikePage($interface)) { + return true; + } + } + + foreach ($namespace->trait as $trait) { + if ($this->filterClassLikePage($trait)) { + return true; + } + } + + foreach ($namespace->enum as $enum) { + if ($this->filterClassLikePage($enum)) { + return true; + } + } + + foreach ($namespace->exception as $exception) { + if ($this->filterClassLikePage($exception)) { + return true; + } + } + + foreach ($namespace->function as $function) { + if ($this->filterFunctionPage($function)) { + return true; + } + } + + return false; + } + + public function filterClassLikePage(ClassLikeInfo $classLike): bool + { + return $this->isClassRendered($classLike); + } + + private function isClassRendered(ClassLikeInfo $classLike): bool + { + $name = $classLike->name->full; + + return str_starts_with($name, 'Nexus\\'); + } +}