Ander San Miguel

Desarrollador Web

19/09/2021

Haciendo un addon para Cockpit CMS

Este es mi problema, he usado Cockpit CMS para hacer una web y tengo todo preparado: el proceso de build, el sitio donde ejecutarlo y la manera de hacer el despliegue al hosting; sólo me falta la manera de decirle a Github Actions que haga el despliegue y el cuando decírselo.

Para la segunda parte, Cockpit tiene un montón de eventos a los que me podría enganchar, pero claro, esos eventos se disparan probablemente demasiadas veces, quiero decir, hay un evento para cada vez que se guarda un item pero igual no necesito hacer el despliegue cada vez y prefiero que sea sobre demanda, cuando el cliente esté listo para hacer el despliegue que lo haga.

Tampoco debería ser nada complicado, tal y como lo tengo montado se puede hacer a mando desde Github, pero claro, no es plan de decirle eso a un cliente...

Vale, pues voy a hacer un addon para Cockpit que permita hacer esto.

Después de mirar un poco me he dado cuenta de dos cosas, una buena y una mala: la buena es que no parece demasiado difícil y que Cockpit está hecho de manera que sea fácil añadir algunas cosas (otras igual no tanto), la mala es que no existe documentación oficial al respecto, esto es lo más parecido que he encontrado (no es poco para empezar).

Así que armado con mis mejores artes de copia-pega pues me he puesto a mirar tanto el código fuente del proyecto como el de otros addons, esta primera versión es muy sencilla y tengo alguna idea para mejorarla, pero para salir del paso pues ya tengo algo.

Los pasos para crear un addon son sencillos: crear una carpeta dentro de addons y ahí dentro un archivo bootstrap.php donde registrar las cosas que quieras, en este caso al ser tan sencillo lo que quiero hacer pues lo he dejado todo en ese archivo pero parece ser que hay patrones por ade separar (por ejemplo) lo que es del panel y lo que es del API.

En mi caso, quiero que tenga un enlace en el menú que te lleve a una página de confirmación y si la petición es correcta pues ya está (me podría complicar con el API de Github y consultar el estado de la ejecución, pero no me merece la pena de momento).

Entonces, en el archivo bootstrap.php:

<?php
// Sólo ejecutar cosas si es para el paenl, nada de APIs
if (COCKPIT_ADMIN_CP) {

    // Evento principal al que me engancho
    $app->on('admin.init', function () {

        // Creo un botón en el menú
        $this->helper('admin')->addMenuItem('modules', [
            'label' => 'Deploy site',
            'icon' => 'assets:app/media/icons/paperplane.svg',
            'route' => '/ghwebhook',
            'active' => strpos($this['route'], '/ghwebhook') === 0
        ]);
        
        // Tengo un controlador donde cargo las vistas
        $this->bindClass('Ghwebhook\\Controller\\Main', 'ghwebhook');

    });
}

Y el controlador queda tal que así (Controler/Main.php):

<?php

namespace Ghwebhook\Controller;

// Extiendo el controlador principal
class Main extends \Cockpit\AuthController {

    // Cargo la vista de confirmación
    public function index() {
        return $this->render("ghwebhook:views/index.php");
    }

    // Hago el deploy
    public function deploy() {

        $curl = curl_init();

        // Las opciones principales: url y token se configuran en el 
        // archivo general de configuración
        curl_setopt_array($curl, array(
            CURLOPT_URL => $this->app->config['ghwebhook']['url'],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS =>'{ "event_type" : "Update from Cockpit CMS" }',
            CURLOPT_HTTPHEADER => array(
                'Accept: application/vnd.github.v3+json',
                'Authorization: token ' . $this->app->config['ghwebhook']['token'],
                'User-Agent: CMS Cockpit',
                'Content-Type: application/json'
            ),
        ));

        $response = curl_exec($curl);
        $code = curl_getinfo($curl,  CURLINFO_HTTP_CODE);
        curl_close($curl);

        // Cargo las vistas correspondientes según la petición haya ido bien o no
        if ($code == 204) {
            return $this->render("ghwebhook:views/deploy.php");
        } else {
            return $this->render("ghwebhook:views/no-deploy.php", ['code' => $code]);
        }

    }

}

Las vistas del addon las he robado vilmente de un módulo de Cockpit y le he quitado todo lo que no necesitaba, realmente no tienen nada interesante.

Pero, si una de las cosas que tiene Cockpit es precisamente un configurador para realizar peticiones externas según los eventos...

Así es, y es una de las cosas que me gustaban de Cockpit en un princpio, pero resultan dos cosas: la primera es que igualmente tenía que hacer el addon si no quería engancharme a los eventos que existen y la segunda y más importante es que tal y como está ahora no es posible hacer una petición de la manera que exige Github (hay que mandar en el cuerpo de la petición un campo event_type).

De momento así se queda, para el futuro me gustaría que fuera configurable de alguna manera desde el panel, o mejor aún, ver que cambios habría que hacer para modificar el core de Cockpit y hacer una pull request con esos cambios, nu sé.

Ah, el código, claro, está aquí (ya le pondré un README aunque sea...): https://github.com/andersanmiguel/cockpit-github-webhook/

Desarrollo Web

Esto es a lo que me dedico, así que es lo que más vas a encontrar en esta página.

Contacto

Esta sección está clara, si quieres contactar conmigo, este es un buen sitio.