Skip to Content
Руководство для разработчиковDevelopmentNPM

Обзор пакетов

Этот монорепозиторий содержит два основных пакета: @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. Выберите Release workflow из списка.
  3. Нажмите на выпадающую кнопку Run workflow.
  4. Заполните необходимые поля:
    • Version: точная версия для релиза (например, v0.2.1).
    • Ref: ветка или SHA коммита, с которой делать релиз (по умолчанию main).
    • Dry Run: оставьте true, чтобы протестировать workflow без публикации, или установите false для реального релиза.
  5. Нажмите Run workflow.

Типы релизов

Проект поддерживает несколько типов релизов:

Стабильные релизы

Обычные стабильные релизы для использования в production.

Preview-релизы

Еженедельные preview-релизы каждый вторник в 23:59 UTC для раннего доступа к будущим функциям.

Nightly-релизы

Ежедневные nightly-релизы в полночь UTC для тестирования самых новых изменений.

Расписание автоматических релизов

  • Nightly: каждый день в полночь UTC
  • Preview: каждый вторник в 23:59 UTC
  • Stable: ручные релизы, инициируемые мейнтейнерами

Как использовать разные типы релизов

Чтобы установить последнюю версию каждого типа:

# Stable (по умолчанию) 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

Детали процесса релиза

Каждый запланированный или ручной релиз выполняется по следующим шагам:

  1. Выполняется checkout указанного кода (последняя версия из ветки main или конкретный коммит).
  2. Устанавливаются все зависимости.
  3. Запускается полный набор preflight проверок и интеграционных тестов.
  4. Если все тесты успешны, вычисляется соответствующий номер версии на основе типа релиза.
  5. Сборка и публикация пакетов в npm с соответствующим dist-tag.
  6. Создание GitHub Release для этой версии.

Обработка сбоев

Если какой-либо шаг workflow релиза завершается неудачей, автоматически создаётся новый issue в репозитории с метками bug и меткой сбоя, специфичной для типа (например, nightly-failure, preview-failure). Issue будет содержать ссылку на неудачный запуск workflow для упрощения отладки.

Валидация релиза

После публикации нового релиза следует выполнить smoke-тестирование, чтобы убедиться, что пакеты работают корректно. Это можно сделать, установив пакеты локально и запустив набор тестов.

  • 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-тестирование с базовым прогоном нескольких команд и инструментов LLM, чтобы убедиться, что пакеты работают ожидаемым образом. В будущем мы более формализуем этот процесс.

Когда нужно сливать изменения версии, а когда нет?

Описанный выше шаблон создания патч-релизов или хотфиксов из текущих или старых коммитов оставляет репозиторий в следующем состоянии:

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

Локальное тестирование и валидация изменений в процессе упаковки и публикации

Если вам нужно протестировать процесс релиза без фактической публикации в NPM или создания публичного GitHub Release, вы можете вручную запустить workflow из интерфейса GitHub.

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

Это запустит весь процесс релиза, но пропустит шаги npm publish и gh release create. Вы можете просмотреть логи workflow, чтобы убедиться, что всё работает ожидаемым образом.

Крайне важно тестировать любые изменения в процессе упаковки и публикации локально перед их коммитом. Это гарантирует, что пакеты будут опубликованы корректно и будут работать должным образом при установке пользователем.

Чтобы проверить ваши изменения, вы можете выполнить сухой прогон процесса публикации. Он имитирует публикацию, не отправляя пакеты в npm registry.

npm_package_version=9.9.9 SANDBOX_IMAGE_REGISTRY="registry" SANDBOX_IMAGE_NAME="thename" npm run publish:npm --dry-run

Эта команда сделает следующее:

  1. Соберёт все пакеты.
  2. Выполнит все prepublish скрипты.
  3. Создаёт tarball’ы пакетов, которые были бы опубликованы в npm.
  4. Выведет сводку пакетов, которые были бы опубликованы.

Затем вы можете проверить сгенерированные tarball’ы, чтобы убедиться, что они содержат правильные файлы и что файлы package.json обновлены корректно. Tarball’ы будут созданы в корне каждого каталога пакета (например, packages/cli/qwen-code-0.1.6.tgz).

Выполнив сухой прогон, вы можете быть уверены, что ваши изменения в процессе упаковки верны и что пакеты будут опубликованы успешно.

Глубокое погружение в процесс релиза

Основная цель процесса релиза — взять исходный код из каталога 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: Сборка (bundling) и формирование финального публикуемого пакета

Это самый важный этап, на котором файлы перемещаются и преобразуются в финальное состояние для публикации. Процесс использует современные техники сборки для создания итогового пакета.

  1. Создание бандла:

    • Что происходит: Скрипт prepare-package.js создаёт чистый дистрибутивный пакет в каталоге dist.
    • Ключевые преобразования:
      • Копирует README.md и LICENSE в dist/
      • Копирует папку locales для интернационализации
      • Создаёт чистый package.json для дистрибутива, содержащий только необходимые зависимости
      • Минимизирует зависимости дистрибутива (без встроенных runtime-зависимостей)
      • Сохраняет опциональные зависимости для node-pty
  2. Создание JavaScript-бандла:

    • Что происходит: Собранный JavaScript из packages/core/dist и packages/cli/dist объединяется в единый исполняемый JS-файл с помощью esbuild.
    • Расположение файла: dist/cli.js
    • Почему: Это создаёт единственный оптимизированный файл, содержащий весь необходимый код приложения. Это упрощает пакет, устраняя необходимость в сложном разрешении зависимостей во время установки.
  3. Копирование статических и вспомогательных файлов:

    • Что происходит: Основные файлы, которые не являются частью исходного кода, но необходимы для правильной работы пакета или его описания, копируются в каталог dist.
    • Перемещение файлов:
      • README.md -> dist/README.md
      • LICENSE -> dist/LICENSE
      • locales/ -> dist/locales/
      • Файлы вендоров -> dist/vendor/
    • Почему:
      • README.md и LICENSE — стандартные файлы, которые должны быть включены в любой NPM-пакет.
      • Locales поддерживают функции интернационализации.
      • Файлы вендоров содержат необходимые runtime-зависимости.

Этап 4: Публикация в NPM

  • Что происходит: Команда npm publish запускается из корневого каталога dist.
  • Почему: Запуская npm publish из каталога dist, мы гарантируем, что в NPM registry будут загружены только те файлы, которые мы тщательно собрали на Этапе 3. Это предотвращает случайную публикацию исходного кода, тестовых файлов или конфигураций разработки, в результате чего пользователи получают чистый и минимальный пакет.

Этот процесс гарантирует, что финальный опубликованный артефакт представляет собой целенаправленное, чистое и эффективное представление проекта, а не прямую копию рабочего пространства разработки.

NPM Workspaces

В этом проекте используются NPM Workspaces  для управления пакетами в рамках монорепозитория. Это упрощает разработку, позволяя управлять зависимостями и запускать скрипты для нескольких пакетов из корня проекта.

Как это работает

Корневой файл package.json определяет workspaces для этого проекта:

{ "workspaces": ["packages/*"] }

Это сообщает NPM, что любая папка внутри каталога packages является отдельным пакетом, который должен управляться как часть workspace.

Преимущества Workspaces

  • Упрощённое управление зависимостями: Выполнение npm install из корня проекта установит все зависимости для всех пакетов в workspace и свяжет их вместе. Это означает, что вам не нужно запускать npm install в каждом каталоге пакета.
  • Автоматическая привязка: Пакеты внутри workspace могут зависеть друг от друга. При выполнении npm install NPM автоматически создаёт симлинки между пакетами. Это означает, что когда вы вносите изменения в один пакет, эти изменения немедленно становятся доступны другим пакетам, которые от него зависят.
  • Упрощённое выполнение скриптов: Вы можете запускать скрипты в любом пакете из корня проекта, используя флаг --workspace. Например, чтобы запустить скрипт build в пакете cli, вы можете выполнить npm run build --workspace @qwen-code/qwen-code.
Last updated on