Обновление DWE
Новая версия DWE может изменить то, как загружается ваш проект, что делает шаг пайплайна или что печатает команда. Большинство релизов не требуют от вас ничего; некоторые — требуют. Эта страница — короткий список того, что ломается и что с этим делать, начиная с самого свежего релиза.
Это сознательно не список изменений — им является CHANGELOG.md, где записано каждое изменение. Здесь только те, ради которых вам придётся что-то править.
Обновите бинарник
Заголовок раздела «Обновите бинарник»Как бы вы его ни ставили:
brew upgrade semsemyonoff/tap/dwe # HomebrewИначе скачайте архив под свою платформу со страницы релизов и замените бинарник в $PATH. Способы установки перечислены в README.
DWE не обновляет сам себя. Блок update: в workspace.yml к этому отношения не имеет — он управляет git-пробой по репозиторию вашего проекта, а не бинарником DWE.
После обновления, в любом проекте
Заголовок раздела «После обновления, в любом проекте»Три вещи, которые стоит сделать, прежде чем доверять новой версии в проекте:
-
Сначала запустите
dwe validate. Он ничего не деплоит и не поднимает ни один сервис, поэтому удалённый ключ конфига всплывёт именованной диагностикой, а не упавшим деплоем. Проект, который вообще перестал загружаться, отрапортует одну ошибку с именем ключа. (При этом он выполняет собственныеchecks.*проекта, а это могут быть командыshellилиscript: предполагается, что они идемпотентная инспекция, но CLI этого не гарантирует.) -
Перезапустите host-bridge, если проект им пользуется. Демон bridge исполняет тот бинарник, которым был запущен, поэтому после обновления на хосте контейнерный
dweпродолжает работать по старой версии, пока демон не заменён:Окно терминала dwe bridge stop && dwe bridge startdwe bridge statusпоказывает работающий демон;dwe versionизнутри контейнера с bridge — сборку, которой он отвечает. -
Сделайте принудительный передеплой, если это сказано в релизных заметках. Изменение поведения, не меняющее хеш деплоя, невидимо для
dwe deploy run: он отрапортуетalready up-to-dateи пропустит ровно тот шаг, семантика которого сдвинулась.dwe deploy run --forceперезапускает все шаги; условияwhen:при этом продолжают действовать.
Обновление до 0.7.1
Заголовок раздела «Обновление до 0.7.1»В существующем проекте ничего менять не нужно: dwe init и его ai-пак по умолчанию больше не создают CLAUDE.md, а проект остаётся с тем паком, с которым был создан. Claude Code читает AGENTS.md сам, а CLAUDE.md, .claude/CLAUDE.md или CLAUDE.local.md в рабочем каталоге или выше заставляют его пропускать все AGENTS.md. Чтобы убрать ссылки из старого проекта, сделайте всё сразу:
- Удалите корневой симлинк
CLAUDE.mdи записьsymlinks:дляCLAUDE.mdиз каждогоworkspace/templates/ai/*/manifest.yml. - Удалите симлинки
services/*/CLAUDE.mdвручную на каждой машине — рендер не удаляет вывод, который больше не объявлен. - Сервисный репозиторий со своим
CLAUDE.mdпо-прежнему подавляетAGENTS.mdвнутри себя, включая корневойAGENTS.mdпроекта. Переименуйте его вAGENTS.mdили выставьте в Claude Code Project instructions =claude-md-and-agents-md(/config). symlink_fallbackвdwe init --output jsonтеперь всегдаfalseи будет удалён в следующем минорном релизе.
Обновление до 0.7.0
Заголовок раздела «Обновление до 0.7.0»В существующем проекте ничего менять не нужно. Одно нужно согласовать:
- Workspace с новым корневым ключом
render:требует 0.7.0 на каждой машине. Старые версии отклоняют неизвестный ключ, поэтомуdweне загружает проект — как и любой git-хук или команда, которые вызываютdwe. Обновите всех до того, как закоммититьrender.workspaceв репозиторий workspace.
Обновление до 0.6.3
Заголовок раздела «Обновление до 0.6.3»В проекте ничего менять не нужно, повторный деплой не требуется. Изменились три вещи:
- Баннер
dwe cmdвыводится в stderr. Строка▶ <id> [<type>] <description>раньше открывала stdout команды; скрипт, который пропускал или разбирал эту первую строку, теперь получает только вывод самой команды, а с--output jsonбаннер не печатается вовсе. Кроме того, баннер показывает только первую строку многострочногоdescription:. dwe validateможет сообщить о новых находках в существующем проекте:hide:, который не вычисляется; отсутствующий файл изcompose:/compose_after:/compose.base; команда, чейservice:не называет ни одного compose-сервиса; info-заметка о блокеhealthcheck:в активной compose-цепочке безstart_period(собственныйHEALTHCHECKобраза не проверяется). Они указывают на ошибки, которые были и раньше. Ни одна из этих проверок не входит в preflight, поэтому lifecycle-команды они не блокируют.dwe compose argvбольше не читает флаги dwe после compose-команды.dwe compose argv exec app ls --allтеперь печатает--allкак часть команды; собственные флаги dwe ставьте первыми (dwe compose argv --all ps,dwe -v compose argv ps).
Обновление до 0.6.2
Заголовок раздела «Обновление до 0.6.2»Интеграционные тесты
Заголовок раздела «Интеграционные тесты»Host-порт compose, проведённый через vars:, теперь переназначается в каждой тестовой копии. Если compose-файл публикует порт одной переменной ("${VALKEY_PORT:-6379}:6379") и активное правило exports.env экспортирует эту переменную from: vars.<path>, dwe test выделяет свободный host-порт для <path> и записывает его в local.yml копии — без записи env.vars в сценарии. Раньше такой порт биндил число живого стека, а dwe validate предупреждал об этом.
Что проверить в своих сценариях:
- Шаг, в котором исходный host-порт был захардкожен, теперь обращается не туда. Читайте порт из переменной —
${vars.<path>}— или зафиксируйте порт копии строкойenv.vars: { <path>: 6380 }, которая отключает автоматическое переназначение для этого пути. - Записи
env.vars: { <path>: auto }для такого порта стали избыточными. Они продолжают работать и ничего не меняют; удалите их, когда будет удобно.autoпо-прежнему нужен для var, который не читает ни один порт compose. - Неотслеженная переменная не изменилась — нет правила
exports.env,when:правила ложен, или правило читает неvars.<path>и не объявленный порт сервиса. Она по-прежнему биндит исходный порт и по-прежнему предупреждает, но теперь предупреждение указывает на два способа провести порт (записьservices.<name>.portsили правилоexports.envfrom: vars.<path>) вместо совета написатьenv.vars: { …: auto }.
Сценарий, заблокированный сканером изоляции compose, ничего не создаёт. Скан теперь выполняется до создания копии, поэтому блокирующая находка (container_name:, буквальный host-порт) проваливает сценарий без каталога копии и без compose-проекта, и отчёт об ошибке для этого запуска не собирается — отчёт, оставшийся от более раннего провала того же сценария, остаётся на месте, так что ориентируйтесь на предупреждения самого запуска, а не на отметку времени каталога. Код выхода прежний (1). --keep в этом случае сохранять нечего.
dwe test list --output json игнорирует персональные compose-overlay’и. compose.extra / services.<name>.compose.extra из вашего workspace/local.yml ссылаются на gitignored-файлы, которых копия не получает, поэтому команда теперь вычисляет сценарии без них — так же, как их выполняет копия: числа стоимости (build_services, external_images) эти сервисы больше не учитывают, как и cost_profile.isolation_findings. dwe validate tests строит то же представление для каждого сценария, поэтому находка interpolated_host_port, существующая только в таком overlay, больше не сообщается, — а остальные виды находок (container_name, литеральный хост-порт, виды про тома и сети) по-прежнему берутся из сканирования всего проекта и предупреждают независимо от overlay’ев.
Обновление до 0.6.1
Заголовок раздела «Обновление до 0.6.1»Функции шаблонов
Заголовок раздела «Функции шаблонов»DWE переходит на go-sprout 1.1, который больше не принимает порядок аргументов Sprig. Это касается всех мест, где вычисляются шаблоны {{ … }}, — см. Шаблоны.
Десять функций теперь падают на порядке Sprig. get, set, unset, hasKey, pick, omit, append, prepend, slice и without принимают map или список последним. Раньше старый порядок молча переставлялся с предупреждением; теперь это ошибка рендера, так что она всплывёт при первом же вычислении шаблона. Перепишите вызов через пайп:
{{ hasKey $m "a" }} → {{ $m | hasKey "a" }}{{ append $list "x" }} → {{ $list | append "x" }}{{ slice $list 1 2 }} → {{ $list | slice 1 2 }}Четыре regex-функции поменяли порядок аргументов и не падают. Строка, с которой они работают, переехала на последнее место. Шаблон под старый порядок продолжает рендериться — в неверный результат:
| функция | было | стало |
|---|---|---|
regexFindAll | regexFindAll <re> <value> <n> | regexFindAll <re> <n> <value> |
regexSplit | regexSplit <re> <value> <n> | regexSplit <re> <n> <value> |
regexReplaceAll | regexReplaceAll <re> <value> <replacement> | regexReplaceAll <re> <replacement> <value> |
regexReplaceAllLiteral | regexReplaceAllLiteral <re> <value> <replacement> | regexReplaceAllLiteral <re> <replacement> <value> |
Об этом ничто не сообщит, поэтому найдите их поиском:
grep -rnE 'regex(FindAll|Split|ReplaceAll)' workspace/Поиск заодно зацепит regexFindAllGroups и regexFindAllNamed, которые не менялись, — их пропустите. Остальные regex-функции — regexMatch, regexFind, regexQuoteMeta и варианты *Groups / *Named — не изменились.
Алиасы mustRegex* удалены. mustRegexFind, mustRegexFindAll, mustRegexMatch, mustRegexSplit, mustRegexReplaceAll и mustRegexReplaceAllLiteral были deprecated; шаблон, который их вызывает, теперь не парсится. Уберите префикс must — и там, где это касается, примените новый порядок аргументов из таблицы выше.
div на ноль теперь ошибка рендера, а не произвольное число.
Платформа
Заголовок раздела «Платформа»Релизным бинарникам нужна macOS 13 Ventura или новее. Они собираются Go 1.27, который прекратил поддержку macOS 12; на более старом Mac оставайтесь на 0.6.0. Сборка из исходников требует Go 1.27.
Интеграционные тесты
Заголовок раздела «Интеграционные тесты»dwe validate предупреждает о host-портах compose, подставленных из переменной, которую dwe test не переназначает. Порт вроде "${VALKEY_PORT:-6379}:6379", где VALKEY_PORT экспортируется from: vars.ports.valkey, в каждом тестовом запуске биндит тот же host-порт, что и живой стек. Так было всегда; теперь об этом говорят dwe validate и dwe test run. Предупреждение появляется только в проектах с каталогом workspace/tests/ и проваливает dwe validate --strict. Исправьте каждый сценарий, который называет предупреждение:
env: vars: ports.valkey: autoПорт, экспортируемый from: services.<name>.ports.<x>, уже переназначается, пока этот сервис включён в сценарии; предупреждение появится только для сценария, который этот сервис выключает, но оставляет его compose-файл в стеке, — например, объявленного в корневом compose-файле. Сервис с required: true выключить нельзя, поэтому его порты переназначаются всегда и предупреждения он не даёт. См. Интерполированные host-порты.
Предупреждение без списка сценариев значит, что ни одно активное правило exports.env не прослеживает переменную — она приходит из написанного вручную .env, окружения хоста или из правила, чей when: ложен, — поэтому никакая настройка сценария её не исправит. Экспортируйте переменную from: vars.<path> и добавьте env.vars: { <path>: auto } в каждый сценарий, либо экспортируйте её from: services.<name>.ports.<x>.
Переходите сразу на 0.6.2? Шаг с env.vars: { <path>: auto } выше там уже не нужен — переменная, экспортируемая from: vars.<path>, переназначается автоматически (см. Обновление до 0.6.2).
Литеральный host-порт за интерполированным адресом привязки теперь блокирует dwe test run. "${BIND:-127.0.0.1}:8080:80" публикует литеральный host-порт 8080, который конфликтует с живым стеком; раньше сканер его пропускал. Опишите порт под services.<name>.ports и интерполируйте его, как любой литеральный host-порт, или передайте --skip-isolation-check.
dwe validate предупреждает, когда host-скрипт сам собирает имя compose-проекта. Внутри dwe test shell-шаги и скрипты получают имя копии в COMPOSE_PROJECT_NAME; скрипт, который передаёт docker compose -p "${PROJECT_PREFIX:-dwe}-${PROJECT_NAME:-myproj}", его игнорирует и обращается к живому стеку. Новое предупреждение tests.host_project_name называет файл и строку. Как и предупреждение о портах, оно появляется только в проектах с каталогом workspace/tests/ и проваливает dwe validate --strict. Оставьте старое выражение как fallback:
PROJECT="${COMPOSE_PROJECT_NAME:-${PROJECT_PREFIX:-dwe}-${PROJECT_NAME:-myproj}}"Что проверка читает и что пропускает — см. Host-скрипты, которые сами собирают имя compose-проекта.
Встроенный пайплайн деплоя теперь снова поднимает остановленный стек. Его шаг up несёт check: {type: builtin, cmd: containers_running}, поэтому выполняется на каждом деплое, а не пропускается журналом после первого успеха. Поэтому встроенный пайплайн больше никогда не сообщает already up-to-date: деплой неизменённого запущенного проекта — это быстрый docker up --wait плюс проверка.
Первый деплой после обновления один раз видит изменение конфига. check: входит в хеш конфига проекта, поэтому проект, задеплоенный встроенным пайплайном, больше не совпадает со своим записанным хешем. Интерактивный dwe deploy run один раз покажет селектор Deployed config changed. Choose action: — выберите Apply changes. Неинтерактивный деплой применит изменение без вопросов. В обоих случаях шаги уровня проекта (up, info, сообщение об успехе) выполнятся один раз; шаги сервисов это не затрагивает.
Извлечённый через eject или написанный вручную workspace/deploy.yml сохраняет старое поведение. Он целиком заменяет встроенный пайплайн, поэтому его шаг docker up по-прежнему без check: и по-прежнему пропускается после записи в журнал. Чтобы получить исправление, добавьте тот же check — это вызовет то же разовое изменение конфига:
- name: up type: dwe cmd: "docker up --wait" check: type: builtin cmd: containers_runningЧто принимает проверка — см. containers_running.
Обновление до 0.6.0
Заголовок раздела «Обновление до 0.6.0»Три группы, в том порядке, в котором вы на них наткнётесь.
Жёсткие отказы на загрузке
Заголовок раздела «Жёсткие отказы на загрузке»Проект не загружается вообще, пока это не исправлено, и все команды сообщают одну и ту же ошибку. Первые две называют файл; третья вместо этого называет индекс правила в exports.env, потому что правило экспорта не несёт в себе исходного слоя.
Верхнеуровневый ключ state: удалён. Удалите его. Это была свободная строка с одним потребителем и без замены; свободные значения живут под vars:.
# workspace/defaults.yml — удалитьstate: ""Если что-то его читало — правило exports.env с from: state, ссылка ${state} — перенесите значение под vars: и поправьте путь либо уберите правило.
Верхнеуровневый блок ui: удалён. Удалите его. Три его настройки браузера команд замены не имеют, а сам браузер теперь работает так, как всегда разрешался отсутствующий блок: верхнеуровневые группы развёрнуты, пустые поддеревья схлопываются при фильтрации, бейджи типов включены. Хоткеи, форма параметров, лестница фолбэков и поведение мыши, которые были описаны на старой странице ui, теперь живут в разделе Интерактивный браузер в ../reference/config/commands/index.md.
COMPOSE_PROJECT_NAME стал зарезервированной переменной .env, и переобъявлять его нельзя. Правило exports.env с таким именем валит загрузку:
exports.env[3]: "COMPOSE_PROJECT_NAME" is a reserved system variable and cannot beredeclared as an export rule (reserved: PROJECT, UID, GID, COMPOSE_PROJECT_NAME)Удалите правило — DWE пишет эту строку сам. Но сначала сверьте значение, не считайте его тем же самым. Встроенное значение — это имя compose-проекта, которое DWE передаёт в -p: project_name из workspace/docker.yml, иначе <project.prefix>-<project.name>, всегда в нижнем регистре. Самодельное правило, собранное по другому выражению, давало другую строку, и всё созданное под старым именем — контейнеры, сети, тома — становится невидимым для нового. Сравните их перед удалением:
grep COMPOSE_PROJECT_NAME .env # что давало ваше правилоdwe render env | grep COMPOSE_PROJECT_NAME # что напишет DWEЕсли значения разошлись, а стек поднят, либо пропишите старое значение в project_name в workspace/docker.yml, либо примите новое имя и передеплойте один раз с нуля.
Тихие изменения поведения
Заголовок раздела «Тихие изменения поведения»Ничего не падает. Поведение стало другим.
Контейнерные команды теперь сами определяют три рантайм-дефолта. Каждый действует на свой набор типов команд:
| дефолт | действует на | новое поведение |
|---|---|---|
| workdir и user | service_exec, service_run, daemon | Без workdir: берётся cli.workdir сервиса → work_dir_internal → dir_internal — та же цепочка, что у dwe shell; workdir: internal — отказ от неё. Демон без user: наследует cli.user сервиса вместо USER из образа. |
| TTY | service_exec, service_run | Терминал в контейнере выдаётся, только если команду запустили вы сами и потоки DWE — терминалы, либо запуск идёт через bridge. Всё остальное получает -T с принудительным цветом. |
| режим exec | service_exec | mode: по умолчанию exec-or-run вместо exec-or-fail: при остановленном сервисе выполняется разовый docker compose run --rm вместо отказа. |
Что проверить: любой демон, у чьего сервиса задан cli.user — меняется владелец всего, что демон пишет, поэтому пропишите user: явно, если старый uid был важен. Любую команду, которая не должна создавать контейнер, — объявите mode: exec-or-fail. Любой check: с type: command, указывающий на service_exec-команду без mode: — теперь он создаёт контейнер, а разовый запуск идёт с --no-deps, так что такая проба может отрапортовать успех против лежащего стека.
Ни одно из трёх изменений не меняет хеш деплоя. Сделайте один dwe deploy run --force после обновления, иначе шаг со сдвинувшейся семантикой отрапортует already up-to-date и будет пропущен.
Голый docker compose из корня проекта теперь работает в проекте DWE. Сгенерированный .env несёт COMPOSE_PROJECT_NAME, а .env лежит в каталоге compose-проекта — Compose подхватывает его сам, поверх любого верхнеуровневого name: в вашем compose-файле. Это и было целью: ручной docker compose ps наконец показывает те же контейнеры, что и dwe status. Но compose-файл с расходящимся name: — то, что dwe validate сообщает как config.compose_project_name — стал мёртвой конфигурацией, и ресурсы, созданные под ним, голому compose больше не видны. Либо приведите оба к одному значению, либо впишите в compose-файл name: ${COMPOSE_PROJECT_NAME} — теперь оно резолвится.
Логи пайплайна больше не пишут каждый кадр перерисовки. Кадр, оканчивающийся на \r, придерживается и перекрывается следующим, поэтому .dwe/logs/<pipeline>.log пишет одну строку на одну завершённую строку. Следствие: tail -f .dwe/logs/deploy.log больше не показывает живой прогресс клона или скачивания, только завершённые строки. Живой вывод в терминале не изменился.
Флаги и сообщения
Заголовок раздела «Флаги и сообщения»dwe docs llms-txt --output PATH стал --out PATH. Алиаса нет: старый локальный --output затенял корневой флаг формата с тем же именем, из-за чего -o на этой команде не работал. -o json теперь принимается и игнорируется — сам документ и есть полезная нагрузка.
Изменился текст ошибки строгих загрузчиков. Неизвестное поле в пайплайне, service.yml, файле команд, манифесте, сценарии, setup.yml или бандле переводов теперь читается так:
workspace/deploy.yml:12: unknown field "defaults" — allowed here: log, phasesРаньше всплывало сообщение YAML-библиотеки field defaults not found in type config.DeployConfig. Скрипт или CI-джоба, которые грепают not found in type, нуждаются в правке.
У dwe validate появились предупреждения, способные завалить --strict. Теперь сообщается о dot-пути, который не резолвится в собранном конфиге: from: или when: у правила exports.env, а также params.<name>.default_from, params.<name>.options.from и context.<name>.from у команды. Это предупреждения — from: с default: является законным опциональным путём, а путь может жить в local.yml, которого нет на этой машине. Но dwe validate --strict считает предупреждения ошибками, поэтому CI-джоба на нём может начать падать на осознанно опциональном пути. Дайте такому правилу default: либо поправьте путь.
dwe validate заодно стал честно сообщать о встроенном пайплайне по умолчанию: пустой или полностью закомментированный deploy.yml теперь идёт как info — has no active content (all comments or empty) — built-in default pipeline is active — там, где раньше рапортовался OK. Ничего не сломано: этот файл никогда и не выполнялся. Если хотите начать править со встроенного пайплайна, dwe deploy eject --out workspace/deploy.yml --force запишет его туда закомментированным, готовым к редактированию документом.
Более ранние релизы
Заголовок раздела «Более ранние релизы»Релизы до v0.5.0 включительно появились раньше этой страницы. Их заметки — на странице релизов.
Смотрите также
Заголовок раздела «Смотрите также»CHANGELOG.md— все изменения во всех релизах, а не только ломающие- Диагностика проблем — когда стек шалит по причинам, не связанным со сменой версии
- Справочник (
reference/) — схемы и поля конфига