Skip to Content
Управление Пакетами

Обзор пакета

Этот монорепозиторий содержит два основных пакета: @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 . Чтобы выполнить ручной релиз патча или хотфикса:

  1. Перейдите на вкладку Actions репозитория.
  2. Выберите workflow Release из списка.
  3. Нажмите кнопку Run workflow.
  4. Заполните необходимые поля:
    • Version: точная версия для релиза (например, v0.2.1).
    • Ref: ветка или SHA коммита, из которого будет выполнен релиз (по умолчанию — main).
    • Dry Run: оставьте true, чтобы протестировать workflow без публикации, или установите false, чтобы выполнить настоящий релиз.
  5. Нажмите Run workflow.

Ночные релизы

В дополнение к ручным релизам, в проекте настроен автоматический процесс ночных релизов, предоставляющий последнюю “bleeding edge” версию для тестирования и разработки.

Процесс

Каждую ночь в 00:00 UTC автоматически запускается Release workflow . Он выполняет следующие шаги:

  1. Получает последний код из ветки main.
  2. Устанавливает все зависимости.
  3. Запускает полный набор проверок preflight и интеграционных тестов.
  4. Если все тесты пройдены успешно, вычисляет номер следующей nightly-версии (например, v0.2.1-nightly.20230101).
  5. Затем собирает и публикует пакеты в npm с dist-tag nightly.
  6. Наконец, создает 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 . После завершения необходимо:

  1. Перейти на страницу pull requests  репозитория.
  2. Создать новый pull request из ветки release/vX.Y.Z в ветку main.
  3. Проверить 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-релизов из текущих или старых коммитов оставляет репозиторий в следующем состоянии:

  1. Тег (vX.Y.Z-patch.1): Этот тег правильно указывает на оригинальный коммит в ветке main, который содержит стабильный код, предназначенный для релиза. Это важно. Любой, кто сделает checkout этого тега, получит точную копию опубликованного кода.
  2. Ветка (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.

  1. Перейдите на вкладку Actions  репозитория.
  2. Нажмите на выпадающий список “Run workflow”.
  3. Оставьте опцию dry_run включенной (true).
  4. Нажмите кнопку “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

Эта команда выполнит следующее:

  1. Соберет все пакеты.
  2. Выполнит все prepublish скрипты.
  3. Создаст tar-архивы пакетов, которые были бы опубликованы в npm.
  4. Выведет сводку по пакетам, которые были бы опубликованы.

После этого вы можете проверить сгенерированные 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.mdbundle/README.md
    • LICENSEbundle/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.
Last updated on