Eseguire Gato GraphQL senza WordPress
Gato GraphQL è stato costruito utilizzando componenti PHP autonomi, gestiti tramite Composer, in modo tale che tutti i componenti PHP che costituiscono il server GraphQL non dipendano da WordPress!
Di conseguenza, il server GraphQL può essere eseguito come applicazione PHP autonoma, e puoi includerlo all'interno di qualsiasi applicazione PHP, basata su WordPress o su qualsiasi altra cosa.
Se per qualche caso d'uso la tua applicazione non ha bisogno di accedere ai dati di WordPress, allora, almeno per quel caso d'uso, sei pronto a partire.
Questo video mostra un caso d'uso di questo tipo: interagire con l'API di GitHub, per scaricare/installare artefatti da GitHub Actions durante lo sviluppo:
Nel video, la query GraphQL esegue una richiesta HTTP per recuperare gli ultimi plugin Gato GraphQL generati in GitHub Actions, che vengono caricati come artefatti al momento del merge di una pull request.
Gli URL degli artefatti dalla risposta GraphQL vengono poi iniettati in WP-CLI, in modo che i plugin vengano installati automaticamente su un server web DEV locale, per eseguire i test.
In questo caso d'uso, poiché non viene acceduto alcun dato di WordPress, il server GraphQL può già essere eseguito come app PHP autonoma.
In dettaglio: Eseguire Gato GraphQL come app PHP autonoma
Ecco la spiegazione dettagliata del video dimostrativo.
Forniamo la query GraphQL da eseguire nel file retrieve-github-artifacts.gql.
La query si connette all'API di GitHub recuperando il token di accesso dalla variabile d'ambiente GITHUB_ACCESS_TOKEN. Genera dinamicamente il percorso completo per l'endpoint actions/artifacts a partire dalle variabili fornite, e poi invia una richiesta HTTP verso di esso.
Dalla risposta, estrae quindi la "download URL" da ciascun elemento artefatto, e invia richieste HTTP asincrone verso di esse. Dall'intestazione Location di ciascuno di questi "download URL", otteniamo l'URL effettivo del file scaricabile.
Infine, stampa tutti gli URL insieme separati da uno spazio, per facilitare l'iniezione in WP-CLI.
# File retrieve-github-artifacts.gql
query RetrieveProxyArtifactDownloadURLs(
$repoOwner: String!
$repoProject: String!
$perPage: Int = 1
$artifactName: String = ""
) {
githubAccessToken: _env(name: "GITHUB_ACCESS_TOKEN")
@remove
# Crea l'intestazione di autorizzazione da inviare a GitHub
authorizationHeader: _sprintf(
string: "Bearer %s"
values: [$__githubAccessToken]
)
@remove
# Crea l'intestazione di autorizzazione da inviare a GitHub
githubRequestHeaders: _echo(
value: [
{ name: "Accept", value: "application/vnd.github+json" }
{ name: "Authorization", value: $__authorizationHeader }
]
)
@remove
@export(as: "githubRequestHeaders")
githubAPIEndpoint: _sprintf(
string: "https://api.github.com/repos/%s/%s/actions/artifacts?per_page=%s&name=%s"
values: [$repoOwner, $repoProject, $perPage, $artifactName]
)
# Usa il campo di "Send HTTP Request Fields" per connetterti a GitHub
gitHubArtifactData: _sendJSONObjectItemHTTPRequest(
input: {
url: $__githubAPIEndpoint
options: { headers: $__githubRequestHeaders }
}
)
@remove
# Estrai infine l'URL da ciascun elemento "artifacts"
gitHubProxyArtifactDownloadURLs: _objectProperty(
object: $__gitHubArtifactData
by: { key: "artifacts" }
)
@underEachArrayItem(passValueOnwardsAs: "artifactItem")
@applyField(
name: "_objectProperty"
arguments: { object: $artifactItem, by: { key: "archive_download_url" } }
setResultInResponse: true
)
@export(as: "gitHubProxyArtifactDownloadURLs")
}
query CreateHTTPRequestInputs
@depends(on: "RetrieveProxyArtifactDownloadURLs")
{
httpRequestInputs: _echo(value: $gitHubProxyArtifactDownloadURLs)
@underEachArrayItem(passValueOnwardsAs: "url")
@applyField(
name: "_objectAddEntry"
arguments: {
object: {
options: { headers: $githubRequestHeaders, allowRedirects: null }
}
key: "url"
value: $url
}
setResultInResponse: true
)
@export(as: "httpRequestInputs")
@remove
}
query RetrieveActualArtifactDownloadURLs
@depends(on: "CreateHTTPRequestInputs")
{
_sendHTTPRequests(inputs: $httpRequestInputs) {
artifactDownloadURL: header(name: "Location")
@export(as: "artifactDownloadURLs", type: LIST)
}
}
query PrintSpaceSeparatedArtifactDownloadURLs
@depends(on: "RetrieveActualArtifactDownloadURLs")
{
spaceSeparatedArtifactDownloadURLs: _arrayJoin(
array: $artifactDownloadURLs
separator: " "
)
}La logica PHP carica direttamente il codice dal plugin Gato GraphQL, e dal bundle "Power Extensions" (necessario per inviare richieste HTTP, e altre funzionalità).
Come app PHP autonoma, dobbiamo indicare esplicitamente quali moduli vengono inizializzati, e fornire qualsiasi configurazione non predefinita.
Ad esempio, indichiamo al modulo SendHTTPRequests di consentire la connessione a https://api.github.com/repos, e al modulo EnvironmentFields di consentire l'accesso alla variabile d'ambiente GITHUB_ACCESS_TOKEN.
Nota che lo schema GraphQL viene generato la prima volta che la query GraphQL viene eseguita, e memorizzato nella cache su disco. In questo modo, dalla 2ª volta in poi, nessun codice per calcolare lo schema viene eseguito, rendendo l'esecuzione più veloce.
Infine, l'app autonoma inizializza il server GraphQL, esegue la query contro di esso, e stampa la risposta.
<?php
// File retrieve-github-artifacts.php
declare(strict_types=1);
use GraphQLByPoP\GraphQLServer\Server\StandaloneGraphQLServer;
use PoP\Root\Container\ContainerCacheConfiguration;
// Carica il server GraphQL tramite i componenti PHP autonomi
require_once (__DIR__ . '/wordpress/wp-content/plugins/gatographql/vendor/scoper-autoload.php');
// Carica le estensioni PRO tramite i componenti PHP autonomi
require_once (__DIR__ . '/wordpress/wp-content/plugins/gatographql-power-extensions-bundle/vendor/scoper-autoload.php');
// Moduli richiesti nella query GraphQL
$moduleClasses = [
\PoPSchema\EnvironmentFields\Module::class,
\PoPSchema\FunctionFields\Module::class,
\GraphQLByPoP\ExportDirective\Module::class,
\GraphQLByPoP\DependsOnOperationsDirective\Module::class,
\GraphQLByPoP\RemoveDirective\Module::class,
\PoPSchema\ApplyFieldDirective\Module::class,
\PoPSchema\SendHTTPRequests\Module::class,
\PoPSchema\ConditionalMetaDirectives\Module::class,
\PoPSchema\DataIterationMetaDirectives\Module::class,
];
// Configura i moduli
$moduleClassConfiguration = [
\PoP\GraphQLParser\Module::class => [
\PoP\GraphQLParser\Environment::ENABLE_MULTIPLE_QUERY_EXECUTION => true,
\PoP\GraphQLParser\Environment::USE_LAST_OPERATION_IN_DOCUMENT_FOR_MULTIPLE_QUERY_EXECUTION_WHEN_OPERATION_NAME_NOT_PROVIDED => true,
\PoP\GraphQLParser\Environment::ENABLE_RESOLVED_FIELD_VARIABLE_REFERENCES => true,
\PoP\GraphQLParser\Environment::ENABLE_COMPOSABLE_DIRECTIVES => true,
],
\PoPSchema\SendHTTPRequests\Module::class => [
\PoPSchema\SendHTTPRequests\Environment::SEND_HTTP_REQUEST_URL_ENTRIES => [
'#https://api.github.com/repos/(.*)#',
],
],
\PoPSchema\EnvironmentFields\Module::class => [
\PoPSchema\EnvironmentFields\Environment::ENVIRONMENT_VARIABLE_OR_PHP_CONSTANT_ENTRIES => [
'GITHUB_ACCESS_TOKEN',
],
],
];
// Memorizza lo schema nella cache su disco, per accelerare l'esecuzione a partire dalla 2ª volta
$containerCacheConfiguration = new ContainerCacheConfiguration('MyGraphQLServer', true, 'retrieve-github-artifacts', __DIR__ . '/tmp');
// Inizializza il server
$graphQLServer = new StandaloneGraphQLServer($moduleClasses, $moduleClassConfiguration, [], [], $containerCacheConfiguration);
/**
* Query GraphQL da eseguire, memorizzata nel proprio file .gql
*
* @var string
*/
$query = file_get_contents(__DIR__ . '/retrieve-github-artifacts.gql');
// Variabili GraphQL
$variables = [
'repoOwner' => 'GatoGraphQL',
'repoProject' => 'GatoGraphQL',
'perPage' => 3
];
// Esegui la query
$response = $graphQLServer->execute(
$query,
$variables,
);
// Stampa la risposta
echo $response->getContent();Per eseguire la query GraphQL, lanciamo nel terminale (utilizzando jq per stampare in modo leggibile il JSON):
php retrieve-github-artifacts.php | jqInfine, per estrarre gli URL degli artefatti dalla risposta GraphQL e iniettarli in WP-CLI, eseguiamo:
GITHUB_ARTIFACT_URLS=$(php retrieve-github-artifacts.php \
| grep -E -o '"spaceSeparatedArtifactDownloadURLs\":"(.*)"' \
| cut -d':' -f2- | cut -d'"' -f2- | rev | cut -d'"' -f2- | rev \
| sed 's/\\\//\//g')
wp plugin install ${GITHUB_ARTIFACT_URLS} --force --activate