Skip to content

Сборка и публикация

Эта страница проведёт вас от дополнения, которое работает на вашей машине, до дополнения, которое владельцы серверов могут установить. Вы сделаете одну релизную сборку, узнаете, как версии выбираются за вас, и опубликуете в официальном маркетплейсе Pano на panomc.com — бесплатно или (с небольшой дополнительной связкой) как платное дополнение.

«Публикация» здесь означает превращение вашего дополнения в релизный jar (.jar — единственный zip-подобный файл, содержащий всё ваше скомпилированное дополнение) и размещение его там, где другие могут его получить.

Примеры на этой странице используют дополнение Shoutbox из Начала работы — небольшое дополнение, чей plugin ID — pano-plugin-shoutbox. Везде, где вы видите shoutbox или pano-plugin-shoutbox, подставляйте pluginId вашего собственного дополнения.

Если вы ещё не собрали своё дополнение, начните с Начала работы и Разработки бэкенда.

Прежде чем начать

Приготовьте эти четыре вещи. Остальная часть страницы предполагает их:

  • Ваше дополнение уже собирается локально — выполнение ./gradlew build в папке вашего дополнения завершается без ошибок. Если нет, сначала вернитесь к Началу работы и Разработке бэкенда.
  • Код вашего дополнения живёт в репозитории GitHub.
  • GitHub Actions включён для этого репозитория (для новых репозиториев он включён по умолчанию).
  • У вас есть бесплатный аккаунт на panomc.com.

Чек-лист первого релиза

Остальная часть страницы объясняет каждую часть детально, но вот вся работа по порядку, чтобы вы всегда знали, что осталось. Каждый шаг ссылается на своё полное объяснение и заканчивается тем, как понять, что он сработал.

Большая часть работы — одноразовая настройка (шаги 2–6). После этого каждый будущий релиз — просто шаг 7 — закоммитить и запушить.

  1. Соберите один раз локально, чтобы подтвердить, что jar производится. → Релизная сборка. Готово, когда вы видите BUILD SUCCESSFUL и jar в build/libs/.
  2. Создайте ресурс в маркетплейсе на panomc.com. → Создание ресурса. Готово, когда у вашего дополнения есть страница на panomc.com с пустым списком версий.
  3. Создайте API-токен и сохраните его как секрет репозитория с именем PANO_PROD_TOKEN (для ветки main). → Создание API-токена. Готово, когда секрет перечислен в настройках вашего репозитория.
  4. Создайте секрет TOKEN_GITHUB (GitHub Personal Access Token). Пропустите это, и каждый релиз падает на самом первом шаге. → Обязательно: секрет TOKEN_GITHUB.
  5. Добавьте .releaserc.json с плагином публикации Pano и замените плейсхолдеры в нём. → Разбор .releaserc.json.
  6. Добавьте один шаг установки в workflow, в оба job-а, чтобы плагин публикации Pano был доступен. Пропустите это, и релиз падает с Cannot find module @PanoMC/semantic-release-pano. → Плагин Pano должен быть установлен в workflow.
  7. Закоммитьте с сообщением в формате conventional-commit и запушьте в main. → Запушьте и наблюдайте публикацию. Готово, когда запуск Actions показывает зелёную галочку, а новая версия появляется в вашем ресурсе.

Релизная сборка

Релизная сборка компилирует ваш бэкенд Kotlin и собирает и встраивает Svelte UI в jar (.jar — единственный самодостаточный файл, который вы отгружаете). Это обычный:

bash
./gradlew build

Запускайте это из корневой папки вашего дополнения. Gradle — инструмент сборки для Kotlin-стороны — считайте ./gradlew build эквивалентом npm run build из мира JVM, а ./gradlew («обёртку Gradle») — скриптом в вашем проекте, который запускает правильную версию Gradle за вас. Через минуту-две вы должны увидеть BUILD SUCCESSFUL.

Вывод приземляется в:

build/libs/pano-plugin-shoutbox-<version>.jar

Локально <version> всегда local-build (так что файл — pano-plugin-shoutbox-local-build.jar). Теперь вы должны увидеть этот файл внутри build/libs/. Реальные номера версий приходят из CI — CI (continuous integration) — автоматическая сборка, которую GitHub запускает на своих серверах каждый раз, когда вы пушите. Смотрите Версионирование ниже.

Релизным jar нужен UI

Для релиза всегда запускайте обычный ./gradlew build — никогда не добавляйте -Pnoui. Флаг -Pnoui пропускает сборку UI Bun/rollup, и это может отгрузить сломанное дополнение двумя разными способами:

  • Если вы никогда не собирали UI: jar отгружается без UI вообще — ваше дополнение загружается без экранов панели или темы.
  • Если старая полная сборка оставила plugin-ui.zip: jar незаметно впекает этот устаревший UI, так что вы отгружаете устаревший интерфейс, не замечая.

Если хотите быть уверены, что старый UI zip не переиспользуется, запустите ./gradlew clean build (задача clean сначала удаляет предыдущий вывод сборки). -Pnoui только для быстрого цикла разработки только бэкенда (смотрите Начало работы).

jar полностью самодостаточен: бэкенд Kotlin, встроенный бандл UI, локализации и logo.png — всё живёт внутри него. Больше нечего отгружать.

Версионирование

У каждого релиза есть номер версии (вроде 1.0.0), чтобы серверы знали, когда доступно обновление.

Вы не поднимаете версию вручную. Версии решаются из ваших сообщений коммитов, которые должны следовать Conventional Commits — простому формату, где каждый коммит начинается со слова вроде feat: (новая возможность), fix: (исправление бага) или chore: (обслуживание). Эти слова управляют и следующим номером версии, и сгенерированным changelog. В версии вроде 1.2.3 1major, 2minor, а 3patch. feat: поднимает minor-версию, fix: поднимает patch-версию, а feat: с футером BREAKING CHANGE: поднимает major-версию.

Четыре разных имени в этом проекте звучат похоже, но означают разное. Эта таблица — та, что стоит держать в порядке:

ИмяЖивёт вКто задаётЧто означает
versiongradle.propertiesCI, во время релизаСобственная версия вашего дополнения (вроде 1.1.0). Остаётся local-build в вашей рабочей копии; никогда не редактируйте её вручную.
pluginPanoVersiongradle.propertiesВы (оставьте на local-build)Копируется в манифест jar. CI не трогает его.
pano-versionманифест jarприходит прямо из pluginPanoVersionПросто впечённая копия pluginPanoVersion внутри собранного jar.
panoVersion.releaserc.jsonВыВерсия платформы Pano, показываемая в вашем листинге маркетплейса (задаётся в файле конфигурации ниже).

Не редактируйте версии вручную

Оставьте и version, и pluginPanoVersion в gradle.properties на local-build. Во время релиза CI внедряет реальную version (через -Pversion — способ, которым Gradle принимает значение из командной строки, -Pversion=1.1.0) из вашей истории коммитов. Ручное поднятие её или редактирование тега (git-тега, который semantic-release создаёт для каждого релиза) ломает автоматизацию. CI не внедряет pluginPanoVersion; атрибут манифеста pano-version остаётся local-build. Версия Pano, объявляемая в маркетплейсе, — отдельное значение, задаваемое опцией panoVersion в .releaserc.json (ниже). Пусть ваши сообщения коммитов управляют версией. Смотрите Конфигурацию манифеста для деталей.

Каналы релизов

Boilerplate настроен на два канала релизов, решаемых тем, в какую ветку вы пушите:

ВеткаКаналВерсия выглядит как
devПредрелиз1.1.0-dev.3
mainСтабильный1.1.0

Предрелиз — тестовая сборка, которую вы можете попробовать до настоящего релиза. Суффикс -dev.3 означает «3-я dev-сборка на пути к 1.1.0». Владельцы серверов, устанавливающие стабильный канал, никогда их не видят; предрелиз — для вас, чтобы безопасно отрепетировать релиз.

Что такое GitHub Actions (прочтите это сначала)

GitHub Actions запускает скрипты на собственных серверах GitHub всякий раз, когда вы пушите. Скрипт — это YAML-файл в вашем репозитории — здесь .github/workflows/release.yml. Один файл содержит один или несколько job-ов; каждый job — список шагов; шаг выполняет команду или готовое действие. Этот файл делает всё, что ниже: собирает ваш jar и публикует его.

Пуш в dev или main запускает workflow GitHub Actions, поставляемый с pano-boilerplate-plugin в .github/workflows/release.yml. Этот workflow вычисляет следующую версию из ваших коммитов, запускает ./gradlew build (настоящая сборка UI — не -Pnoui), а затем запускает semantic-release — инструмент, который читает ваши сообщения коммитов, решает следующий номер версии, пишет changelog и публикует релиз, всё автоматически.

Одна правка требуется для публикации в маркетплейс. Из коробки workflow boilerplate запускает semantic-release без установленного плагина публикации Pano. Чтобы также публиковать в маркетплейс, вы должны добавить один шаг установки в workflow — это расписано в разделе Плагин Pano должен быть установлен в workflow ниже, и это шаг 6 чек-листа. Помимо этой одной правки и секретов, которые она ожидает, вы не трогаете workflow для обычного дополнения.

Триггер в начале этого workflow — просто:

yaml
on:
  push:
    branches: ['dev', 'main']

Это уже в boilerplate — вы его не меняете. Он показан, чтобы вы знали, что пуш в dev или main — весь триггер релиза: нет отдельной кнопки «опубликовать».

Разбор .releaserc.json

.releaserc.json — место, где настраивается semantic-release. Этот файл упоминает API-токен и ресурс маркетплейса, которые вы создаёте в следующем разделе — это нормально. Прочтите этот разбор, чтобы понять файл, настройте его, затем создайте эти вещи после.

Boilerplate поставляет .releaserc.json, который создаёт релиз GitHub с прикреплённым jar. Чтобы также публиковать в маркетплейс, вы добавляете плагин @PanoMC/semantic-release-pano.

Три имени здесь содержат слово «release» — держите их раздельно:

  • semantic-release — сам инструмент.
  • @semantic-release/commit-analyzer, @semantic-release/release-notes-generator, @semantic-release/github — стандартные, готовые плагины для этого инструмента.
  • @PanoMC/semantic-release-pano — единственный специфичный для Pano плагин, который вы добавляете, делающий публикацию в маркетплейс.

В списке plugins ниже каждая запись — либо имя плагина само по себе, либо пара [name, options] — двухэлементный массив из имени плагина плюс его настройки. Вот полный файл для Shoutbox — адаптированный 1:1 из реальной конфигурации релиза pano-plugin-faq:

json
{
  "branches": [
    { "name": "dev", "prerelease": true },
    "main"
  ],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    ["@semantic-release/github", {
      "assets": [
        { "path": "build/libs/*.jar", "label": false },
        { "path": "LICENSE", "label": false }
      ]
    }],
    ["@PanoMC/semantic-release-pano", {
      "file": "build/libs/pano-plugin-shoutbox-${version}.jar",
      "panoVersion": "1.0.0",
      "useGitHubLink": true,
      "repositoryUrl": "https://github.com/YourName/pano-plugin-shoutbox.git",
      "configs": [
        {
          "resourceId": "pano-plugin-shoutbox",
          "panoUrl": "https://api-dev.panomc.com",
          "tokenVar": "PANO_TOKEN",
          "branches": ["dev"]
        },
        {
          "resourceId": "pano-plugin-shoutbox",
          "panoUrl": "https://api.panomc.com",
          "tokenVar": "PANO_PROD_TOKEN",
          "branches": ["main"]
        }
      ]
    }]
  ],
  "repositoryUrl": "https://github.com/YourName/pano-plugin-shoutbox.git"
}

Замените эти плейсхолдеры

Прежде чем этот файл заработает, замените примерные значения на свои:

  • YourName (2 места — обе строки repositoryUrl) → ваше имя пользователя или организации GitHub.
  • pano-plugin-shoutbox (5 мест — путь file, оба значения resourceId и внутри обеих строк repositoryUrl) → ваш собственный pluginId.

Путь file должен содержать ваш pluginId точно, иначе релиз падает намного позже с запутанным «file not found». И да, repositoryUrl появляется дважды намеренно (один раз внутри опций плагина Pano, один раз на верхнем уровне) — задайте URL вашего репозитория в обоих.

Поле за полем:

ПолеЧто оно делает
commit-analyzer и release-notes-generatorПервые две записи в plugins. Стандартные плагины semantic-release — оставьте их ровно как есть.
@semantic-release/github assetsПрикрепляет ваш build/libs/*.jarLICENSE) к релизу GitHub. Держите плагины в этом порядке — плагин GitHub должен выполниться до плагина Pano, чтобы jar был уже прикреплён, когда useGitHubLink его понадобится. ("label": false просто оставляет собственное имя каждого файла как его метку загрузки — оставьте это.)
fileПуть к собранному jar. ${version} подставляется версией релиза.
panoVersionВерсия платформы Pano, под которую собрано и протестировано ваше дополнение (например, 1.0.0) — это значение, показываемое в вашем листинге маркетплейса. Это не собственная версия вашего дополнения.
useGitHubLinktrue = не перезагружать jar; вместо этого указать маркетплейсу на jar, уже прикреплённый к релизу GitHub (плюс его хеш SHA-256 — отпечаток, чтобы загрузку можно было проверить). Идеально для бесплатных дополнений — без дублирующей загрузки. Премиум-дополнения вместо этого загружают jar напрямую (премиум: задайте useGitHubLink: false; смотрите Премиум-аддоны и лицензирование).
configs[]Одна запись на канал. Каждая говорит в какой маркетплейс публиковать и с каким токеном, ограничено branches.
resourceIdВаш ресурс маркетплейса — для дополнений это ваш pluginId (смотрите ниже).
panoUrlAPI маркетплейса: https://api-dev.panomc.com для канала dev, https://api.panomc.com для main.
tokenVarИмя секрета GitHub, содержащего API-токен: PANO_TOKEN для dev, PANO_PROD_TOKEN для продакшена.
branchesОграничивает конфигурацию одним каналом, так что пуш в dev никогда не трогает продакшен-маркетплейс (а отсутствующий PANO_PROD_TOKEN не сломает dev-сборку).

Зачем два configs — и что такое «dev-маркетплейс»

api-dev.panomc.com — отдельный песочный маркетплейс: у него свои ресурсы, свои токены и свой вход, и ничто, что вы там публикуете, никогда не видят реальные владельцы серверов. Разделение по ветке означает, что вы можете отрепетировать релиз на api-dev.panomc.com из вашей ветки dev, затем отгрузить точно тот же код в реальный api.panomc.com из main.

Если вы публикуете своё первое дополнение, держите просто: публикуйте только в main. Удалите запись конфигурации dev (и ветку { "name": "dev", "prerelease": true }), и вам нужен только один токен, PANO_PROD_TOKEN. Добавьте dev-песочницу позже, если когда-нибудь захотите репетиционный канал.

Плагин Pano должен быть установлен в workflow

@PanoMC/semantic-release-pano не опубликован в npm и не является зависимостью boilerplate, так что перечисления его в .releaserc.json недостаточно само по себе — semantic-release упадёт с «Cannot find module @PanoMC/semantic-release-pano».

Это единственная обязательная правка workflow

Вы должны добавить этот шаг установки в оба job-а в .github/workflows/release.yml — job черновой прогонки версии (get-next-version) и job релиза (build-and-release) — размещённый перед шагом semantic-release каждого job-а:

yaml
- run: npm install -D git+https://github.com/PanoMC/semantic-release-pano.git

(-D = установить как dev-зависимость; URL git+ устанавливает плагин прямо с GitHub, потому что его нет в npm. Этот один шаг использует npm/npx, хотя остальная часть проекта использует Bun — так и должно быть здесь.)

Например, в job-е релиза он идёт прямо перед существующим шагом Release:

yaml
      # add this line...
      - run: npm install -D git+https://github.com/PanoMC/semantic-release-pano.git

      # ...before the step already in the file:
      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.TOKEN_GITHUB }}
        run: npx semantic-release@24.2.6

Сделайте то же в job-е черновой прогонки, перед его шагом npx semantic-release --dry-run. Если вы добавите это только в один job, запуск падает на другом с Cannot find module @PanoMC/semantic-release-pano — эта ошибка означает, что вы пропустили один из двух job-ов. Workflow pano-plugin-faq, из которого скопирована эта конфигурация, имеет ровно этот шаг.

Публикация в официальном маркетплейсе Pano

Маркетплейс на panomc.com — место, где владельцы серверов находят и устанавливают дополнения прямо из своей панели. Ресурс — листинг вашего дополнения в магазине на panomc.com. Публикация занимает три шага: создать ресурс, создать API-токен, затем позволить автоматизации загрузить версии. (Секрет TOKEN_GITHUB также требуется — смотрите блок после шага 2.)

1. Создание ресурса

  1. Зарегистрируйтесь (или войдите) на panomc.com.
  2. Из области вашего профиля откройте Create Resource и выберите тип Plugin.
  3. Выберите категорию, заполните название и описание.
  4. Выберите ценообразование: free или paid. Если вы просто публикуете бесплатное дополнение, выберите free — это вся эта страница. Выбор paid добавляет шаг лицензирования, рассмотренный в Премиум-аддоны и лицензирование.

Теперь вы должны увидеть страницу вашего дополнения на panomc.com с пустым списком версий — автоматизация заполнит его, когда вы запушите.

ID ресурса вашего дополнения — это ваш plugin ID

resourceId вашего дополнения в маркетплейсе — точно ваш pluginId — для Shoutbox это pano-plugin-shoutbox. Именно поэтому configs[] выше используют "resourceId": "pano-plugin-shoutbox", а не случайный ID. (Темы отличаются — они используют случайный UUID — но дополнения нет.) pluginId — единственная идентичность, которую Pano использует везде, где ваше дополнение касается системы: имя директории данных, префикс узла разрешения, сегмент URL для UI и ресурс маркетплейса. Полный список на Конфигурации манифеста.

2. Создание API-токена

  1. На panomc.com откройте Profile → Settings → API Tokens и нажмите Create.
  2. Скопируйте токен немедленно — он показывается только один раз, в модальном окне сразу после создания.
  3. В вашем репозитории GitHub перейдите в Settings → Secrets and variables → Actions и добавьте токен как секрет репозитория (зашифрованное значение, которое могут читать только ваши запуски Actions), с именем, соответствующим вашему tokenVar:
    • PANO_PROD_TOKEN для канала main (продакшен) — тот, что настраивается первым.
    • PANO_TOKEN для канала dev, только если вы сохранили конфигурацию dev-песочницы. Это другой токен, созданный в отдельной песочнице api-dev.panomc.com — не то же значение, что PANO_PROD_TOKEN.

Страница Settings → Secrets and variables → Actions вашего репозитория теперь должна перечислять PANO_PROD_TOKENPANO_TOKEN тоже, если вы публикуете в dev).

Никогда не коммитьте токен

API-токен даёт права публикации в ваш ресурс. Храните его только как секрет GitHub (или локальную переменную окружения). Никогда не помещайте его в .releaserc.json, коммит или любой файл в репозитории.

Обязательно: секрет TOKEN_GITHUB

Самому релизу GitHub нужен второй секрет, TOKEN_GITHUB, который workflow boilerplate читает (как secrets.TOKEN_GITHUB) в нескольких местах, включая черновую прогонку версии — репетиционный job, который вычисляет следующую версию, ничего не публикуя. Встроенный GITHUB_TOKEN GitHub не доступен под этим именем, так что вы должны создать его сами.

Без этого каждый релиз падает на самом первом шаге

Создайте TOKEN_GITHUB как Personal Access Token (PAT) — токен, который вы генерируете под своим аккаунтом GitHub:

  1. На GitHub перейдите в свой аватар → Settings → Developer settings → Personal access tokens.
  2. Создайте classic токен с областью repo (semantic-release нужна она, чтобы создавать релизы и пушить теги).
  3. Скопируйте его, затем добавьте в вашем репозитории под Settings → Secrets and variables → Actions как секрет с именем ровно TOKEN_GITHUB.

Список секретов вашего репозитория теперь должен показывать TOKEN_GITHUB.

Предпочитаете встроенный токен GitHub?

Если вы предпочли бы не создавать PAT, вы можете отредактировать workflow, чтобы он читал secrets.GITHUB_TOKEN (автоматический токен GitHub на запуск) вместо secrets.TOKEN_GITHUB. Путь PAT выше — стандартный для boilerplate и не требует правки workflow, так что это рекомендуемый путь.

3. Запушьте и наблюдайте публикацию

С созданным ресурсом, добавленными обоими обязательными секретами и .releaserc.json (плюс шагом установки workflow) на месте, публикация — просто коммит с сообщением в формате conventional-commit и пуш:

bash
git push origin main    # or dev, if you kept the dev sandbox

Теперь откройте вкладку Actions вашего репозитория. Запуск, названный по имени workflow (Pano Plugin Build), должен появиться в течение минуты. Обычно на завершение уходит несколько минут.

  • Зелёная галочка = опубликовано. Откройте ваш ресурс на panomc.com — новая версия должна быть в списке, и владельцы серверов увидят обновление в своей панели под Панель → Дополнения.
  • Красный крест = что-то упало. Кликните в упавший шаг, чтобы прочитать ошибку. Две самые частые:
    • Cannot find module @PanoMC/semantic-release-pano — вы пропустили шаг установки в одном из двух job-ов (шаг 6 / выноска об установке).
    • Ошибка аутентификации на самом первом шаге — отсутствующий или неправильный секрет TOKEN_GITHUB (блок TOKEN_GITHUB выше).

Ручное распространение

Вам не обязательно использовать маркетплейс. Поскольку релизный jar полностью самодостаточен, любой может установить его напрямую:

  • Прикрепите jar к релизу GitHub и поделитесь ссылкой, или
  • Передайте .jar владельцу сервера для загрузки через Панель → Дополнения → Загрузить.

Разница, которую видит пользователь: дополнения, скачанные из маркетплейса, помечены как проверенные, а вручную загруженные jar — нет. Для публичного дополнения маркетплейс настоятельно предпочтителен — он бесплатно даёт вам доставку обновлений, страницу магазина и значок проверенного.

Премиум-листинги

Продажа вашего дополнения работает через тот же поток релиза, плюс встроенный во время сборки ключ лицензии и проверка лицензии во время выполнения, впечённая в ваш код. Полное прохождение — встраивание ключа во время сборки, добавление проверки во время выполнения и связка её в CI — живёт в Премиум-аддоны и лицензирование. Оно строится прямо на этой странице; дополнительные флаги лицензии, которые оно использует (-PlicenseServer, -PpanoLicensePublicKey и переменная окружения PANO_LICENSE_PUBLIC_KEY), также сведены в Конфигурации манифеста.

Куда дальше