Обзор пакета
Этот монорепозиторий содержит два основных пакета: @qwen-code/qwen-code
и @qwen-code/qwen-code-core
.
@qwen-code/qwen-code
Это основной пакет для Qwen Code. Он отвечает за пользовательский интерфейс, парсинг команд и весь другой функционал, с которым взаимодействует пользователь.
При публикации этот пакет собирается в один исполняемый файл. В этот бандл включены все зависимости пакета, включая @qwen-code/qwen-code-core
. Это означает, что независимо от того, устанавливает ли пользователь пакет с помощью npm install -g @qwen-code/qwen-code
или запускает его напрямую через npx @qwen-code/qwen-code
, он использует этот единственный, самодостаточный исполняемый файл.
@qwen-code/qwen-code-core
Этот пакет содержит основную логику для CLI. Он отвечает за выполнение API-запросов к настроенным провайдерам, обработку аутентификации и управление локальным кэшем.
Этот пакет не собирается в бандл. При публикации он выпускается как стандартный Node.js пакет со своими собственными зависимостями. Это позволяет использовать его как отдельный пакет в других проектах, если это необходимо. Весь транспилированный js-код в папке dist
включается в пакет.
Процесс релиза
Этот проект следует структурированному процессу релиза, чтобы гарантировать правильную версионность и публикацию всех пакетов. Процесс максимально автоматизирован.
Как выполнить релиз
Релизы управляются через GitHub Actions workflow release.yml . Чтобы выполнить ручной релиз патча или хотфикса:
- Перейдите на вкладку Actions репозитория.
- Выберите workflow Release из списка.
- Нажмите кнопку Run workflow.
- Заполните необходимые поля:
- Version: точная версия для релиза (например,
v0.2.1
). - Ref: ветка или SHA коммита, из которого будет выполнен релиз (по умолчанию —
main
). - Dry Run: оставьте
true
, чтобы протестировать workflow без публикации, или установитеfalse
, чтобы выполнить настоящий релиз.
- Version: точная версия для релиза (например,
- Нажмите Run workflow.
Ночные релизы
В дополнение к ручным релизам, в проекте настроен автоматический процесс ночных релизов, предоставляющий последнюю “bleeding edge” версию для тестирования и разработки.
Процесс
Каждую ночь в 00:00 UTC автоматически запускается Release workflow . Он выполняет следующие шаги:
- Получает последний код из ветки
main
. - Устанавливает все зависимости.
- Запускает полный набор проверок
preflight
и интеграционных тестов. - Если все тесты пройдены успешно, вычисляет номер следующей nightly-версии (например,
v0.2.1-nightly.20230101
). - Затем собирает и публикует пакеты в npm с dist-tag
nightly
. - Наконец, создает GitHub Release для nightly-версии.
Обработка ошибок
Если какой-либо шаг в nightly workflow завершится с ошибкой, автоматически будет создан новый issue в репозитории с метками bug
и nightly-failure
. В issue будет добавлена ссылка на неудачный запуск workflow для упрощения отладки.
Как использовать Nightly Build
Чтобы установить последнюю nightly-сборку, используйте тег @nightly
:
npm install -g @qwen-code/qwen-code@nightly
Мы также запускаем Google Cloud Build под названием release-docker.yml, который публикует sandbox Docker-образ, соответствующий вашему релизу. После настройки разрешений для service account, этот процесс также будет перенесён в GitHub и объединён с основным release-файлом.
После релиза
После успешного завершения workflow вы можете отслеживать его выполнение во вкладке GitHub Actions . После завершения необходимо:
- Перейти на страницу pull requests репозитория.
- Создать новый pull request из ветки
release/vX.Y.Z
в веткуmain
. - Проверить pull request (он должен содержать только обновления версий в файлах
package.json
) и выполнить слияние (merge). Это позволит поддерживать актуальную версию в веткеmain
.
Валидация релиза
После пуша нового релиза необходимо провести smoke testing, чтобы убедиться, что пакеты работают корректно. Это можно сделать, установив пакеты локально и запустив набор тестов для проверки их функциональности.
npx -y @qwen-code/qwen-code@latest --version
— проверка, что пуш прошёл успешно (если вы не использовали теги rc или dev)npx -y @qwen-code/qwen-code@<release tag> --version
— проверка корректности запушенного тега- Это действие разрушительно для локальной среды:
npm uninstall @qwen-code/qwen-code && npm uninstall -g @qwen-code/qwen-code && npm cache clean --force && npm install @qwen-code/qwen-code@<version>
- Рекомендуется выполнить smoke testing, запустив базовые команды и инструменты LLM, чтобы убедиться, что пакеты работают как ожидается. В будущем мы формализуем этот процесс.
Когда сливать изменения версии, а когда нет?
Описанный выше подход к созданию патч-релизов или hotfix-релизов из текущих или старых коммитов оставляет репозиторий в следующем состоянии:
- Тег (
vX.Y.Z-patch.1
): Этот тег правильно указывает на оригинальный коммит в ветке main, который содержит стабильный код, предназначенный для релиза. Это важно. Любой, кто сделает checkout этого тега, получит точную копию опубликованного кода. - Ветка (
release-vX.Y.Z-patch.1
): Эта ветка содержит один новый коммит поверх коммита с тегом. Этот новый коммит содержит только изменение номера версии в package.json (и других связанных файлах, таких как package-lock.json).
Такое разделение полезно. Оно позволяет сохранить историю основной ветки main без лишних коммитов с изменениями версий, пока вы явно не решите их слить.
Это ключевое решение, и оно полностью зависит от характера релиза.
Merge Back для стабильных патчей и хотфиксов
Почти всегда нужно мержить ветку release-<tag>
обратно в main
для любого
стабильного патча или хотфикса.
- Зачем? Основная причина — обновление версии в package.json ветки main. Если вы делаете релиз v1.2.1 из старого коммита, но никогда не мержите изменение версии обратно, то package.json в вашей ветке main всё ещё будет содержать “version”: “1.2.0”. Следующий разработчик, который начнёт работу над следующим фичерелизом (v1.3.0), будет создавать ветку от кодовой базы с некорректной, устаревшей версией. Это вызывает путаницу и требует ручного обновления версии позже.
- Процесс: После создания ветки release-v1.2.1 и успешной публикации пакета вы должны открыть pull request для мержа release-v1.2.1 в main. Этот PR будет содержать всего один коммит: “chore: bump version to v1.2.1”. Это чистая и простая интеграция, которая поддерживает вашу ветку main в актуальном состоянии с последней выпущенной версией.
НЕ выполняйте Merge Back для предварительных релизов (RC, Beta, Dev)
Обычно вы не выполняете слияние веток релизов для предварительных релизов обратно в main
.
- Почему? Предварительные версии (например, v1.3.0-rc.1, v1.3.0-rc.2) по определению не являются стабильными и временными. Вы не хотите засорять историю своей основной ветки серией изменений версий для релиз-кандидатов. package.json в main должен отражать последнюю стабильную версию релиза, а не RC.
- Процесс: Создается ветка release-v1.3.0-rc.1, происходит npm publish —tag rc, и затем… ветка выполнила свою задачу. Вы можете просто удалить ее. Код для RC уже находится в main (или в feature-ветке), поэтому функциональный код не теряется. Ветка релиза была лишь временным средством для номера версии.
Локальное тестирование и валидация: изменения в процессе упаковки и публикации
Если вам нужно протестировать процесс релиза без фактической публикации в NPM или создания публичного релиза на GitHub, вы можете запустить workflow вручную через GitHub UI.
- Перейдите на вкладку Actions репозитория.
- Нажмите на выпадающий список “Run workflow”.
- Оставьте опцию
dry_run
включенной (true
). - Нажмите кнопку “Run workflow”.
Это запустит весь процесс релиза, но пропустит шаги npm publish
и gh release create
. Вы можете изучить логи workflow, чтобы убедиться, что всё работает как ожидается.
Крайне важно тестировать любые изменения в процессе упаковки и публикации локально перед коммитом. Это гарантирует, что пакеты будут опубликованы корректно и будут работать должным образом при установке пользователем.
Чтобы проверить ваши изменения, вы можете выполнить пробный запуск процесса публикации. Это симулирует процесс публикации, но не будет отправлять пакеты в реестр npm.
npm_package_version=9.9.9 SANDBOX_IMAGE_REGISTRY="registry" SANDBOX_IMAGE_NAME="thename" npm run publish:npm --dry-run
Эта команда выполнит следующее:
- Соберет все пакеты.
- Выполнит все prepublish скрипты.
- Создаст tar-архивы пакетов, которые были бы опубликованы в npm.
- Выведет сводку по пакетам, которые были бы опубликованы.
После этого вы можете проверить сгенерированные tar-архивы, чтобы убедиться, что они содержат правильные файлы и что package.json
обновлены корректно. Архивы будут созданы в корневой директории каждого пакета (например, packages/cli/qwen-code-0.1.6.tgz
).
Выполнив пробный запуск, вы можете быть уверены, что ваши изменения в процессе упаковки корректны и что пакеты будут успешно опубликованы.
Подробное описание процесса релиза
Основная цель процесса релиза — взять исходный код из директории packages/
, собрать его и создать чистый, самодостаточный пакет во временной директории bundle
в корне проекта. Именно содержимое этой директории bundle
публикуется в NPM.
Вот ключевые этапы:
Этап 1: Предварительные проверки и версионирование
- Что происходит: Перед перемещением любых файлов система убеждается, что проект находится в рабочем состоянии. Это включает запуск тестов, линтинга и проверки типов (
npm run preflight
). Номер версии в корневомpackage.json
и вpackages/cli/package.json
обновляется до новой версии релиза. - Зачем: Это гарантирует, что в релиз попадает только качественный и рабочий код. Версионирование — первый шаг, обозначающий новый релиз.
Этап 2: Сборка исходного кода
- Что происходит: Исходный код на TypeScript из
packages/core/src
иpackages/cli/src
компилируется в JavaScript. - Перемещение файлов:
packages/core/src/**/*.ts
→ компилируется в →packages/core/dist/
packages/cli/src/**/*.ts
→ компилируется в →packages/cli/dist/
- Зачем: Код на TypeScript, написанный во время разработки, должен быть преобразован в обычный JavaScript, который может выполнить Node.js. Сначала собирается
core
пакет, потому чтоcli
зависит от него.
Этап 3: Формирование финального пакета для публикации
Это самый критичный этап, на котором файлы перемещаются и преобразуются в финальный вид для публикации. Во временной директории bundle
в корне проекта формируется содержимое финального пакета.
1. Преобразование package.json
:
- Что происходит:
package.json
изpackages/cli/
считывается, модифицируется и записывается в директориюbundle/
. - Перемещение файла:
packages/cli/package.json
→ (внутреннее преобразование) →bundle/package.json
- Зачем: Финальный
package.json
должен отличаться от того, что используется в разработке. Основные изменения:- Удаление
devDependencies
. - Удаление зависимостей вида
"@qwen-code/core": "workspace:*"
и включение кодаcore
напрямую в финальный JS-файл. - Поля
bin
,main
иfiles
должны указывать на правильные пути внутри финальной структуры пакета.
- Удаление
2. Создание бандла JavaScript:
- Что происходит: Скомпилированный JavaScript из
packages/core/dist
иpackages/cli/dist
объединяется в один исполняемый JS-файл. - Перемещение файла:
packages/cli/dist/index.js
+packages/core/dist/index.js
→ (бандлится через esbuild) →bundle/gemini.js
(или аналогичное имя). - Зачем: Это создаёт один оптимизированный файл со всем необходимым кодом приложения. Это упрощает пакет, так как
core
больше не нужен как отдельная зависимость в NPM — его код теперь встроен напрямую.
3. Копирование статических и вспомогательных файлов:
- Что происходит: Необходимые файлы, не являющиеся частью исходного кода, но важные для работы пакета или его описания, копируются в директорию
bundle
. - Перемещение файлов:
README.md
→bundle/README.md
LICENSE
→bundle/LICENSE
packages/cli/src/utils/*.sb
(профили песочницы) →bundle/
- Зачем:
README.md
иLICENSE
— стандартные файлы, которые должны присутствовать в любом NPM-пакете.- Профили песочницы (
.sb
файлы) — критически важные рантайм-ресурсы для работы функции sandboxing в CLI. Они должны находиться рядом с финальным исполняемым файлом.
Этап 4: Публикация в NPM
- Что происходит: Команда
npm publish
запускается из директорииbundle
. - Зачем: Запуская
npm publish
изbundle
, мы публикуем только те файлы, которые были тщательно собраны на этапе 3. Это предотвращает случайную публикацию исходного кода, тестов или конфигураций разработки, обеспечивая чистый и минималистичный пакет для пользователей.
Схема потока файлов
Этот процесс гарантирует, что финальный опубликованный артефакт — это специально подготовленный, чистый и эффективный пакет, а не прямая копия рабочей среды разработки.
NPM Workspaces
Этот проект использует NPM Workspaces для управления пакетами в этом монорепозитории. Это упрощает разработку, позволяя управлять зависимостями и запускать скрипты в нескольких пакетах из корня проекта.
Как это работает
Корневой файл package.json
определяет рабочие области (workspaces) для этого проекта:
{
"workspaces": ["packages/*"]
}
Это указывает NPM, что любая папка внутри директории packages
является отдельным пакетом, который должен управляться как часть workspace.
Преимущества Workspaces
- Упрощенное управление зависимостями: Запуск
npm install
из корня проекта установит все зависимости для всех пакетов в workspace и свяжет их между собой. Это означает, что вам не нужно запускатьnpm install
в каждой директории пакета. - Автоматическая линковка: Пакеты в рамках workspace могут зависеть друг от друга. При запуске
npm install
NPM автоматически создаст symlinks между пакетами. Это значит, что при внесении изменений в один пакет, они сразу становятся доступны другим пакетам, которые от него зависят. - Упрощенный запуск скриптов: Вы можете запускать скрипты из любого пакета из корня проекта, используя флаг
--workspace
. Например, чтобы запустить скриптbuild
из пакетаcli
, выполните командуnpm run build --workspace @qwen-code/qwen-code
.