diff --git a/.github/workflows/publish_mcp_abilities.yml b/.github/workflows/publish_mcp_abilities.yml new file mode 100644 index 000000000..dc5d22072 --- /dev/null +++ b/.github/workflows/publish_mcp_abilities.yml @@ -0,0 +1,86 @@ +name: Publish MCP Abilities to ARD Service + +on: + push: + tags: + - "*" + +jobs: + dump-abilities: + runs-on: ubuntu-latest + + name: Dump Imagify abilities catalog (WP latest, PHP 8.2) + + env: + WP_TESTS_DIR: "/tmp/tests/phpunit" + WP_CORE_DIR: "/tmp/wordpress-develop" + + steps: + - name: Checkout + uses: actions/checkout@v6 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.2' + coverage: none + tools: composer:v2, phpunit + + - name: Install SVN + run: sudo apt-get install subversion + + - name: Start mysql service + run: sudo /etc/init.d/mysql start + + - name: Get composer cache directory + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Strauss + run: sh -c 'test -f ./bin/strauss.phar || curl -o bin/strauss.phar -L -C - https://github.com/BrianHenryIE/strauss/releases/latest/download/strauss.phar' + + - name: Install dependencies + run: composer install --no-interaction + + - name: Install tests + run: bash bin/install-wp-tests.sh wordpress_test root root 127.0.0.1:3306 latest + + - name: Mysql8 auth plugin workaround + run: sudo mysql -u root -proot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';" + + - name: Dump abilities catalog as JSON + env: + ABILITIES_CATALOG_OUTPUT_PATH: ${{ github.workspace }}/imagify-abilities-catalog.json + run: composer run-script test-integration-abilities-catalog + + - name: Upload abilities catalog artifact + uses: actions/upload-artifact@v4 + with: + name: imagify-abilities-catalog + path: imagify-abilities-catalog.json + retention-days: 14 + + - name: Upload abilities catalog to ard-service + # No continue-on-error here: this workflow triggers on a tag push, + # so the tag/release has already happened by the time this step + # runs. A failure here can't block or delay the release — it can + # only fail to be noticed if swallowed. Letting this step fail for + # real surfaces it as a red workflow run (Actions tab, commit + # status, failure-notification emails), which is the whole point: + # this catalog going stale should be visible, even though it's not + # release-blocking. + env: + ARD_SERVICE_API_TOKEN: ${{ secrets.ARD_SERVICE_API_TOKEN }} + run: | + curl --fail -sS -X POST \ + https://ard-service-production.public-default.k8spod4-cph3.ingress.k8s.g1i.one/api/v1/upload/imagify/manifest \ + -H "Content-Type: application/json" \ + -H "x-api-key: ${ARD_SERVICE_API_TOKEN}" \ + --data @imagify-abilities-catalog.json diff --git a/Tests/Integration/classes/Abilities/Catalog/DumpAbilitiesCatalogTest.php b/Tests/Integration/classes/Abilities/Catalog/DumpAbilitiesCatalogTest.php new file mode 100644 index 000000000..881a69b49 --- /dev/null +++ b/Tests/Integration/classes/Abilities/Catalog/DumpAbilitiesCatalogTest.php @@ -0,0 +1,85 @@ +markTestSkipped( 'WordPress 6.9+ required for the Abilities API.' ); + } + + if ( ! function_exists( 'wp_get_abilities' ) ) { + $this->markTestSkipped( 'wp_get_abilities() is not available in this environment.' ); + } + } + + /** + * Reads every registered ability via the public Abilities API and prints + * the ones belonging to Imagify as a JSON manifest. + * + * @return void + */ + public function testShouldDumpRegisteredAbilitiesAsJson(): void { + $abilities = wp_get_abilities(); + + $this->assertNotEmpty( $abilities, 'Expected at least one ability to be registered by wp_get_abilities().' ); + + $manifest = []; + + foreach ( $abilities as $ability ) { + if ( 0 !== strpos( $ability->get_name(), self::VENDOR_PREFIX ) ) { + continue; + } + + $manifest[] = [ + 'name' => $ability->get_name(), + 'label' => $ability->get_label(), + 'description' => $ability->get_description(), + 'category' => $ability->get_category(), + 'input_schema' => $ability->get_input_schema(), + 'output_schema' => $ability->get_output_schema(), + 'meta' => $ability->get_meta(), + ]; + } + + $this->assertNotEmpty( $manifest, 'Expected at least one imagify/* ability to be registered.' ); + + $json = wp_json_encode( $manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); + + fwrite( STDERR, "\n" . self::START_MARKER . "\n" . $json . "\n" . self::END_MARKER . "\n" ); + + // Also write to a file the CI workflow uploads as a downloadable artifact — + // avoids scraping the JSON out of the raw Action log by hand. + $outputPath = getenv( 'ABILITIES_CATALOG_OUTPUT_PATH' ) ?: sys_get_temp_dir() . '/imagify-abilities-catalog.json'; + file_put_contents( $outputPath, $json ); + } +} diff --git a/composer.json b/composer.json index 6c7c89076..1e4eab0bb 100644 --- a/composer.json +++ b/composer.json @@ -115,6 +115,7 @@ "scripts": { "test-unit":"\"vendor/bin/phpunit\" --testsuite unit --colors=always --configuration Tests/Unit/phpunit.xml.dist", "test-integration": "\"vendor/bin/phpunit\" --testsuite integration --colors=always --configuration Tests/Integration/phpunit.xml.dist", + "test-integration-abilities-catalog": "\"vendor/bin/phpunit\" --testsuite integration --colors=always --configuration Tests/Integration/phpunit.xml.dist --group AbilitiesCatalog", "install-codestandards": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run", "phpcs": "vendor/bin/phpcs", "phpcs-changed": "./bin/phpcs-changed.sh",