chore: version single preland config
This commit is contained in:
1 parent
8d2beb36e0
commit
dfbb086e2b
7 files changed
+120
-45
No files matched your search
@@ -5,8 +5,9 @@ name: deploy-preland
|
||||
# Цель — домен со своим хостингом (список — matrix ниже): реквизиты — секреты репозитория <prefix>_FTP_HOST,
|
||||
# <prefix>_FTP_USER, <prefix>_FTP_PASS (порт 21). Цели независимы: сбой одного хостинга остальные не останавливает.
|
||||
# Заливаются файлы репозитория (git ls-files), кроме служебных (.gitea/, README.md, AGENTS.md, CLAUDE.md, .gitignore) и тех, что живут
|
||||
# только на хостинге: config.json (в git его нет) и requisites.html (реквизиты заполняют на месте — пустой файл
|
||||
# из git их бы затёр). На хостинге ничего не удаляется: удалённое из репозитория убирать вручную.
|
||||
# только на хостинге: requisites.html (реквизиты заполняют на месте — пустой файл из git их бы затёр).
|
||||
# Рабочий config.json единственный и версионируется: он должен попадать в каждую доставку.
|
||||
# На хостинге ничего не удаляется: удалённое из репозитория убирать вручную.
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -26,7 +27,7 @@ jobs:
|
||||
include:
|
||||
# name — имя цели, url — адрес преленда (для проверки), prefix — префикс секретов <prefix>_FTP_*,
|
||||
# dir — каталог сайта на FTP ("" — корень FTP, как на beget). Новый домен — новая запись и три секрета;
|
||||
# config.json (и requisites.html) создают на хостинге цели — без него проверка страницы не пройдёт.
|
||||
# requisites.html создают на хостинге цели. Рабочий config.json приходит из Git.
|
||||
- name: barbariskatest
|
||||
url: https://preland.anton.barbariskatest.ru
|
||||
prefix: PRELAND
|
||||
@@ -61,7 +62,7 @@ jobs:
|
||||
netrc=$(mktemp); list=$(mktemp)
|
||||
trap 'rm -f "$netrc" "$list"' EXIT
|
||||
printf 'machine %s login %s password %s\n' "$FTP_HOST" "$FTP_USER" "$FTP_PASS" > "$netrc"
|
||||
git ls-files | grep -vE '^(\.gitea/|README\.md$|AGENTS\.md$|CLAUDE\.md$|\.gitignore$|config\.json$|requisites\.html$)' > files.txt
|
||||
git ls-files | grep -vE '^(\.gitea/|README\.md$|AGENTS\.md$|CLAUDE\.md$|\.gitignore$|requisites\.html$)' > files.txt
|
||||
# имя уходит в адрес ftp:// как есть — пробелы и прочее экранирование не поддерживаем
|
||||
if grep -q '[^A-Za-z0-9._/-]' files.txt; then echo "имена с недопустимыми символами:"; grep '[^A-Za-z0-9._/-]' files.txt; exit 1; fi
|
||||
# один curl на все файлы — одно соединение FTP+TLS вместо соединения на файл
|
||||
@@ -118,7 +119,7 @@ jobs:
|
||||
files=$(mktemp)
|
||||
trap 'rm -f "$known_hosts" "$batch" "$files"' EXIT
|
||||
printf '%s\n' "$SFTP_KNOWN_HOSTS" > "$known_hosts"
|
||||
git ls-files | grep -vE '^(\.gitea/|README\.md$|AGENTS\.md$|CLAUDE\.md$|\.gitignore$|config\.json$|requisites\.html$)' > "$files"
|
||||
git ls-files | grep -vE '^(\.gitea/|README\.md$|AGENTS\.md$|CLAUDE\.md$|\.gitignore$|requisites\.html$)' > "$files"
|
||||
if grep -q '[^A-Za-z0-9._/-]' "$files"; then echo "имена с недопустимыми символами:"; grep '[^A-Za-z0-9._/-]' "$files"; exit 1; fi
|
||||
printf '%s\n' "-mkdir $REMOTE_DIR" > "$batch"
|
||||
sed 's#/[^/]*$##' "$files" | grep -v '^$' | sort -u | while read -r dir; do printf '%s\n' "-mkdir $REMOTE_DIR/$dir" >> "$batch"; done
|
||||
@@ -177,7 +178,7 @@ jobs:
|
||||
files=$(mktemp)
|
||||
trap 'rm -f "$known_hosts" "$batch" "$files"' EXIT
|
||||
printf '%s\n' "$SFTP_KNOWN_HOSTS" > "$known_hosts"
|
||||
git ls-files | grep -vE '^(\.gitea/|README\.md$|AGENTS\.md$|CLAUDE\.md$|\.gitignore$|config\.json$|requisites\.html$)' > "$files"
|
||||
git ls-files | grep -vE '^(\.gitea/|README\.md$|AGENTS\.md$|CLAUDE\.md$|\.gitignore$|requisites\.html$)' > "$files"
|
||||
if grep -q '[^A-Za-z0-9._/-]' "$files"; then echo "имена с недопустимыми символами:"; grep '[^A-Za-z0-9._/-]' "$files"; exit 1; fi
|
||||
printf '%s\n' "-mkdir $REMOTE_DIR" > "$batch"
|
||||
sed 's#/[^/]*$##' "$files" | grep -v '^$' | sort -u | while read -r dir; do printf '%s\n' "-mkdir $REMOTE_DIR/$dir" >> "$batch"; done
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
config.json
|
||||
@@ -8,7 +8,7 @@
|
||||
## Перед работой
|
||||
|
||||
- Прочитать [README.md](README.md), [заметку проекта](../.known-base/Проекты/Преленд%20—%20anton-preland.md),
|
||||
а для выката — `.gitea/workflows/deploy.yml` и `config.json.example`.
|
||||
а для выката — `.gitea/workflows/deploy.yml` и единственный `config.json`.
|
||||
- Проверить состояние ветки и чужие изменения в `preland/`; изменения API сайта согласовать
|
||||
с его контрактом и инструкциями `api/`.
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
переход напрямую на `/public/upscale` не заменяет передачу владельца через claim.
|
||||
- `host` задаёт сайт назначения; HTTPS необходим для `crypto.randomUUID()`.
|
||||
Не обходить серверные правила доступа к загрузке и результату обработки.
|
||||
- Рабочий `config.json` каждой цели и `requisites.html` живут на хостинге: не добавлять
|
||||
их в git, не перезаписывать и не удалять при деплое. В репозитории — только образец конфига.
|
||||
- Рабочий `config.json` единственный для всех прилендов: это точная проверенная
|
||||
конфигурация `zoomstage.online`, и каждый FTP/SFTP-deploy обязан доставлять её на
|
||||
stage и production. `requisites.html` по-прежнему живёт только на хостинге и не
|
||||
перезаписывается. Не создавать target-specific конфиги или `config.json.example`.
|
||||
- Коммит в `main` запускает FTP-автодеплой на все цели workflow; откат через `git revert`
|
||||
также запускает выкат. Коммит, push и изменения хостинга — только по прямому поручению.
|
||||
- Проверки кода и браузера проводить в Docker без установки ПО на хост.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
## Перед работой
|
||||
|
||||
- Прочитать [README.md](README.md), [заметку проекта](../.known-base/Проекты/Преленд%20—%20anton-preland.md),
|
||||
а для выката — `.gitea/workflows/deploy.yml` и `config.json.example`.
|
||||
а для выката — `.gitea/workflows/deploy.yml` и единственный `config.json`.
|
||||
- Проверить состояние ветки и чужие изменения в `preland/`; изменения API сайта согласовать
|
||||
с его контрактом и инструкциями `api/`.
|
||||
|
||||
@@ -21,8 +21,10 @@
|
||||
переход напрямую на `/public/upscale` не заменяет передачу владельца через claim.
|
||||
- `host` задаёт сайт назначения; HTTPS необходим для `crypto.randomUUID()`.
|
||||
Не обходить серверные правила доступа к загрузке и результату обработки.
|
||||
- Рабочий `config.json` каждой цели и `requisites.html` живут на хостинге: не добавлять
|
||||
их в git, не перезаписывать и не удалять при деплое. В репозитории — только образец конфига.
|
||||
- Рабочий `config.json` единственный для всех прилендов: это точная проверенная
|
||||
конфигурация `zoomstage.online`, и каждый FTP/SFTP-deploy обязан доставлять её на
|
||||
stage и production. `requisites.html` по-прежнему живёт только на хостинге и не
|
||||
перезаписывается. Не создавать target-specific конфиги или `config.json.example`.
|
||||
- Коммит в `main` запускает FTP-автодеплой на все цели workflow; откат через `git revert`
|
||||
также запускает выкат. Коммит, push и изменения хостинга — только по прямому поручению.
|
||||
- Проверки кода и браузера проводить в Docker без установки ПО на хост.
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
| `requisites.html` | реквизиты для подвала (HTML), если в `config.json` нет `requisites`. Без обоих — **заглушка «ИП Иванов Иван Иванович»** из `template.php` |
|
||||
| `images/`, `fonts/`, `favicon/`, `*.css` | статика; `style.min.css` встраивается в страницу |
|
||||
| `.htaccess` | только сроки кэширования статики (Apache) |
|
||||
| `config.json.example` | образец конфига; рабочий `config.json` в git не хранится |
|
||||
| `config.json` | единственный версионируемый рабочий конфиг всех прилендов: точная проверенная конфигурация stage `zoomstage.online`; каждый deploy доставляет его на целевой хост |
|
||||
|
||||
### `config.json`
|
||||
|
||||
@@ -87,12 +87,10 @@
|
||||
git clone http://git.dira89kv.beget.tech:3000/anton/preland.git && cd preland
|
||||
# дальше — загрузка на хостинг: rsync/scp по SSH или FTP-клиент
|
||||
```
|
||||
3. **Конфиг и реквизиты.** На сервере, рядом с `index.php`; реквизиты — ключ `requisites` (иначе в подвале заглушка):
|
||||
```bash
|
||||
cp config.json.example config.json # host — домен сайта, метки — по кампании
|
||||
```
|
||||
`config.json` не в git: при обновлении файлов **не удалять** его (не синхронизировать каталог «зеркалом» без
|
||||
исключения `config.json`). 2026-10-05 после заливки он пропал, и преленд слал загрузку на собственный домен.
|
||||
3. **Конфиг и реквизиты.** Рабочий `config.json` уже лежит в репозитории и обязателен к доставке на каждый
|
||||
приленд. Его не заменяют локальным вариантом и не исключают из синхронизации. Реквизиты задаются ключом
|
||||
`requisites` в нём либо runtime-файлом `requisites.html`. 2026-10-05 конфиг пропал после заливки,
|
||||
и преленд слал загрузку на собственный домен; это больше не допускается.
|
||||
4. **nginx без Apache** (если хостинг не обрабатывает `.htaccess`):
|
||||
```nginx
|
||||
server {
|
||||
@@ -139,14 +137,13 @@
|
||||
1. Домен и HTTPS — как в «Деплой на произвольный домен», шаг 1.
|
||||
2. Секреты `<ПРЕФИКС>_FTP_HOST`, `<ПРЕФИКС>_FTP_USER`, `<ПРЕФИКС>_FTP_PASS` (Gitea → настройки репозитория →
|
||||
Actions → секреты; порт 21, FTP с TLS). В коде реквизитов нет.
|
||||
3. На хостинге, в каталоге сайта, — `config.json` из `config.json.example`: свой `host`, метки, `requisites`.
|
||||
В репозитории только образец: `config.json` у каждого домена свой и живёт на его хостинге.
|
||||
4. Запись в `matrix` — коммит в `main`, автодеплой выкатит все цели. Пока на новом хостинге нет `config.json`,
|
||||
его проверка падает: загрузка ушла бы на сам преленд.
|
||||
3. Никаких ручных конфигов не создавать: единственный `config.json` приезжает вместе с кодом.
|
||||
4. Запись в `matrix` — коммит в `main`, автодеплой выкатит все цели вместе с конфигом.
|
||||
|
||||
**Что заливается.** Файлы репозитория (`git ls-files`), кроме служебных (`.gitea/`, `README.md`, `.gitignore`)
|
||||
и живущих на хостинге `config.json` и `requisites.html`. На хостинге ничего не удаляется: файлы, убранные
|
||||
из репозитория, удалять вручную.
|
||||
**Что заливается.** Каждый deploy получает файлы репозитория (`git ls-files`), кроме служебных
|
||||
(`.gitea/`, `README.md`, `.gitignore`) и живущего на хостинге `requisites.html`. Единственный
|
||||
версионируемый `config.json` всегда доставляется вместе с кодом.
|
||||
На хостинге ничего не удаляется: файлы, убранные из репозитория, удалять вручную.
|
||||
|
||||
**Проверка после заливки.** На странице цели должен быть адрес загрузки на сайте, а не на самом преленде (иначе нет
|
||||
`config.json` с `host`), и переход на `claim`. Иначе прогон этой цели падает.
|
||||
|
||||
@@ -11,52 +11,52 @@
|
||||
"utm": {
|
||||
"indpic": {
|
||||
"weights": {
|
||||
"1": 0.2,
|
||||
"2": 0.3
|
||||
"1": 1,
|
||||
"2": 0
|
||||
},
|
||||
"default": "1"
|
||||
},
|
||||
"theme": {
|
||||
"weights": {
|
||||
"light": 0.5,
|
||||
"dark": 0.5
|
||||
"light": 0,
|
||||
"dark": 1
|
||||
},
|
||||
"default": "dark"
|
||||
},
|
||||
"degr": {
|
||||
"weights": {
|
||||
"1": 0.7,
|
||||
"2": 0.3
|
||||
"1": 1,
|
||||
"2": 0
|
||||
},
|
||||
"default": "1"
|
||||
},
|
||||
"registration": {
|
||||
"weights": {
|
||||
"before": 0.7,
|
||||
"after": 0.3
|
||||
"before": 0,
|
||||
"after": 1
|
||||
},
|
||||
"default": "before"
|
||||
"default": "after"
|
||||
},
|
||||
"bchoice": {
|
||||
"weights": {
|
||||
"a": 0.7,
|
||||
"b": 0.3
|
||||
"a": 1,
|
||||
"b": 0
|
||||
},
|
||||
"default": "a"
|
||||
},
|
||||
"chb": {
|
||||
"weights": {
|
||||
"a": 0.7,
|
||||
"b": 0.3
|
||||
"a": 1,
|
||||
"b": 0
|
||||
},
|
||||
"default": "a"
|
||||
"default": "b"
|
||||
},
|
||||
"tp": {
|
||||
"weights": {
|
||||
"1": 0.7,
|
||||
"2": 0.3
|
||||
"1": 0,
|
||||
"2": 1
|
||||
},
|
||||
"default": "2"
|
||||
"default": "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* Регрессия единственного рабочего конфига приленда.
|
||||
*
|
||||
* Stage-конфиг — единственный канонический конфиг каждого приленда. Он должен
|
||||
* быть в репозитории и попадать во все FTP/SFTP-доставки без исключений.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
$failures = [];
|
||||
$root = dirname(__DIR__);
|
||||
$configPath = $root . '/config.json';
|
||||
$config = is_file($configPath) ? json_decode((string) file_get_contents($configPath), true) : null;
|
||||
|
||||
if (!is_array($config)) {
|
||||
$failures[] = 'Рабочий config.json должен существовать в корне приленда и содержать валидный JSON.';
|
||||
} else {
|
||||
$expected = [
|
||||
'host' => 'zoomzilla.ru',
|
||||
'indpic' => ['1' => 1, '2' => 0, 'default' => '1'],
|
||||
'theme' => ['light' => 0, 'dark' => 1, 'default' => 'dark'],
|
||||
'degr' => ['1' => 1, '2' => 0, 'default' => '1'],
|
||||
'registration' => ['before' => 0, 'after' => 1, 'default' => 'after'],
|
||||
'bchoice' => ['a' => 1, 'b' => 0, 'default' => 'a'],
|
||||
'chb' => ['a' => 1, 'b' => 0, 'default' => 'b'],
|
||||
'tp' => ['1' => 0, '2' => 1, 'default' => '1'],
|
||||
];
|
||||
|
||||
if (($config['host'] ?? null) !== $expected['host']) {
|
||||
$failures[] = 'Рабочий config.json обязан направлять загрузку на zoomzilla.ru.';
|
||||
}
|
||||
|
||||
foreach (array_diff_key($expected, ['host' => true]) as $key => $settings) {
|
||||
$actual = $config['utm'][$key] ?? [];
|
||||
if (($actual['weights'] ?? null) !== array_diff_key($settings, ['default' => true])
|
||||
|| ($actual['default'] ?? null) !== $settings['default']) {
|
||||
$failures[] = "Рабочий config.json должен сохранять stage-настройку UTM {$key}.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$workflow = (string) file_get_contents($root . '/.gitea/workflows/deploy.yml');
|
||||
$legacyStart = strpos($workflow, ' deploy:');
|
||||
$stageStart = strpos($workflow, 'deploy-zoomstage:');
|
||||
$productionStart = strpos($workflow, 'deploy-zoompixel-production:');
|
||||
$legacyBlock = $legacyStart === false || $stageStart === false
|
||||
? ''
|
||||
: substr($workflow, $legacyStart, $stageStart - $legacyStart);
|
||||
$stageBlock = $stageStart === false || $productionStart === false
|
||||
? ''
|
||||
: substr($workflow, $stageStart, $productionStart - $stageStart);
|
||||
$productionBlock = $productionStart === false ? '' : substr($workflow, $productionStart);
|
||||
|
||||
foreach ([
|
||||
'legacy FTP' => $legacyBlock,
|
||||
'deploy-zoomstage' => $stageBlock,
|
||||
'deploy-zoompixel-production' => $productionBlock,
|
||||
] as $delivery => $block) {
|
||||
if ($block === '' || str_contains($block, 'config\\.json$')) {
|
||||
$failures[] = "{$delivery} обязан доставлять единый версионируемый config.json.";
|
||||
}
|
||||
}
|
||||
|
||||
if (is_file($root . '/config.json.example')) {
|
||||
$failures[] = 'config.json.example не должен существовать: рабочий config.json единственный.';
|
||||
}
|
||||
|
||||
if ($failures !== []) {
|
||||
fwrite(STDERR, "FAILED\n- " . implode("\n- ", $failures) . "\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fwrite(STDOUT, "OK: versioned stage config and ZoomPixel delivery\n");
|
||||
Reference in new issue
Block a user