<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Guías — Blog de GameAP</title><link>https://blog.gameap.com/es/guides/</link><description>Últimas publicaciones del blog de GameAP</description><language>es-ES</language><generator>Hugo 0.164.0</generator><atom:link href="https://blog.gameap.com/es/guides/index.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sat, 08 Aug 2026 13:00:00 +0300</lastBuildDate><item><title>¿Cómo publicar su plugin?</title><link>https://blog.gameap.com/es/guides/publishing-plugins/</link><pubDate>Sat, 08 Aug 2026 13:00:00 +0300</pubDate><guid>https://blog.gameap.com/es/guides/publishing-plugins/</guid><description>Publicación de sus plugins de GameAP en plugins.gameap.dev: creación del plugin, subida de versiones desde el dashboard y desde CI, moderación.</description><content:encoded>&lt;p&gt;Los plugins de GameAP se publican en &lt;a href="https://plugins.gameap.dev" target="_blank" rel="noopener"&gt;plugins.gameap.dev&lt;/a&gt; — 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.&lt;/p&gt;
&lt;p&gt;Se presupone que su plugin ya está escrito y se compila en un &lt;code&gt;.wasm&lt;/code&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2 id="paso-1-cuenta-de-desarrollador"&gt;Paso 1. Cuenta de desarrollador &lt;a class="hanchor" href="#paso-1-cuenta-de-desarrollador" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Publicar plugins requiere una cuenta con estado de desarrollador. Se concede gratis e
inmediatamente — basta con aceptar las reglas de publicación.&lt;/p&gt;
&lt;p&gt;En el catálogo de plugins pulse &lt;strong&gt;Publish your plugin&lt;/strong&gt; — el botón de la esquina superior derecha.&lt;/p&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_5159adbc8240679d.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_e87690acd34e62fd.webp 800w, https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_d5e0ccee4c05e9e0.webp 1200w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_948bf2e9ae7b63c.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_2603f5b6f5388b0d.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_1ef640ba0eb0d06.png 800w, https://blog.gameap.com/es/guides/publishing-plugins/publish-plugins.es_hu_948bf2e9ae7b63c.png 1200w" sizes="(min-width: 860px) 808px, 100vw" width="1200" height="756" alt="El botón «Publish your plugin» en el catálogo de plugins" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;El catálogo de plugins&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Se abrirá la página con las reglas de publicación. En resumen, lo que usted acepta:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Plugins funcionales y de calidad&lt;/strong&gt; — solo plugins operativos y probados, que hagan lo que
promete su descripción.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Nada de código malicioso&lt;/strong&gt; — sin puertas traseras, mineros ocultos ni lógica ofuscada;
cualquier recopilación de datos de los usuarios debe describirse explícitamente.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Derechos y licencias&lt;/strong&gt; — usted es propietario del código o está autorizado a distribuirlo,
las licencias de terceros se respetan y la licencia del plugin está indicada.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Compatibilidad con GameAP&lt;/strong&gt; — el plugin funciona con las versiones actuales del panel y cumple
los requisitos del formato.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actualizaciones y soporte&lt;/strong&gt; — los errores críticos y las vulnerabilidades se corrigen en plazos
razonables, y los reportes de los usuarios reciben respuesta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Moderación&lt;/strong&gt; — cada plugin y cada versión pasan una revisión, y un plugin que infrinja las
reglas puede ser retirado en cualquier momento.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sin spam ni duplicados&lt;/strong&gt; — sin nombres engañosos ni relleno de palabras clave.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;El texto completo está en la propia página, y vale la pena leerlo entero.&lt;/p&gt;
&lt;!-- captura de pantalla: la página de reglas de publicación con el botón "Agree" → publish-rules.ru.png / publish-rules.en.png --&gt;
&lt;p&gt;Pulse &lt;strong&gt;Agree&lt;/strong&gt; 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 &lt;strong&gt;Developer&lt;/strong&gt; con los apartados Dashboard, My Plugins, New
Plugin y Support, y llegará un correo informándole de que ya es desarrollador.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante.&lt;/strong&gt; Las reglas solo pueden aceptarse con un correo electrónico verificado: de lo
contrario, el botón &lt;strong&gt;Agree&lt;/strong&gt; 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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;El botón &lt;strong&gt;Publish your plugin&lt;/strong&gt; es visible para todos, incluidos los visitantes que no han iniciado
sesión. Sin sesión, la página de reglas muestra &lt;strong&gt;Log in to agree&lt;/strong&gt; — al identificarse volverá a
las reglas.&lt;/p&gt;
&lt;h2 id="paso-2-creación-del-plugin"&gt;Paso 2. Creación del plugin &lt;a class="hanchor" href="#paso-2-creaci%c3%b3n-del-plugin" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Seleccione &lt;strong&gt;New Plugin&lt;/strong&gt; en el menú de la izquierda — se abrirá el formulario de creación.&lt;/p&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_66c90ae02a704edc.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_ed73830ca4a7af69.webp 800w, https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_5b9135d573b083bb.webp 1200w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_ed7a4092b897f55.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_df39b9d938ca9d05.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_2ce3df4183fea9ad.png 800w, https://blog.gameap.com/es/guides/publishing-plugins/new-plugin.es_hu_ed7a4092b897f55.png 1200w" sizes="(min-width: 860px) 808px, 100vw" width="1200" height="662" alt="El formulario de creación de un plugin en el dashboard de plugins.gameap.dev" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;Creación de un nuevo plugin&lt;/figcaption&gt;&lt;/figure&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Campo&lt;/th&gt;
					&lt;th&gt;Obligatorio&lt;/th&gt;
					&lt;th&gt;Qué indicar&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Name&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;Hasta 255 caracteres&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Summary&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;Una frase para la tarjeta del catálogo, hasta 500 caracteres&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Description&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;Descripción completa en Markdown — el campo tiene una barra de formato&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Category&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Una de las tres siguientes&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Labels&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Palabras clave que facilitan encontrar el plugin&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;License&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Texto libre: &lt;code&gt;MIT&lt;/code&gt;, &lt;code&gt;GPL-3.0&lt;/code&gt;, &lt;code&gt;Proprietary&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Source URL&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Enlace a las fuentes, si están abiertas&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Repository URL&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Enlace al repositorio&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Homepage URL&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;El sitio web del plugin o del autor&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Las categorías:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Server Management&lt;/strong&gt; — la mayoría de los plugins. Todo lo que añade acciones sobre un servidor
de juegos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Files&lt;/strong&gt; — extensiones del gestor de archivos: editores, visores de formatos concretos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrations&lt;/strong&gt; — plugins que amplían sustancialmente lo que el panel puede hacer, por ejemplo
la gestión de bases de datos.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante.&lt;/strong&gt; Source URL y Repository URL afectan a algo más que la ficha. Si ninguno de los
dos está relleno, &lt;strong&gt;cada&lt;/strong&gt; 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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="paso-3-el-id-del-plugin"&gt;Paso 3. El ID del plugin &lt;a class="hanchor" href="#paso-3-el-id-del-plugin" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tras pulsar &lt;strong&gt;Create&lt;/strong&gt; llegará a la página de edición del plugin. Su primer bloque es el
&lt;strong&gt;Plugin ID&lt;/strong&gt; — un campo de solo lectura con un botón para copiar.&lt;/p&gt;
&lt;!-- captura de pantalla: parte superior de la página de edición con el campo "Plugin ID" y su botón de copiar → plugin-id.ru.png / plugin-id.en.png --&gt;
&lt;p&gt;Este ID hay que escribirlo en el código fuente del plugin — en el campo &lt;code&gt;id&lt;/code&gt; de la estructura
&lt;code&gt;PluginInfo&lt;/code&gt; que devuelve el método &lt;code&gt;GetInfo&lt;/code&gt;. Así es como el panel asocia un plugin instalado por
el usuario con su entrada en el marketplace.&lt;/p&gt;
&lt;p&gt;El ID se genera una sola vez al crear el plugin y &lt;strong&gt;no puede cambiarse&lt;/strong&gt;. Internamente es un número
de 64 bits (8 bytes aleatorios) escrito en base32 — 13 caracteres latinos y dígitos, por ejemplo
&lt;code&gt;fmqnme42gg7da&lt;/code&gt;. El mismo ID aparece en la URL de la página del plugin y en la dirección del
endpoint de CI.&lt;/p&gt;
&lt;p&gt;Cómo se ve en los plugins existentes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/gameap/plugin-mysql/blob/main/src/lib.rs" target="_blank" rel="noopener"&gt;plugin-mysql&lt;/a&gt; — la constante &lt;code&gt;PLUGIN_ID&lt;/code&gt; (&lt;code&gt;fmqnme42gg7da&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gameap/plugin-goldsrc-addons/blob/main/src/lib.rs" target="_blank" rel="noopener"&gt;plugin-goldsrc-addons&lt;/a&gt; — &lt;code&gt;PLUGIN_ID&lt;/code&gt; (&lt;code&gt;ezvdsxmlu6fbk&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gameap/plugin-minecraft-modrinth/blob/main/assembly/constants.ts" target="_blank" rel="noopener"&gt;plugin-minecraft-modrinth&lt;/a&gt; — &lt;code&gt;PLUGIN_ID&lt;/code&gt; (&lt;code&gt;dshdabjp2l73a&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante.&lt;/strong&gt; Escriba el ID y recompile el &lt;code&gt;.wasm&lt;/code&gt; 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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="paso-4-icono-y-traducciones"&gt;Paso 4. Icono y traducciones &lt;a class="hanchor" href="#paso-4-icono-y-traducciones" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;!-- captura de pantalla: el control de subida del icono en la página de edición → icon-upload.ru.png / icon-upload.en.png --&gt;
&lt;p&gt;La página del plugin tiene un bloque &lt;strong&gt;Translations&lt;/strong&gt;. 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.&lt;/p&gt;
&lt;!-- captura de pantalla: el bloque "Translations" en la página del plugin → translations.ru.png / translations.en.png --&gt;
&lt;h2 id="paso-5-subida-de-una-versión"&gt;Paso 5. Subida de una versión &lt;a class="hanchor" href="#paso-5-subida-de-una-versi%c3%b3n" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;En la página del plugin busque la tarjeta &lt;strong&gt;Versions&lt;/strong&gt; y pulse &lt;strong&gt;Upload Version&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_243bccfe940fb645.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_aa693942bf347d41.webp 800w, https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_1f9f52625438df09.webp 1200w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_a143f910d4449488.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_fb2b83c72ead6ea2.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_9724bcb241379e5.png 800w, https://blog.gameap.com/es/guides/publishing-plugins/upload-version.es_hu_a143f910d4449488.png 1200w" sizes="(min-width: 860px) 808px, 100vw" width="1200" height="611" alt="El formulario de subida de una versión del plugin" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;Subida de una nueva versión&lt;/figcaption&gt;&lt;/figure&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Campo&lt;/th&gt;
					&lt;th&gt;Obligatorio&lt;/th&gt;
					&lt;th&gt;Qué indicar&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Version&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;Versión semántica: &lt;code&gt;1.0.0&lt;/code&gt;, &lt;code&gt;1.2.0-beta.1&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Plugin File&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;El &lt;code&gt;.wasm&lt;/code&gt; compilado, hasta 100 MB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;GPG Signature&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Firma separada &lt;code&gt;.sig&lt;/code&gt; o &lt;code&gt;.asc&lt;/code&gt;, hasta 1 MB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Source Code Archive&lt;/td&gt;
					&lt;td&gt;depende&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;.zip&lt;/code&gt; o &lt;code&gt;.tar.gz&lt;/code&gt;, hasta 50 MB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Changelog&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Qué cambió respecto a la versión anterior, en Markdown&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Stable Release&lt;/td&gt;
					&lt;td&gt;—&lt;/td&gt;
					&lt;td&gt;Un interruptor, &lt;strong&gt;activado por defecto&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Min GameAP Version&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;La versión del panel a partir de la cual funciona el plugin&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La &lt;strong&gt;firma GPG&lt;/strong&gt; 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.&lt;/p&gt;
&lt;p&gt;El &lt;strong&gt;archivo de código fuente&lt;/strong&gt; 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.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante.&lt;/strong&gt; Una versión subida a través del dashboard permanece como &lt;strong&gt;borrador&lt;/strong&gt;. Hasta que
no la envíe a revisión, nadie la ve.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="capturas-de-pantalla-de-la-versión"&gt;Capturas de pantalla de la versión &lt;a class="hanchor" href="#capturas-de-pantalla-de-la-versi%c3%b3n" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Justo después de la subida se abre un segundo paso — &lt;strong&gt;Add Screenshots&lt;/strong&gt;. 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.&lt;/p&gt;
&lt;h2 id="paso-6-envío-a-revisión"&gt;Paso 6. Envío a revisión &lt;a class="hanchor" href="#paso-6-env%c3%ado-a-revisi%c3%b3n" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;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 &lt;strong&gt;Submit for Review&lt;/strong&gt; — solo es visible
mientras el plugin está en estado Draft o Rejected.&lt;/p&gt;
&lt;!-- captura de pantalla: cabecera de la página del plugin con el botón "Submit for Review" y la tabla de versiones con insignias de estado → submit-review.ru.png / submit-review.en.png --&gt;
&lt;p&gt;Un plugin sin ninguna versión no puede enviarse — suba primero una versión. Enviar una &lt;em&gt;versión&lt;/em&gt; 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.&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Estado&lt;/th&gt;
					&lt;th&gt;Qué significa&lt;/th&gt;
					&lt;th&gt;Qué se puede hacer&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Draft&lt;/td&gt;
					&lt;td&gt;Creado, no enviado a ninguna parte&lt;/td&gt;
					&lt;td&gt;Editar, enviar a revisión, eliminar&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Pending Review&lt;/td&gt;
					&lt;td&gt;Esperando a un moderador&lt;/td&gt;
					&lt;td&gt;Esperar&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Rejected&lt;/td&gt;
					&lt;td&gt;Un moderador lo devolvió&lt;/td&gt;
					&lt;td&gt;Corregirlo y enviarlo de nuevo&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Released&lt;/td&gt;
					&lt;td&gt;Disponible para todos en el catálogo&lt;/td&gt;
					&lt;td&gt;Subir nuevas versiones&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Approved&lt;/td&gt;
					&lt;td&gt;Un estado intermedio en el modelo de datos&lt;/td&gt;
					&lt;td&gt;—&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Deprecated&lt;/td&gt;
					&lt;td&gt;Marcado como obsoleto&lt;/td&gt;
					&lt;td&gt;Aún instalable, pero señalizado&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Retracted&lt;/td&gt;
					&lt;td&gt;Retirado de la publicación&lt;/td&gt;
					&lt;td&gt;No disponible para instalar&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;La aprobación mueve el plugin y la versión directamente a &lt;strong&gt;Released&lt;/strong&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h2 id="tokens-de-despliegue"&gt;Tokens de despliegue &lt;a class="hanchor" href="#tokens-de-despliegue" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Para publicar versiones desde CI se necesita un token de despliegue. Está al final de la página del
plugin, en la tarjeta &lt;strong&gt;Deploy Tokens&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_197cb25595fb5b5f.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_a9f5978f4b4c86b9.webp 800w, https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_1699d5db1124bb17.webp 1200w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_4faa04302751dca0.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_dbe4db4c7c810656.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_beffba6e035fdfb3.png 800w, https://blog.gameap.com/es/guides/publishing-plugins/token-deploy.es_hu_4faa04302751dca0.png 1200w" sizes="(min-width: 860px) 808px, 100vw" width="1200" height="611" alt="La tarjeta «Deploy Tokens» al final de la página del plugin" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;La tarjeta de tokens de despliegue&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;Pulse &lt;strong&gt;Create Token&lt;/strong&gt; y rellene el diálogo: un nombre (&lt;code&gt;GitHub Actions&lt;/code&gt;, por ejemplo) y,
opcionalmente, una fecha de caducidad.&lt;/p&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy-create-form.es.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy-create-form.es_hu_9247ea9ef3fc28dc.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/token-deploy-create-form.es_hu_bc8c408f37c39612.webp 800w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy-create-form.es_hu_c4886a088e2fce6d.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/token-deploy-create-form.es_hu_e53a113cd49f24d.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/token-deploy-create-form.es_hu_c4886a088e2fce6d.png 800w" sizes="(min-width: 860px) 808px, 100vw" width="800" height="514" alt="El diálogo de creación del token de despliegue con los campos “Name” y “Expires At”" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;Creación de un token de despliegue&lt;/figcaption&gt;&lt;/figure&gt;&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Importante.&lt;/strong&gt; 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.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lo que conviene saber sobre los tokens:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;El formato es &lt;code&gt;gapd_&lt;/code&gt; más 43 caracteres, 48 en total. El prefijo lo detectan fácilmente los
escáneres de secretos.&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;La revocación es inmediata: un pipeline con un token revocado fallará en su próxima ejecución.&lt;/li&gt;
&lt;li&gt;Un mismo plugin puede tener hasta 20 tokens.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="publicación-desde-ci"&gt;Publicación desde CI &lt;a class="hanchor" href="#publicaci%c3%b3n-desde-ci" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;El endpoint de CI acepta una nueva versión sin inicio de sesión interactivo — se autentica con un
token de despliegue.&lt;/p&gt;
&lt;h3 id="subida-con-curl"&gt;Subida con curl &lt;a class="hanchor" href="#subida-con-curl" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl --fail-with-body -sS &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -H &lt;span class="s2"&gt;&amp;#34;Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$GAMEAP_DEPLOY_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -F &lt;span class="s2"&gt;&amp;#34;version=1.2.3&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -F &lt;span class="s2"&gt;&amp;#34;file=@build/plugin.wasm&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -F &lt;span class="s2"&gt;&amp;#34;signature=@build/plugin.wasm.asc&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -F &lt;span class="s2"&gt;&amp;#34;changelog=Corregido un fallo al reiniciar el servidor&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -F &lt;span class="s2"&gt;&amp;#34;min_gameap_version=4.1.0&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -F &lt;span class="s2"&gt;&amp;#34;is_stable=true&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;https://plugins.gameap.dev/api/ci/plugins/&lt;/span&gt;&lt;span class="nv"&gt;$GAMEAP_PLUGIN_ID&lt;/span&gt;&lt;span class="s2"&gt;/versions&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;La petición es un &lt;code&gt;POST&lt;/code&gt; con &lt;code&gt;multipart/form-data&lt;/code&gt;. Los campos del formulario:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Campo&lt;/th&gt;
					&lt;th&gt;Obligatorio&lt;/th&gt;
					&lt;th&gt;Descripción&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;version&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;Versión semántica, p. ej. &lt;code&gt;1.2.3&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;file&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;sí&lt;/td&gt;
					&lt;td&gt;El &lt;code&gt;.wasm&lt;/code&gt; compilado, hasta 100 MB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;signature&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Firma GPG separada, hasta 1 MB&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;source&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;depende&lt;/td&gt;
					&lt;td&gt;Archivo de fuentes &lt;code&gt;.zip&lt;/code&gt;/&lt;code&gt;.tar.gz&lt;/code&gt; hasta 50 MB; obligatorio cuando el plugin no tiene ni Source URL ni Repository URL&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;changelog&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Notas de la versión; cómodo pasarlas desde un archivo: &lt;code&gt;-F &amp;quot;changelog=&amp;lt;CHANGELOG.md&amp;quot;&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;min_gameap_version&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Versión mínima de GameAP&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;min_plugin_api_version&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Versión mínima del Plugin API (el formulario del dashboard no tiene este campo)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;is_stable&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;true&lt;/code&gt; o &lt;code&gt;1&lt;/code&gt; marca la versión como estable&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;submit&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;no&lt;/td&gt;
					&lt;td&gt;Por defecto &lt;code&gt;true&lt;/code&gt;; &lt;code&gt;false&lt;/code&gt; mantiene la versión como borrador&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;No ponga una barra final en la URL.&lt;/strong&gt; El router responde a &lt;code&gt;.../versions/&lt;/code&gt; con un &lt;code&gt;301&lt;/code&gt;, y curl
no reenvía el cuerpo del &lt;code&gt;POST&lt;/code&gt; en una redirección — la subida se convertiría silenciosamente en un
&lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Una respuesta exitosa es un &lt;code&gt;201&lt;/code&gt; con un cuerpo como:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;plugin_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;fmqnme42gg7da&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1.2.3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;file_size&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1048576&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;file_hash&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;9f86d081884c7d65...&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;has_source&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;pending_review&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id="github-actions"&gt;GitHub Actions &lt;a class="hanchor" href="#github-actions" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Publish plugin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;release&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;types&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="l"&gt;published]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;runs-on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;uses&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;actions/checkout@v4&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Build plugin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;make wasm &lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# debe producir build/plugin.wasm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Sign plugin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;GPG_SIGNING_KEY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.GPG_SIGNING_KEY }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; printf &amp;#39;%s&amp;#39; &amp;#34;$GPG_SIGNING_KEY&amp;#34; | gpg --batch --import
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; gpg --batch --yes --detach-sign --armor \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -o build/plugin.wasm.asc build/plugin.wasm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;Publish to plugins.gameap.dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;GAMEAP_DEPLOY_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ secrets.GAMEAP_DEPLOY_TOKEN }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;GAMEAP_PLUGIN_ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ vars.GAMEAP_PLUGIN_ID }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;TAG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ github.event.release.tag_name }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;RELEASE_BODY&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ github.event.release.body }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;PRERELEASE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;${{ github.event.release.prerelease }}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="sd"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; VERSION=&amp;#34;${TAG#v}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; printf &amp;#39;%s&amp;#39; &amp;#34;$RELEASE_BODY&amp;#34; &amp;gt; &amp;#34;$RUNNER_TEMP/changelog.md&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; ARGS=(--fail-with-body -sS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -H &amp;#34;Authorization: Bearer ${GAMEAP_DEPLOY_TOKEN}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -F &amp;#34;version=${VERSION}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -F &amp;#34;file=@build/plugin.wasm&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -F &amp;#34;signature=@build/plugin.wasm.asc&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; -F &amp;#34;changelog=&amp;lt;${RUNNER_TEMP}/changelog.md&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; if [ &amp;#34;$PRERELEASE&amp;#34; != &amp;#34;true&amp;#34; ]; then
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; ARGS+=(-F &amp;#34;is_stable=true&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; fi
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; curl &amp;#34;${ARGS[@]}&amp;#34; \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="sd"&gt; &amp;#34;https://plugins.gameap.dev/api/ci/plugins/${GAMEAP_PLUGIN_ID}/versions&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;VERSION=&amp;quot;${TAG#v}&amp;quot;&lt;/code&gt; elimina la &lt;code&gt;v&lt;/code&gt; inicial para que el tag &lt;code&gt;v1.2.3&lt;/code&gt; se publique como versión
&lt;code&gt;1.2.3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;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 &lt;a href="https://github.com/gameap/plugin-mysql/blob/main/.github/workflows/release.yml" target="_blank" rel="noopener"&gt;plugin-mysql&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="configuración-del-repositorio-de-github"&gt;Configuración del repositorio de GitHub &lt;a class="hanchor" href="#configuraci%c3%b3n-del-repositorio-de-github" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;El token y el ID del plugin no deben estar en el código — pertenecen a la configuración del
repositorio. Abra &lt;strong&gt;Settings → Secrets and variables (en la sección Security and quality) →
Actions&lt;/strong&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets-sidebar.en.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets-sidebar.en_hu_9541da5da7d0384f.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/github-secrets-sidebar.en_hu_d3ee64d4baa6a46f.webp 800w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets-sidebar.en_hu_9963f0bb4b582211.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets-sidebar.en_hu_a2eced0c8f3ab9c4.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/github-secrets-sidebar.en_hu_9963f0bb4b582211.png 800w" sizes="(min-width: 860px) 808px, 100vw" width="800" height="844" alt="El elemento «Secrets and variables → Actions» en el menú lateral de la configuración del repositorio de GitHub" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;La sección de configuración del repositorio&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;En la pestaña &lt;strong&gt;Secrets&lt;/strong&gt; pulse &lt;strong&gt;New repository secret&lt;/strong&gt; y añada:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Nombre&lt;/th&gt;
					&lt;th&gt;Valor&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GAMEAP_DEPLOY_TOKEN&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;El token de despliegue que copió al crearlo (empieza por &lt;code&gt;gapd_&lt;/code&gt;)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GPG_SIGNING_KEY&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Una clave privada GPG en formato ASCII-armor, si firma sus compilaciones&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_dff430a18e15af5b.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_531cc5e7a73438e1.webp 800w, https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_6fdea19099fffc55.webp 1200w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_58a93b3c3b3364b1.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_88a534958aec6989.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_8367254b45013968.png 800w, https://blog.gameap.com/es/guides/publishing-plugins/github-secrets.en_hu_58a93b3c3b3364b1.png 1200w" sizes="(min-width: 860px) 808px, 100vw" width="1200" height="575" alt="La pestaña Secrets con los secretos GAMEAP_DEPLOY_TOKEN y GPG_SIGNING_KEY" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;Secretos del repositorio&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;En la pestaña &lt;strong&gt;Variables&lt;/strong&gt; pulse &lt;strong&gt;New repository variable&lt;/strong&gt; y añada:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Nombre&lt;/th&gt;
					&lt;th&gt;Valor&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;GAMEAP_PLUGIN_ID&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;El ID del plugin, p. ej. &lt;code&gt;fmqnme42gg7da&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;figure&gt;&lt;a class="zoom" href="https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en.png" target="_blank" rel="noopener"&gt;&lt;picture&gt;
 &lt;source type="image/webp" srcset="https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_f38ec3bfa362fe8b.webp 480w, https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_d954d987a2cc5fb6.webp 800w, https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_869e19eb01ccc276.webp 1200w" sizes="(min-width: 860px) 808px, 100vw"&gt;
 &lt;img src="https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_4d3d26a67a5a6e9d.png" srcset="https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_b1080eb19826b888.png 480w, https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_47d81d0f089d30fe.png 800w, https://blog.gameap.com/es/guides/publishing-plugins/github-variables.en_hu_4d3d26a67a5a6e9d.png 1200w" sizes="(min-width: 860px) 808px, 100vw" width="1200" height="524" alt="La pestaña Variables con la variable GAMEAP_PLUGIN_ID" loading="lazy" decoding="async"&gt;
 &lt;/picture&gt;&lt;/a&gt;&lt;figcaption&gt;Variables del repositorio&lt;/figcaption&gt;&lt;/figure&gt;&lt;p&gt;El ID del plugin es el mismo identificador base32 que escribió en &lt;code&gt;PluginInfo&lt;/code&gt;. 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.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;Así se exporta una clave privada GPG para &lt;code&gt;GPG_SIGNING_KEY&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;gpg --armor --export-secret-keys SU_ID_DE_CLAVE
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Publique la clave pública donde los usuarios puedan encontrarla — en el README del plugin, por
ejemplo — para que la firma sea verificable.&lt;/p&gt;
&lt;h3 id="dashboard-y-ci-valores-por-defecto-distintos"&gt;Dashboard y CI: valores por defecto distintos &lt;a class="hanchor" href="#dashboard-y-ci-valores-por-defecto-distintos" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Qué&lt;/th&gt;
					&lt;th&gt;Dashboard&lt;/th&gt;
					&lt;th&gt;CI&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Stable release&lt;/td&gt;
					&lt;td&gt;El interruptor está activado por defecto&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;is_stable&lt;/code&gt; por defecto es &lt;strong&gt;false&lt;/strong&gt; — pásalo explícitamente&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Envío a revisión&lt;/td&gt;
					&lt;td&gt;Manual, pulsando un botón&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;submit&lt;/code&gt; por defecto es &lt;strong&gt;true&lt;/strong&gt; — la versión va a revisión de inmediato&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Capturas de pantalla&lt;/td&gt;
					&lt;td&gt;Se ofrecen justo después de la subida&lt;/td&gt;
					&lt;td&gt;No soportadas, añádalas a través del dashboard&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Si lo único que quiere de CI es subir el archivo y terminar los metadatos a mano, pase
&lt;code&gt;submit=false&lt;/code&gt; y la versión permanecerá como borrador.&lt;/p&gt;
&lt;h3 id="errores"&gt;Errores &lt;a class="hanchor" href="#errores" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Código&lt;/th&gt;
					&lt;th&gt;Causa&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;400&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;ID de plugin inválido, un multipart mal formado o no se pasó &lt;code&gt;file&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;401&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;El token falta, es inválido o ha caducado; la cabecera no tiene la forma &lt;code&gt;Bearer gapd_...&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;403&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;El token es válido pero fue emitido para otro plugin&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;409&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Ya existe una versión con ese número&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;422&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;La versión no pasa la comprobación de semver; el archivo de fuentes falta, es demasiado grande o no es &lt;code&gt;.zip&lt;/code&gt;/&lt;code&gt;.tar.gz&lt;/code&gt;; se superan los límites de tamaño del archivo o de la firma&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Los cuerpos de error tienen una forma común:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;status&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;version already exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;version already exists&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;http_code&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;409&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Tras un error &lt;code&gt;5xx&lt;/code&gt;, no reintente la subida a ciegas.&lt;/strong&gt; 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 &lt;code&gt;409&lt;/code&gt;. Abra
el dashboard y compruebe qué pasó realmente.&lt;/p&gt;
&lt;h2 id="actualización-y-retirada-de-versiones"&gt;Actualización y retirada de versiones &lt;a class="hanchor" href="#actualizaci%c3%b3n-y-retirada-de-versiones" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;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 &lt;code&gt;409&lt;/code&gt;. Si la compilación salió mal, incremente la versión de parche.&lt;/p&gt;
&lt;p&gt;Cada fila de la tabla de versiones tiene sus propias acciones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Edit&lt;/strong&gt; — cambiar el changelog y los metadatos.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Submit for Review&lt;/strong&gt; — para borradores y versiones rechazadas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deprecate&lt;/strong&gt; — para versiones publicadas. La versión sigue disponible pero se marca como
obsoleta.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retract&lt;/strong&gt; — para versiones publicadas y obsoletas. La versión se retira de la publicación.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solo se puede eliminar un plugin en estado Draft. Un plugin publicado no se puede eliminar — se
puede retractar.&lt;/p&gt;
&lt;h2 id="lista-de-comprobación"&gt;Lista de comprobación &lt;a class="hanchor" href="#lista-de-comprobaci%c3%b3n" aria-label="Enlace a este encabezado"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;El correo está verificado, las reglas de publicación aceptadas y la cuenta tiene estado de
desarrollador.&lt;/li&gt;
&lt;li&gt;El plugin está creado, y el nombre y ambas descripciones están rellenos.&lt;/li&gt;
&lt;li&gt;Source URL o Repository URL están rellenos — de lo contrario, cada versión necesita un archivo
de fuentes.&lt;/li&gt;
&lt;li&gt;El ID del plugin está escrito en &lt;code&gt;PluginInfo.id&lt;/code&gt; y el &lt;code&gt;.wasm&lt;/code&gt; se recompiló después.&lt;/li&gt;
&lt;li&gt;El icono está subido y las traducciones de la ficha están en su sitio.&lt;/li&gt;
&lt;li&gt;La versión está subida, con firma y capturas de pantalla adjuntas.&lt;/li&gt;
&lt;li&gt;La versión está enviada a revisión, no dejada como borrador.&lt;/li&gt;
&lt;li&gt;Para CI: un token de despliegue creado y guardado en los secretos, el ID del plugin en las
variables.&lt;/li&gt;
&lt;li&gt;El workflow no tiene barra final en la URL y pasa &lt;code&gt;is_stable&lt;/code&gt; explícitamente.&lt;/li&gt;
&lt;li&gt;Tras el release, se confirma que el plugin y la versión están en estado Released.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item></channel></rss>