Los plugins de GameAP se publican en plugins.gameap.dev — desde ahí los usuarios los instalan directamente desde el panel. Esta guía recorre todo el camino: desde la creación de la ficha del plugin hasta la publicación automática de nuevas versiones desde CI.

Se presupone que su plugin ya está escrito y se compila en un .wasm. También necesitará una cuenta en plugins.gameap.dev: un registro normal con confirmación del correo electrónico, o inicio de sesión a través de GitHub, GitLab o Google.

Hay dos formas de subir una versión: manualmente a través del dashboard y a través de la API desde CI. Es más fácil empezar con el dashboard y, cuando la compilación se estabilice, pasar a CI.

Paso 1. Cuenta de desarrollador #

Publicar plugins requiere una cuenta con estado de desarrollador. Se concede gratis e inmediatamente — basta con aceptar las reglas de publicación.

En el catálogo de plugins pulse Publish your plugin — el botón de la esquina superior derecha.

El botón «Publish your plugin» en el catálogo de plugins
El catálogo de plugins

Se abrirá la página con las reglas de publicación. En resumen, lo que usted acepta:

  • Plugins funcionales y de calidad — solo plugins operativos y probados, que hagan lo que promete su descripción.
  • Nada de código malicioso — sin puertas traseras, mineros ocultos ni lógica ofuscada; cualquier recopilación de datos de los usuarios debe describirse explícitamente.
  • Derechos y licencias — usted es propietario del código o está autorizado a distribuirlo, las licencias de terceros se respetan y la licencia del plugin está indicada.
  • Compatibilidad con GameAP — el plugin funciona con las versiones actuales del panel y cumple los requisitos del formato.
  • Actualizaciones y soporte — los errores críticos y las vulnerabilidades se corrigen en plazos razonables, y los reportes de los usuarios reciben respuesta.
  • Moderación — cada plugin y cada versión pasan una revisión, y un plugin que infrinja las reglas puede ser retirado en cualquier momento.
  • Sin spam ni duplicados — sin nombres engañosos ni relleno de palabras clave.

El texto completo está en la propia página, y vale la pena leerlo entero.

Pulse Agree al final de la página. El rol se concede al instante, sin revisión ni espera: en la barra lateral aparecerá la sección Developer con los apartados Dashboard, My Plugins, New Plugin y Support, y llegará un correo informándole de que ya es desarrollador.

Importante. Las reglas solo pueden aceptarse con un correo electrónico verificado: de lo contrario, el botón Agree permanece inactivo y la página muestra un recordatorio para confirmar la dirección. Las cuentas creadas a través de GitHub, GitLab o Google se consideran verificadas de inmediato.

El botón Publish your plugin es visible para todos, incluidos los visitantes que no han iniciado sesión. Sin sesión, la página de reglas muestra Log in to agree — al identificarse volverá a las reglas.

Paso 2. Creación del plugin #

Seleccione New Plugin en el menú de la izquierda — se abrirá el formulario de creación.

El formulario de creación de un plugin en el dashboard de plugins.gameap.dev
Creación de un nuevo plugin
CampoObligatorioQué indicar
NameHasta 255 caracteres
SummaryUna frase para la tarjeta del catálogo, hasta 500 caracteres
DescriptionDescripción completa en Markdown — el campo tiene una barra de formato
CategorynoUna de las tres siguientes
LabelsnoPalabras clave que facilitan encontrar el plugin
LicensenoTexto libre: MIT, GPL-3.0, Proprietary
Source URLnoEnlace a las fuentes, si están abiertas
Repository URLnoEnlace al repositorio
Homepage URLnoEl sitio web del plugin o del autor

Las categorías:

  • Server Management — la mayoría de los plugins. Todo lo que añade acciones sobre un servidor de juegos.
  • Files — extensiones del gestor de archivos: editores, visores de formatos concretos.
  • Integrations — plugins que amplían sustancialmente lo que el panel puede hacer, por ejemplo la gestión de bases de datos.

El icono no se puede subir en este paso — el formulario lo advierte explícitamente; el control de subida aparece justo después de la creación.

Importante. Source URL y Repository URL afectan a algo más que la ficha. Si ninguno de los dos está relleno, cada versión tendrá que incluir un archivo con el código fuente — los moderadores necesitan algo con lo que verificar la compilación. Rellene al menos uno de ellos si sus fuentes son públicas.

Paso 3. El ID del plugin #

Tras pulsar Create llegará a la página de edición del plugin. Su primer bloque es el Plugin ID — un campo de solo lectura con un botón para copiar.

Este ID hay que escribirlo en el código fuente del plugin — en el campo id de la estructura PluginInfo que devuelve el método GetInfo. Así es como el panel asocia un plugin instalado por el usuario con su entrada en el marketplace.

El ID se genera una sola vez al crear el plugin y no puede cambiarse. Internamente es un número de 64 bits (8 bytes aleatorios) escrito en base32 — 13 caracteres latinos y dígitos, por ejemplo fmqnme42gg7da. El mismo ID aparece en la URL de la página del plugin y en la dirección del endpoint de CI.

Cómo se ve en los plugins existentes:

Importante. Escriba el ID y recompile el .wasm antes de subir la primera versión. Las versiones son inmutables: no se puede volver a subir un archivo con el mismo número, habría que incrementar la versión.

Paso 4. Icono y traducciones #

En esa misma página de edición se puede subir un icono: JPG, PNG, WebP o SVG, hasta 2 MB; se recomienda 128×128.

La página del plugin tiene un bloque Translations. El catálogo es bilingüe y cada visitante ve la ficha en su propio idioma: sin traducción, un usuario ruso recibirá la descripción en inglés y viceversa. El nombre, el resumen y la descripción se traducen por separado para cada idioma — cinco minutos de trabajo que cambian notablemente el aspecto de la ficha.

Paso 5. Subida de una versión #

En la página del plugin busque la tarjeta Versions y pulse Upload Version.

El formulario de subida de una versión del plugin
Subida de una nueva versión
CampoObligatorioQué indicar
VersionVersión semántica: 1.0.0, 1.2.0-beta.1
Plugin FileEl .wasm compilado, hasta 100 MB
GPG SignaturenoFirma separada .sig o .asc, hasta 1 MB
Source Code Archivedepende.zip o .tar.gz, hasta 50 MB
ChangelognoQué cambió respecto a la versión anterior, en Markdown
Stable ReleaseUn interruptor, activado por defecto
Min GameAP VersionnoLa versión del panel a partir de la cual funciona el plugin

La firma GPG es opcional pero bienvenida: el servidor la almacena tal cual y nunca la verifica — existe para que los usuarios puedan comprobar por sí mismos la autenticidad del archivo.

El archivo de código fuente es obligatorio cuando el plugin no tiene rellenos ni Source URL ni Repository URL — el formulario cambia por sí solo la etiqueta del campo de «(Optional)» a «(Required)». El archivo se usa solo para la moderación y la verificación de la compilación; nunca se publica ni es accesible a través de ningún endpoint público.

Importante. Una versión subida a través del dashboard permanece como borrador. Hasta que no la envíe a revisión, nadie la ve.

Capturas de pantalla de la versión #

Justo después de la subida se abre un segundo paso — Add Screenshots. Las capturas pertenecen a una versión concreta: JPG, PNG o WebP, hasta 10, de 5 MB cada una. El paso se puede omitir y retomar más tarde desde la página de la versión.

Paso 6. Envío a revisión #

Los plugins pasan por moderación — conforme a las mismas reglas de publicación que aceptó en el paso 1. La cabecera de la página del plugin tiene un botón Submit for Review — solo es visible mientras el plugin está en estado Draft o Rejected.

Un plugin sin ninguna versión no puede enviarse — suba primero una versión. Enviar una versión a revisión desde la tabla de versiones también mueve el propio plugin de Draft a Pending Review, así que normalmente no hace falta pulsar el botón de la cabecera por separado.

EstadoQué significaQué se puede hacer
DraftCreado, no enviado a ninguna parteEditar, enviar a revisión, eliminar
Pending ReviewEsperando a un moderadorEsperar
RejectedUn moderador lo devolvióCorregirlo y enviarlo de nuevo
ReleasedDisponible para todos en el catálogoSubir nuevas versiones
ApprovedUn estado intermedio en el modelo de datos
DeprecatedMarcado como obsoletoAún instalable, pero señalizado
RetractedRetirado de la publicaciónNo disponible para instalar

La aprobación mueve el plugin y la versión directamente a Released. Solo los objetos en ese estado son visibles públicamente: si un plugin está publicado pero su única versión sigue pendiente de revisión, no hay nada que instalar.

El motivo del rechazo llega por correo electrónico — la página del plugin solo muestra el estado, así que revise su bandeja de entrada.

Tokens de despliegue #

Para publicar versiones desde CI se necesita un token de despliegue. Está al final de la página del plugin, en la tarjeta Deploy Tokens.

La tarjeta «Deploy Tokens» al final de la página del plugin
La tarjeta de tokens de despliegue

Pulse Create Token y rellene el diálogo: un nombre (GitHub Actions, por ejemplo) y, opcionalmente, una fecha de caducidad.

El diálogo de creación del token de despliegue con los campos “Name” y “Expires At”
Creación de un token de despliegue

Importante. El token se muestra exactamente una vez, justo después de su creación. En el servidor solo se guarda su hash y el valor no se puede recuperar — cópielo directamente en los secretos de su CI.

Lo que conviene saber sobre los tokens:

  • Un token está vinculado a un solo plugin y solo puede subir versiones de ese plugin. No abre ni otros plugins ni el resto de la API.
  • El formato es gapd_ más 43 caracteres, 48 en total. El prefijo lo detectan fácilmente los escáneres de secretos.
  • La tabla muestra el prefijo del token, la fecha de creación, el último uso y la caducidad — práctico para averiguar qué token sigue en uso.
  • La revocación es inmediata: un pipeline con un token revocado fallará en su próxima ejecución.
  • Un mismo plugin puede tener hasta 20 tokens.

Publicación desde CI #

El endpoint de CI acepta una nueva versión sin inicio de sesión interactivo — se autentica con un token de despliegue.

Subida con curl #

curl --fail-with-body -sS \
  -H "Authorization: Bearer $GAMEAP_DEPLOY_TOKEN" \
  -F "version=1.2.3" \
  -F "file=@build/plugin.wasm" \
  -F "signature=@build/plugin.wasm.asc" \
  -F "changelog=Corregido un fallo al reiniciar el servidor" \
  -F "min_gameap_version=4.1.0" \
  -F "is_stable=true" \
  "https://plugins.gameap.dev/api/ci/plugins/$GAMEAP_PLUGIN_ID/versions"

La petición es un POST con multipart/form-data. Los campos del formulario:

CampoObligatorioDescripción
versionVersión semántica, p. ej. 1.2.3
fileEl .wasm compilado, hasta 100 MB
signaturenoFirma GPG separada, hasta 1 MB
sourcedependeArchivo de fuentes .zip/.tar.gz hasta 50 MB; obligatorio cuando el plugin no tiene ni Source URL ni Repository URL
changelognoNotas de la versión; cómodo pasarlas desde un archivo: -F "changelog=<CHANGELOG.md"
min_gameap_versionnoVersión mínima de GameAP
min_plugin_api_versionnoVersión mínima del Plugin API (el formulario del dashboard no tiene este campo)
is_stablenotrue o 1 marca la versión como estable
submitnoPor defecto true; false mantiene la versión como borrador

No ponga una barra final en la URL. El router responde a .../versions/ con un 301, y curl no reenvía el cuerpo del POST en una redirección — la subida se convertiría silenciosamente en un GET.

Una respuesta exitosa es un 201 con un cuerpo como:

{
  "id": 123,
  "plugin_id": "fmqnme42gg7da",
  "version": "1.2.3",
  "file_size": 1048576,
  "file_hash": "9f86d081884c7d65...",
  "has_source": false,
  "status": "pending_review"
}

GitHub Actions #

Este workflow se dispara cuando se publica un release de GitHub, compila el plugin, lo firma y lo envía a plugins.gameap.dev. El cuerpo del release se convierte en el changelog, y la versión se marca como estable solo cuando el release no es un pre-release.

name: Publish plugin

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build plugin
        run: make wasm            # debe producir build/plugin.wasm

      - name: Sign plugin
        env:
          GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
        run: |
          printf '%s' "$GPG_SIGNING_KEY" | gpg --batch --import
          gpg --batch --yes --detach-sign --armor \
            -o build/plugin.wasm.asc build/plugin.wasm

      - name: Publish to plugins.gameap.dev
        env:
          GAMEAP_DEPLOY_TOKEN: ${{ secrets.GAMEAP_DEPLOY_TOKEN }}
          GAMEAP_PLUGIN_ID: ${{ vars.GAMEAP_PLUGIN_ID }}
          TAG: ${{ github.event.release.tag_name }}
          RELEASE_BODY: ${{ github.event.release.body }}
          PRERELEASE: ${{ github.event.release.prerelease }}
        run: |
          VERSION="${TAG#v}"
          printf '%s' "$RELEASE_BODY" > "$RUNNER_TEMP/changelog.md"
          ARGS=(--fail-with-body -sS
            -H "Authorization: Bearer ${GAMEAP_DEPLOY_TOKEN}"
            -F "version=${VERSION}"
            -F "file=@build/plugin.wasm"
            -F "signature=@build/plugin.wasm.asc"
            -F "changelog=<${RUNNER_TEMP}/changelog.md")
          if [ "$PRERELEASE" != "true" ]; then
            ARGS+=(-F "is_stable=true")
          fi
          curl "${ARGS[@]}" \
            "https://plugins.gameap.dev/api/ci/plugins/${GAMEAP_PLUGIN_ID}/versions"

VERSION="${TAG#v}" elimina la v inicial para que el tag v1.2.3 se publique como versión 1.2.3.

La versión de producción de este workflow, con compilación del frontend, caché de Cargo y comprobación del estado HTTP, está en plugin-mysql.

Configuración del repositorio de GitHub #

El token y el ID del plugin no deben estar en el código — pertenecen a la configuración del repositorio. Abra Settings → Secrets and variables (en la sección Security and quality) → Actions.

El elemento «Secrets and variables → Actions» en el menú lateral de la configuración del repositorio de GitHub
La sección de configuración del repositorio

En la pestaña Secrets pulse New repository secret y añada:

NombreValor
GAMEAP_DEPLOY_TOKENEl token de despliegue que copió al crearlo (empieza por gapd_)
GPG_SIGNING_KEYUna clave privada GPG en formato ASCII-armor, si firma sus compilaciones
La pestaña Secrets con los secretos GAMEAP_DEPLOY_TOKEN y GPG_SIGNING_KEY
Secretos del repositorio

En la pestaña Variables pulse New repository variable y añada:

NombreValor
GAMEAP_PLUGIN_IDEl ID del plugin, p. ej. fmqnme42gg7da
La pestaña Variables con la variable GAMEAP_PLUGIN_ID
Variables del repositorio

El ID del plugin es el mismo identificador base32 que escribió en PluginInfo. Cópielo con el botón junto al campo Plugin ID en la página de edición, o desde el bloque Details en la página del plugin.

El ID va en variables y no en secretos a propósito: no es un secreto, y tenerlo visible en los logs de CI facilita mucho el diagnóstico de fallos. El token, en cambio, siempre es un secreto.

Así se exporta una clave privada GPG para GPG_SIGNING_KEY:

gpg --armor --export-secret-keys SU_ID_DE_CLAVE

Publique la clave pública donde los usuarios puedan encontrarla — en el README del plugin, por ejemplo — para que la firma sea verificable.

Dashboard y CI: valores por defecto distintos #

QuéDashboardCI
Stable releaseEl interruptor está activado por defectois_stable por defecto es false — pásalo explícitamente
Envío a revisiónManual, pulsando un botónsubmit por defecto es true — la versión va a revisión de inmediato
Capturas de pantallaSe ofrecen justo después de la subidaNo soportadas, añádalas a través del dashboard

Si lo único que quiere de CI es subir el archivo y terminar los metadatos a mano, pase submit=false y la versión permanecerá como borrador.

Errores #

CódigoCausa
400ID de plugin inválido, un multipart mal formado o no se pasó file
401El token falta, es inválido o ha caducado; la cabecera no tiene la forma Bearer gapd_...
403El token es válido pero fue emitido para otro plugin
409Ya existe una versión con ese número
422La versión no pasa la comprobación de semver; el archivo de fuentes falta, es demasiado grande o no es .zip/.tar.gz; se superan los límites de tamaño del archivo o de la firma

Los cuerpos de error tienen una forma común:

{
  "status": "error",
  "error": "version already exists",
  "message": "version already exists",
  "http_code": 409
}

Tras un error 5xx, no reintente la subida a ciegas. Escribir la versión y enviarla a revisión no son una única transacción: la versión puede que ya exista, y un reintento devuelve 409. Abra el dashboard y compruebe qué pasó realmente.

Actualización y retirada de versiones #

Una nueva versión se sube exactamente igual que la primera — a través del dashboard o desde CI. Las versiones ya subidas son inmutables: volver a subir un archivo con el mismo número no es posible, el intento devuelve 409. Si la compilación salió mal, incremente la versión de parche.

Cada fila de la tabla de versiones tiene sus propias acciones:

  • Edit — cambiar el changelog y los metadatos.
  • Submit for Review — para borradores y versiones rechazadas.
  • Deprecate — para versiones publicadas. La versión sigue disponible pero se marca como obsoleta.
  • Retract — para versiones publicadas y obsoletas. La versión se retira de la publicación.

Solo se puede eliminar un plugin en estado Draft. Un plugin publicado no se puede eliminar — se puede retractar.

Lista de comprobación #

  • El correo está verificado, las reglas de publicación aceptadas y la cuenta tiene estado de desarrollador.
  • El plugin está creado, y el nombre y ambas descripciones están rellenos.
  • Source URL o Repository URL están rellenos — de lo contrario, cada versión necesita un archivo de fuentes.
  • El ID del plugin está escrito en PluginInfo.id y el .wasm se recompiló después.
  • El icono está subido y las traducciones de la ficha están en su sitio.
  • La versión está subida, con firma y capturas de pantalla adjuntas.
  • La versión está enviada a revisión, no dejada como borrador.
  • Para CI: un token de despliegue creado y guardado en los secretos, el ID del plugin en las variables.
  • El workflow no tiene barra final en la URL y pasa is_stable explícitamente.
  • Tras el release, se confirma que el plugin y la versión están en estado Released.