diff --git a/content/docs/api-service/operator-cli.mdx b/content/docs/api-service/operator-cli.mdx index 665315f..38b88ef 100644 --- a/content/docs/api-service/operator-cli.mdx +++ b/content/docs/api-service/operator-cli.mdx @@ -57,6 +57,7 @@ from another. | `--keep-going` | **true** | Continue after a failed build. | | `--runtime-image` | `debian:trixie-slim` | Image each built plugin is smoke-tested in; must match the base of the service image. | | `--no-smoke` | false | Skip the smoke run. The archive is still checked to unpack the way the service unpacks it. | +| `--platform` | this machine's | Platform to build and smoke-test for, e.g. `linux/amd64`. A smoke run for another architecture goes through Docker's emulation. | ## plugins publish @@ -91,6 +92,12 @@ everything it matches (see [Plugins](/docs/api-service/plugins#republishing)). Before anything is built, `publish` checks that storage answers, that the service accepts the token, and which versions the service already has. +Plugins are built and smoke-tested for the platform the service reports, e.g. +`linux/amd64`, so a Mac on Apple silicon publishes binaries the service can run; +`--platform` overrides it. A service older than v1.3.0 reports none: `publish` +warns and builds for the machine it runs on. Archives are packed reproducibly, +so an unchanged rebuild is byte-identical and is not uploaded again. + | Flag | Default | Meaning | |---|---|---| | `--archives` | — | Publish this `plugin.tgz` tree instead of building. | @@ -104,6 +111,7 @@ service accepts the token, and which versions the service already has. | `--dry-run` | false | List what would be published without building or contacting anything. | | `--non-interactive` | false | No interactive UI. | | `--runtime-image`, `--no-smoke` | as for `build` | Verification. | +| `--platform` | the service's | Platform to build and smoke-test for, instead of the one the service reports. | | `--cfg` | — | A **full** service config; `registry.s3` fills settings not given as flags. A fragment containing only `registry.s3` is refused. | | `--bucket` | — | Bucket (overrides the config). | | `--endpoint` | — | Endpoint URL, e.g. `http://localhost:9000`. | diff --git a/content/docs/api-service/operator-cli.ru.mdx b/content/docs/api-service/operator-cli.ru.mdx index 60772cc..da2913a 100644 --- a/content/docs/api-service/operator-cli.ru.mdx +++ b/content/docs/api-service/operator-cli.ru.mdx @@ -56,6 +56,7 @@ Docker. Каждая версия из `plugin.yaml` собирается с `-- | `--keep-going` | **true** | Продолжать после неудачной сборки. | | `--runtime-image` | `debian:trixie-slim` | Образ, в котором пробно запускается каждый собранный плагин; должен совпадать с базой образа сервиса. | | `--no-smoke` | false | Не запускать плагин. Архив всё равно проверяется на распаковку тем же способом, что в сервисе. | +| `--platform` | как у этой машины | Платформа сборки и пробного запуска, например `linux/amd64`. Пробный запуск под другую архитектуру идёт через эмуляцию Docker. | ## plugins publish @@ -91,6 +92,13 @@ Docker. Каждая версия из `plugin.yaml` собирается с `-- собирать, `publish` проверяет, что хранилище отвечает, что сервис принимает токен, и какие версии у сервиса уже есть. +Плагины собираются и пробно запускаются под платформу, которую сообщает сервис, +например `linux/amd64`, так что Mac на Apple silicon публикует бинарники, которые +сервис сможет запустить; `--platform` её заменяет. Сервис старше v1.3.0 +платформу не сообщает: `publish` предупреждает и собирает под машину, на которой +запущен. Архивы упаковываются воспроизводимо, поэтому неизменённая пересборка +побайтно совпадает и повторно не загружается. + | Флаг | По умолчанию | Смысл | |---|---|---| | `--archives` | — | Опубликовать это дерево `plugin.tgz` вместо сборки. | @@ -104,6 +112,7 @@ Docker. Каждая версия из `plugin.yaml` собирается с `-- | `--dry-run` | false | Показать, что будет опубликовано, ничего не собирая и никуда не обращаясь. | | `--non-interactive` | false | Без интерактивного интерфейса. | | `--runtime-image`, `--no-smoke` | как у `build` | Проверка. | +| `--platform` | как у сервиса | Платформа сборки и пробного запуска вместо той, что сообщает сервис. | | `--cfg` | — | **Полный** конфиг сервиса; `registry.s3` заполняет то, что не передано флагами. Фрагмент только с `registry.s3` отвергается. | | `--bucket` | — | Бакет (переопределяет конфиг). | | `--endpoint` | — | URL эндпоинта, например `http://localhost:9000`. | diff --git a/content/docs/api-service/plugins.mdx b/content/docs/api-service/plugins.mdx index 103fa71..b28d8cb 100644 --- a/content/docs/api-service/plugins.mdx +++ b/content/docs/api-service/plugins.mdx @@ -111,12 +111,15 @@ a time, so a catalogue never has to fit on the publishing machine and nothing is registered before its archive is in place: 1. **build** — a Docker build of the version. Needs Docker. Produces Linux - binaries. + binaries for the platform the service reports, e.g. `linux/amd64`, whatever + the publishing machine is; `--platform` overrides it. A service older than + v1.3.0 reports none, and the build is for the publishing machine. 2. **verify** — the bundle is packed and unpacked with the service's own unpacker, and `plugin` is smoke-run in the service's base image. A version that fails goes no further. 3. **upload** — `plugin.tgz` goes to storage with its sha256 in the object - metadata. Skipped when storage already holds the same archive. + metadata. Skipped when storage already holds the same archive; archives are + packed reproducibly, so an unchanged rebuild is the same archive. 4. **register** — `CreatePlugin` (or `UpdatePlugin`, if the service already has the version) with the sha256 in the config. The service checks the archive is in storage with that checksum and derives the command @@ -140,7 +143,8 @@ archive actually has. the new archive and replaces the version's config with the new checksum through `UpdatePlugin`. Every replica then refetches its unpacked copy on next use: each keeps a `.sha256` marker beside the unpacked directory and compares it with the -registry. Directories unpacked before v1.2.0 have no marker and count as current. +registry. A directory without a marker, unpacked before v1.2.0, is fetched once +and gets one. The config `publish` sends is the whole config, so a hand-edited `env` or `timeout` does not survive republishing. diff --git a/content/docs/api-service/plugins.ru.mdx b/content/docs/api-service/plugins.ru.mdx index b5f5438..0f789a1 100644 --- a/content/docs/api-service/plugins.ru.mdx +++ b/content/docs/api-service/plugins.ru.mdx @@ -110,12 +110,16 @@ sequenceDiagram ничего не регистрируется раньше, чем его архив окажется на месте: 1. **build** — Docker-сборка версии. Нужен Docker. Получаются линуксовые - бинарники. + бинарники под платформу, которую сообщает сервис, например `linux/amd64`, на + какой бы машине ни шла публикация; `--platform` её заменяет. Сервис старше + v1.3.0 платформу не сообщает, и сборка идёт под публикующую машину. 2. **verify** — бандл упаковывается и распаковывается распаковщиком самого сервиса, а `plugin` пробно запускается в базовом образе сервиса. Версия, не прошедшая проверку, дальше не идёт. 3. **upload** — `plugin.tgz` загружается в хранилище с sha256 в метаданных - объекта. Пропускается, если в хранилище уже тот же архив. + объекта. Пропускается, если в хранилище уже тот же архив; архивы + упаковываются воспроизводимо, так что неизменённая пересборка даёт тот же + архив. 4. **register** — `CreatePlugin` (или `UpdatePlugin`, если версия у сервиса уже есть) с sha256 в конфиге. Сервис проверяет, что архив лежит в хранилище с этой контрольной суммой, и сам выводит команду @@ -140,8 +144,8 @@ sequenceDiagram загружает новый архив и заменяет конфиг версии новой контрольной суммой через `UpdatePlugin`. После этого каждая реплика при следующем обращении заново скачивает распакованную копию: рядом с распакованным каталогом каждая хранит -маркер `.sha256` и сверяет его с реестром. Каталоги, распакованные до v1.2.0, -маркера не имеют и считаются актуальными. `publish` отправляет конфиг целиком, +маркер `.sha256` и сверяет его с реестром. Каталог без маркера, распакованный +до v1.2.0, скачивается один раз и получает маркер. `publish` отправляет конфиг целиком, поэтому вручную изменённые `env` или `timeout` повторную публикацию не переживают. diff --git a/content/docs/api-service/quickstart.mdx b/content/docs/api-service/quickstart.mdx index 128513b..67e7ebd 100644 --- a/content/docs/api-service/quickstart.mdx +++ b/content/docs/api-service/quickstart.mdx @@ -63,7 +63,7 @@ services: retries: 30 service: - image: ghcr.io/easyp-tech/service:v1.2.1 + image: ghcr.io/easyp-tech/service:v1.3.0 command: ["service", "start"] depends_on: postgres: diff --git a/content/docs/api-service/quickstart.ru.mdx b/content/docs/api-service/quickstart.ru.mdx index 3a5d2e9..974d479 100644 --- a/content/docs/api-service/quickstart.ru.mdx +++ b/content/docs/api-service/quickstart.ru.mdx @@ -63,7 +63,7 @@ services: retries: 30 service: - image: ghcr.io/easyp-tech/service:v1.2.1 + image: ghcr.io/easyp-tech/service:v1.3.0 command: ["service", "start"] depends_on: postgres: diff --git a/content/docs/api-service/upgrading.mdx b/content/docs/api-service/upgrading.mdx index 4d986d6..b23898d 100644 --- a/content/docs/api-service/upgrading.mdx +++ b/content/docs/api-service/upgrading.mdx @@ -34,6 +34,26 @@ A rename is handled without breaking anyone: the old configuration key keeps working for one release while warning, naming both spellings and the line to change, and only then stops. +## v1.2.1 → v1.3.0 + +### `plugins publish` builds for the service's platform + +`PluginsResponse` gains `platform`, the `os/arch` the service runs plugins on, +and `plugins publish` builds and smoke-tests for it. Before, it built for the +machine it ran on: published from a Mac on Apple silicon, a version was an arm64 +binary that an amd64 service fails to start with `exec format error`. +Republish such versions with `plugins publish --force`. Upgrade the service +before the CLI, or pass `--platform linux/amd64`: against an older service +`publish` warns and builds for its own machine, as before. + +### Archives are reproducible + +`plugins publish` packs a version with fixed timestamps, owners and modes, so +rebuilding an unchanged version produces the same archive and its upload is +skipped. Archives already in storage were packed the old way: the first +`publish --force` after upgrading uploads every version once more, and each +replica refetches what it serves. + ## v1.2.0 → v1.2.1 ### Unpacked copies without a checksum marker are fetched once diff --git a/content/docs/api-service/upgrading.ru.mdx b/content/docs/api-service/upgrading.ru.mdx index 9e40f39..249dc69 100644 --- a/content/docs/api-service/upgrading.ru.mdx +++ b/content/docs/api-service/upgrading.ru.mdx @@ -34,6 +34,27 @@ description: "Заметки по обновлению API Service от рели работать один релиз, предупреждая и называя оба написания и строку, которую надо поправить, и только после этого перестаёт. +## v1.2.1 → v1.3.0 + +### `plugins publish` собирает под платформу сервиса + +В `PluginsResponse` появилось поле `platform` — `os/arch`, на которой сервис +запускает плагины, и `plugins publish` собирает и пробно запускает плагины под +неё. Раньше сборка шла под машину, на которой запущен `publish`: опубликованная +с Mac на Apple silicon версия была arm64-бинарником, который amd64-сервис не +запускает (`exec format error`). Такие версии перепубликуйте через +`plugins publish --force`. Обновляйте сервис раньше CLI или передавайте +`--platform linux/amd64`: со старым сервисом `publish` предупреждает и, как +раньше, собирает под свою машину. + +### Архивы воспроизводимы + +`plugins publish` упаковывает версию с фиксированными временем, владельцами и +правами, поэтому пересборка неизменённой версии даёт тот же архив, и загрузка +пропускается. Архивы, уже лежащие в хранилище, упакованы по-старому: первый +`publish --force` после обновления ещё раз загрузит каждую версию, а каждая +реплика заново скачает то, что обслуживает. + ## v1.2.0 → v1.2.1 ### Копии без маркера контрольной суммы перекачиваются один раз