Перейти до основного вмісту

Тримати один модуль на тій версії, що працює

Автооновлення модулів було «все або нічого». writable/auto_update_modules.on змітав кожен установлений store-модуль, у якого в каталозі є новіша версія, і єдине, що могло зупинити один із них, — детектор локальних правок, тобто випадковість, а не рішення. Сайт, який інтегрував один модуль або просто ще не перевірив його новий реліз, міг утримати його, лише вимкнувши автооновлення для всього.

Фіксація (pin) — відповідь на рівні модуля: модуль лишається на тій версії, що працює, решта оновлюється далі.

Фіксація — тимчасовий захід, а не спосіб жити. Вона тримає модуль, поки ви перевіряєте реліз, поки переперевіряється інтеграція або поки клієнт не підтвердив. Потім її знімають. Модуль, зафіксований на місяці, — це модуль, який колись оновлять одразу через кілька релізів, а це і є ризиковане оновлення, а не безпечне. Адмінка і --list завжди показують і зафіксовану версію, і ту, що пропонує каталог: фіксація може затримати оновлення, але не приховати його.

Що робить фіксація​

ШляхКоли фіксація діє
cms9:auto-update (нічний)пропускає модуль, пише причину в writable/logs/auto-update.log
cms9:module-update --allпоказує модуль як pinned at vX — skipped, код виходу не змінюється
cms9:module-update <module>відмовляє, код виходу 1
Кнопка «Оновити» на полиці модулівзаблокована, картка пояснює чому
ВЛАСНА кнопка «Оновити» модуля, що оновлює себе самзаблокована, банер каже зафіксовано vX, доступна vY
cms9:module-update <module> --ignore-pinоновлює і переносить фіксацію на нову версію

Усі ці шляхи проходять одне й те саме рішення в App\Libraries\UpdateServer\ModuleInstaller::install() — нове місце виклику успадковує поведінку, а не переписує її. Обидві команди додатково відсікають зафіксований модуль до будь-якої мережевої роботи, щоб пакетний прогін міг відзвітувати без завантаження пакета.

Модулі, що оновлюють себе самі​

Кілька модулів носять власного клієнта оновлень — Libraries/ModuleUpdater.php усередині модуля (Notify, Pixozip, CloudStorage). Вони ходять на сервер оновлень напряму і не проходять через ModuleInstaller, тому питання про фіксацію ставлять самі, через той самий App\Libraries\UpdateServer\ModulePins::blockedFor():

  • check() повертає pinned, pin_reason і pin_blocked поруч із latest — і рахує це поза добовим кешем перевірки, щоб фіксація, поставлена п'ять хвилин тому, гасила кнопку зараз, а не завтра;
  • update() відмовляє до завантаження, бекапу й запису — тим самим реченням, що друкує CLI (error: pinned);
  • власний банер модуля показує зафіксовано vX, доступна vY, а кнопка «Оновити» — disabled; реліз із прапорцем security: true додає червоний рядок і фіксацію все одно не знімає.

Виклик загорнуто в class_exists() навмисно: ці модулі їдуть окремими пакетами і ставляться на ядра, старші за саму фіксацію, де класу ModulePins просто немає. Фіксації там теж не буває — тож «ніщо не блокує» і є правильна відповідь, а не фатальна помилка.

Пишеш новий модуль із власним апдейтером — скопіюй цю пару викликів. Самооновлювач, що їх не має, — це діра в кожній фіксації на сайті.

Як довести фіксацію, не зрушивши весь сайт​

cms9:auto-update має для цього два прапорці:

php spark cms9:auto-update --only=my_module # лише цей модуль; ЯДРО не чіпається
php spark cms9:auto-update --only=my_module --dry-run # вирішує і логує, не пише нічого

--dry-run пише would update 1.0.1 → 1.0.2 — nothing written (і звичний рядок pinned … skipped для зафіксованого модуля) з позначкою [dry-run] у writable/logs/auto-update.log. --only і робить перевірку прийнятною на спільному стенді: без нього довести, що тримається один модуль, означає дати оновитися всім іншим на цій машині. Приймаються обидві форми: --only=x і --only x.

Командний рядок​

php spark cms9:module-pin my_module --reason="чекаємо підтвердження інтеграції"
php spark cms9:module-pin my_module --version=1.0.3 # зафіксувати не на встановленій версії
php spark cms9:module-unpin my_module
php spark cms9:module-pin --list
php spark cms9:module-pin --list --json

Приймаються обидві форми опцій — --reason=текст і --reason текст.

Коди виходу: 0 — успіх; 1 — некоректний identif модуля, модуль не встановлений (нема на що фіксувати), модуль їде всередині core-zip (див. нижче) або — для cms9:module-unpin — модуль не був зафіксований.

Адмінка​

На полиці модулів (Модулі → Магазин) установлений модуль отримує:

  • Зафіксувати на цій версії — питає причину і заморожує модуль;
  • позначку зафіксовано: vX поруч із доступна: vY, коли каталог попереду;
  • Зняти фіксацію;
  • заблоковану кнопку «Оновити», поки фіксація тримає.

Обидві дії пишуться в журнал адмінки як module.pin / module.unpin разом із причиною — у фіксації є автор і дата, а не лише запис у файлі.

Де лежить стан​

writable/store_pins.json, поруч зі store_versions.json — навмисно поза текою модуля і поза його рядком у components, щоб фіксація пережила видалення й повторне встановлення модуля. Так само навмисно це не той самий файл, що writable/module_local_changes.json: там записано, що випадково зупинив детектор правок, а тут — що вибрала людина.

{
"my_module": {
"version": "1.0.3",
"by": "owner@example.com",
"at": 1790220000,
"reason": "чекаємо підтвердження інтеграції",
"security": {
"to": "1.0.5",
"since": 1790300000,
"dismissed": ""
}
}
}
  • version — версія, на якій заморожено модуль;
  • by — e-mail адміна або cli, якщо фіксували з командного рядка;
  • at — unix-час фіксації (або останнього перенесення через --ignore-pin);
  • reason — вільний текст, видно в адмінці й у --list;
  • security — присутнє, лише поки чекає безпековий реліз, див. нижче.

Файл пишеться атомарно (тимчасовий файл + rename) і видаляється, коли знято останню фіксацію, — порожній store_pins.json не залишається.

--ignore-pin переносить фіксацію, а не знімає її​

php spark cms9:module-update my_module --ignore-pin ставить нову версію і переписує фіксацію на неї, зберігаючи by і reason. Власник сказав «оновити саме цей», а не «перестати фіксувати модуль» — зняти фіксацію означало б тихо повернути модуль у нічний прогін, тобто рівно те, проти чого фіксація й існує. Щоб справді зняти її — cms9:module-unpin.

Безпекові релізи: фіксація тримає далі​

Запис у каталозі може нести необов'язкове булеве поле security у manifest модуля:

{ "module": "my_module", "version": "1.0.5", "security": true }

update.php (list/check) віддає це поле як є — більше на сервері оновлень його ніщо не інтерпретує.

Безпековий реліз не знімає фіксацію автоматично. Тихе оновлення — саме те, проти чого фіксація існує. Натомість:

  • угорі адмінки зʼявляється червоний банер із назвою модуля і версією, що чекає;
  • банер тримається, доки адмін його не закриє, і закриття нічого не оновлює;
  • картка модуля позначена так само.

Рішення — оновити зараз чи тримати далі — лишається людині. Звичайні (не безпекові) релізи поводяться так само, тільки без червоного банера.

Межа: модулі, що їдуть у core-zip​

Кожен модуль, що їде всередині core-zip, версіонується разом із ядром: оновлювач ядра кладе його файли як частину білда, а версія — це номер білда ядра. Це system і standard за Config\ModulePolicy (наприклад notify, gallery) — два класи, яких пакувальник ніколи не виключає, — плюс будь-який інший модуль, що є у файловому переліку встановленого білда (платний модуль, у якого ще немає store-пакета). Вони фіксуються разом із ядром, утриманням білда ядра, а не поодинці. cms9:module-pin таким відмовляє, і кнопка в адмінці теж (у картки її просто немає):

notify: Модуль оновлюється разом з ядром, зафіксувати його версію не можна.

Запис фіксації, що лишила на такому модулі старіша версія, фіксацією не є: оновлювачі й картка його ігнорують, а сам він видаляється з рядком у writable/logs/auto-update.log.

Коли фіксація — не той інструмент​

Фіксація купує час, але не замінює штатну точку розширення. Якщо ви фіксуєте модуль тому, що новий реліз затре ваші правки, проблема — у правках:

Перенесіть зміну в одне з цього — і зніміть фіксацію.