Обзор пакетов
Этот монорепозиторий содержит два основных пакета: @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.
Типы релизов
Проект поддерживает несколько типов релизов:
Стабильные релизы (Stable)
Обычные стабильные релизы для использования в production.
Превью-релизы (Preview)
Еженедельные превью-релизы каждый вторник в 23:59 UTC для раннего доступа к новым функциям.
Ночные релизы (Nightly)
Ежедневные ночные релизы в полночь UTC для тестирования самых свежих изменений в разработке.
Автоматическое расписание релизов
- Nightly: Каждый день в полночь UTC
- Preview: Каждый вторник в 23:59 UTC
- Stable: Ручные релизы, запускаемые мейнтейнерами
Как использовать разные типы релизов
Для установки последней версии каждого типа:
# Stable (default)
npm install -g @qwen-code/qwen-code
# Preview
npm install -g @qwen-code/qwen-code@preview
# Nightly
npm install -g @qwen-code/qwen-code@nightlyДетали процесса релиза
Каждый запланированный или ручной релиз проходит следующие этапы:
- Получает указанный код (последний из ветки
mainили конкретный коммит). - Устанавливает все зависимости.
- Запускает полный набор проверок
preflightи интеграционных тестов. - Если все тесты проходят успешно, вычисляется соответствующий номер версии в зависимости от типа релиза.
- Собирает и публикует пакеты в npm с соответствующим dist-tag.
- Создает GitHub Release для данной версии.
Обработка ошибок
Если какой-либо шаг workflow релиза завершается ошибкой, в репозитории автоматически создается новый issue с метками bug и специфичной для типа релиза меткой ошибки (например, nightly-failure, preview-failure). В issue будет содержаться ссылка на неудачный запуск workflow для упрощения отладки.
Валидация релиза
После публикации нового релиза необходимо провести smoke-тестирование, чтобы убедиться, что пакеты работают корректно. Для этого установите пакеты локально и запустите набор тестов для проверки их работоспособности.
npx -y @qwen-code/qwen-code@latest --versionдля проверки успешности публикации, если вы не использовали тегиrcилиdevnpx -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-тестирование, выполнив несколько команд и инструментов LLM, чтобы убедиться в корректной работе пакетов. В будущем мы формализуем этот процесс.
Когда нужно мержить изменение версии, а когда нет?
Описанный выше паттерн создания патчей или хотфиксов на основе текущих или старых коммитов оставляет репозиторий в следующем состоянии:
- Тег (
vX.Y.Z-patch.1): Этот тег корректно указывает на исходный коммит вmain, содержащий стабильный код, который вы планировали выпустить. Это критически важно. Любой, кто сделает checkout этого тега, получит именно тот код, который был опубликован. - Ветка (
release-vX.Y.Z-patch.1): Эта ветка содержит один новый коммит поверх тегированного. Этот коммит включает только изменение номера версии вpackage.json(и других связанных файлах, напримерpackage-lock.json).
Такое разделение полезно. Оно сохраняет историю ветки main чистой от специфичных для релиза изменений версии до тех пор, пока вы не решите их смержить.
Это ключевое решение, которое полностью зависит от типа релиза.
Мерж обратно для стабильных патчей и хотфиксов
Для любого стабильного патча или хотфикса ветку 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с последней выпущенной версией.
НЕ мержить обратно для пре-релизов (RC, Beta, Dev)
Ветки релизов для пре-релизов обычно не мержат обратно в main.
- Зачем? Пре-релизные версии (например,
v1.3.0-rc.1,v1.3.0-rc.2) по определению нестабильны и носят временный характер. Не стоит засорять историю веткиmainсерией изменений версии для релиз-кандидатов.package.jsonвmainдолжен отражать последнюю стабильную версию, а не RC. - Процесс: Создается ветка
release-v1.3.0-rc.1, выполняетсяnpm publish --tag rc, и на этом ветка выполняет свою задачу. Вы можете просто удалить её. Код для RC уже находится вmain(или в feature-ветке), поэтому функциональный код не теряется. Ветка релиза служила лишь временным носителем для номера версии.
Локальное тестирование и валидация: изменения в процессе упаковки и публикации
Если вам нужно протестировать процесс релиза без фактической публикации в NPM или создания публичного GitHub Release, вы можете запустить workflow вручную через интерфейс GitHub.
- Перейдите на вкладку Actions репозитория.
- Нажмите на выпадающий список “Run workflow”.
- Оставьте опцию
dry_runвключенной (true). - Нажмите кнопку “Run workflow”.
Это запустит весь процесс релиза, но пропустит шаги npm publish и gh release create. Вы можете изучить логи workflow, чтобы убедиться, что всё работает корректно.
Крайне важно тестировать любые изменения в процессе упаковки и публикации локально перед коммитом. Это гарантирует корректную публикацию пакетов и их ожидаемую работу после установки пользователем.
Для валидации изменений вы можете выполнить dry run процесса публикации. Это симулирует публикацию без фактической отправки пакетов в реестр 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).
Выполняя dry run, вы можете быть уверены, что ваши изменения в процессе упаковки корректны и пакеты будут успешно опубликованы.
Детальный разбор процесса релиза
Основная цель процесса релиза — взять исходный код из директории packages/, собрать его и сформировать чистый, самодостаточный пакет во временной директории dist в корне проекта. Именно содержимое директории dist публикуется в 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: Бандлинг и сборка финального пакета для публикации
Это самый важный этап, на котором файлы перемещаются и преобразуются в финальное состояние для публикации. Процесс использует современные техники бандлинга для создания итогового пакета.
-
Создание бандла:
- Что происходит: Скрипт
prepare-package.jsсоздает чистый дистрибутив в директорииdist. - Ключевые преобразования:
- Копирует
README.mdиLICENSEвdist/ - Копирует папку
localesдля поддержки интернационализации - Создает чистый
package.jsonдля дистрибутива только с необходимыми зависимостями - Минимизирует зависимости дистрибутива (без бандлинга runtime-зависимостей)
- Сохраняет опциональные зависимости для
node-pty
- Копирует
- Что происходит: Скрипт
-
Создание JavaScript-бандла:
- Что происходит: Собранный JavaScript из
packages/core/distиpackages/cli/distбандлится в один исполняемый JS-файл с помощьюesbuild. - Расположение файла:
dist/cli.js - Зачем: Это создает единый оптимизированный файл, содержащий весь необходимый код приложения. Это упрощает пакет, устраняя необходимость в сложном разрешении зависимостей во время установки.
- Что происходит: Собранный JavaScript из
-
Копирование статических и вспомогательных файлов:
- Что происходит: Важные файлы, не являющиеся частью исходного кода, но необходимые для корректной работы или описания пакета, копируются в директорию
dist. - Перемещение файлов:
- README.md -> dist/README.md
- LICENSE -> dist/LICENSE
- locales/ -> dist/locales/
- Vendor-файлы -> dist/vendor/
- Зачем:
README.mdиLICENSE— стандартные файлы, которые должны включаться в любой NPM-пакет.localesподдерживает функции интернационализации- Vendor-файлы содержат необходимые runtime-зависимости
- Что происходит: Важные файлы, не являющиеся частью исходного кода, но необходимые для корректной работы или описания пакета, копируются в директорию
Этап 4: Публикация в NPM
- Что происходит: Команда
npm publishвыполняется из корневой директорииdist. - Зачем: Запуск
npm publishиз директорииdistгарантирует, что в реестр NPM будут загружены только файлы, тщательно собранные на Этапе 3. Это предотвращает случайную публикацию исходного кода, тестов или конфигураций для разработки, обеспечивая чистый и минимальный пакет для пользователей.
Этот процесс гарантирует, что финальный опубликованный артефакт представляет собой специально подготовленное, чистое и эффективное представление проекта, а не прямую копию рабочей среды разработки.
NPM Workspaces
В этом проекте используются NPM Workspaces для управления пакетами внутри монорепозитория. Это упрощает разработку, позволяя управлять зависимостями и запускать скрипты для нескольких пакетов из корня проекта.
Как это работает
Корневой файл package.json определяет workspaces для этого проекта:
{
"workspaces": ["packages/*"]
}Это указывает NPM, что любая папка внутри директории packages является отдельным пакетом, который должен управляться как часть workspace.
Преимущества Workspaces
- Упрощенное управление зависимостями: Запуск
npm installиз корня проекта установит все зависимости для всех пакетов в workspace и свяжет их между собой. Это означает, что вам не нужно запускатьnpm installв директории каждого пакета. - Автоматическое связывание: Пакеты внутри workspace могут зависеть друг от друга. При запуске
npm installNPM автоматически создаст символические ссылки между пакетами. Это означает, что при внесении изменений в один пакет они сразу становятся доступны другим пакетам, которые от него зависят. - Упрощенный запуск скриптов: Вы можете запускать скрипты любого пакета из корня проекта, используя флаг
--workspace. Например, для запуска скриптаbuildв пакетеcliвыполнитеnpm run build --workspace @qwen-code/qwen-code.