diff --git a/AGENTS.md b/AGENTS.md index 38ff8b0..f7b25f9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,11 +23,13 @@ Не обходить серверные правила доступа к загрузке и результату обработки. - Рабочий `config.json` на каждом хостинге настраивает владелец. Деплой не имеет права перезаписывать его значений. При появлении новой обязательной UTM workflow - получает текущий хостовый конфиг и добавляет только отсутствующий ключ через - `bin/ensure-focus-config.php`; имеющиеся значения, включая уже настроенный - `focus`, остаются байт-в-байт прежними. `requisites.html` также живёт только на - хостинге и не перезаписывается. Не создавать target-specific конфиги или - `config.json.example`. + получает текущий хостовый конфиг и меняет только ключи, которые прямо + согласованы в задаче. Иные значения, включая уже настроенные UTM, остаются + байт-в-байт прежними. Для #274 `bin/ensure-focus-config.php` — явное + исключение: он задаёт только новый `focus=face` (default и rnd). После каждого + такого выпуска фактический stage-config следует забрать и зафиксировать в Git. + `requisites.html` также живёт только на хостинге и не перезаписывается. Не + создавать target-specific конфиги или `config.json.example`. - Коммит в `main` запускает FTP-автодеплой на все цели workflow; откат через `git revert` также запускает выкат. Коммит, push и изменения хостинга — только по прямому поручению. - Проверки кода и браузера проводить в Docker без установки ПО на хост. diff --git a/README.md b/README.md index 5da2c52..f7a6432 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Preland всегда формирует полный resolved-набор сво | `requisites.html` | реквизиты для подвала (HTML), если в `config.json` нет `requisites`. Без обоих — **заглушка «ИП Иванов Иван Иванович»** из `template.php` | | `images/`, `fonts/`, `favicon/`, `*.css` | статика; `style.min.css` встраивается в страницу | | `.htaccess` | только сроки кэширования статики (Apache) | -| `config.json` | зафиксированный Git-снимок актуального stage-конфига; runtime-файл хоста является источником истины и обычным deploy не заменяется | +| `config.json` | снимок актуального stage-конфига и схема. Рабочий конфиг на каждом хостинге настраивает владелец; deploy не заменяет его и меняет только явно согласованные в задаче ключи. После такого изменения актуальный stage-снимок забирают обратно в Git | ### `config.json` diff --git a/bin/ensure-focus-config.php b/bin/ensure-focus-config.php index 5e8507a..bc87327 100644 --- a/bin/ensure-focus-config.php +++ b/bin/ensure-focus-config.php @@ -1,11 +1,13 @@ [ 'center' => 0, 'face' => 1, @@ -49,6 +47,13 @@ $config['utm']['focus'] = [ 'default' => 'face', ]; +if (($config['utm']['focus'] ?? null) === $focus) { + fwrite(STDOUT, "focus уже включён: конфиг не изменён.\n"); + exit(0); +} + +$config['utm']['focus'] = $focus; + try { $encoded = json_encode( $config, @@ -64,5 +69,5 @@ if (file_put_contents($path, $encoded, LOCK_EX) === false) { exit(2); } -fwrite(STDOUT, "Добавлен только utm.focus (face включён по умолчанию).\n"); +fwrite(STDOUT, "Изменён только utm.focus: face включён по умолчанию и для rnd.\n"); exit(10); diff --git a/tests/check-host-config-patch.php b/tests/check-host-config-patch.php new file mode 100644 index 0000000..f3ab7f0 --- /dev/null +++ b/tests/check-host-config-patch.php @@ -0,0 +1,39 @@ + 'custom.example', + 'requisites' => ['Не менять'], + 'utm' => [ + 'theme' => ['weights' => ['dark' => 7, 'light' => 3], 'default' => 'light'], + 'focus' => ['weights' => ['center' => 9, 'face' => 1], 'default' => 'center'], + ], +]; +$path = tempnam(sys_get_temp_dir(), 'preland-config-'); +if ($path === false) { + fwrite(STDERR, "FAIL: не создан временный config.\n"); + exit(1); +} + +try { + file_put_contents($path, json_encode($fixture, JSON_THROW_ON_ERROR)); + exec(PHP_BINARY . ' ' . escapeshellarg($script) . ' ' . escapeshellarg($path), $output, $code); + $actual = json_decode((string) file_get_contents($path), true, 512, JSON_THROW_ON_ERROR); +} finally { + @unlink($path); +} + +if ($code !== 10 + || ($actual['host'] ?? null) !== 'custom.example' + || ($actual['requisites'] ?? null) !== ['Не менять'] + || ($actual['utm']['theme'] ?? null) !== $fixture['utm']['theme'] + || ($actual['utm']['focus'] ?? null) !== ['weights' => ['center' => 0, 'face' => 1], 'default' => 'face']) { + fwrite(STDERR, "FAIL: host-config должен сохранить все значения, кроме явно заданного focus.\n"); + exit(1); +} + +fwrite(STDOUT, "OK: host config changes only explicit focus\n"); diff --git a/tests/check-versioned-stage-config.php b/tests/check-versioned-stage-config.php index 3744705..e0b64f5 100644 --- a/tests/check-versioned-stage-config.php +++ b/tests/check-versioned-stage-config.php @@ -4,7 +4,7 @@ * * Репозиторный config.json задаёт схему и стартовые значения. Рабочий конфиг * владельца на хостинге не перезаписывается: delivery добавляет только - * отсутствующие обязательные UTM-ключи. + * явно согласованные ключи. В #274 это единственный новый ключ focus. */ declare(strict_types=1); @@ -63,7 +63,7 @@ foreach ([ || !str_contains($block, 'config\\.json$') || !str_contains($block, 'ensure-focus-config.php') || !str_contains($block, 'Preserve host config and add focus if absent')) { - $failures[] = "{$delivery} обязан сохранять хостовый config.json и добавлять только отсутствующий focus."; + $failures[] = "{$delivery} обязан сохранять хостовый config.json и менять только явно согласованный focus."; } }