Обзор пакета
Этот монорепозиторий содержит два основных пакета: @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 со своими собственными зависимостями. Это позволяет использовать его как отдельный пакет в других проектах при необходимости. Весь транспилированный JavaScript-код из папки dist включается в пакет.
Процесс релиза
Этот проект следует структурированному процессу релиза, чтобы гарантировать правильное версионирование и публикацию всех пакетов. Процесс спроектирован так, чтобы быть максимально автоматизированным.
Как выполнить релиз
Релизы управляются через рабочий процесс GitHub Actions release.yml . Чтобы выполнить ручной релиз для патча или хотфикса:
- Перейдите на вкладку Actions репозитория.
- Выберите рабочий процесс Release из списка.
- Нажмите раскрывающуюся кнопку Run workflow.
- Заполните обязательные поля:
- Version: Точная версия для релиза (например,
v0.2.1). - Ref: Ветка или SHA коммита, из которого будет выполнен релиз (по умолчанию
main). - Dry Run: Оставьте значение
true, чтобы протестировать рабочий процесс без публикации, или установитеfalse, чтобы выполнить реальный релиз.
- Version: Точная версия для релиза (например,
- Нажмите Run workflow.
Типы релизов
Проект поддерживает несколько типов релизов:
Стабильные релизы
Обычные стабильные релизы для использования в продакшене.
Предварительные релизы
Еженедельные предварительные релизы каждую вторник в 23:59 по UTC для раннего доступа к предстоящим функциям.
Ночные сборки
Ежедневные ночные сборки в полночь по UTC для тестирования последних разработок.
Расписание автоматических выпусков
- Ночные: каждый день в полночь по UTC
- Предварительные: каждую вторник в 23:59 по UTC
- Стабильные: ручные выпуски, запускаемые сопровождающими
Как использовать различные типы выпусков
Для установки последней версии каждого типа:
# Стабильная (по умолчанию)
npm install -g @qwen-code/qwen-code
# Предварительная
npm install -g @qwen-code/qwen-code@preview
# Ночная
npm install -g @qwen-code/qwen-code@nightlyДетали процесса релиза
Каждый запланированный или ручной релиз проходит следующие шаги:
- Выполняет проверку указанного кода (последняя версия из ветки
mainили конкретный коммит). - Устанавливает все зависимости.
- Запускает полный набор проверок
preflightи интеграционных тестов. - Если все тесты пройдены успешно, вычисляется соответствующий номер версии на основе типа релиза.
- Собирает и публикует пакеты в npm с соответствующим тегом dist.
- Создает релиз на GitHub для данной версии.
Обработка сбоев
Если какой-либо шаг в рабочем процессе релиза завершается неудачно, автоматически создается новая задача (issue) в репозитории с метками bug и специфичной меткой типа сбоя (например, nightly-failure, preview-failure). В задаче будет содержаться ссылка на неудачный запуск рабочего процесса для удобства отладки.
Проверка релиза
После публикации нового релиза необходимо выполнить проверку работоспособности, чтобы убедиться, что пакеты функционируют должным образом. Это можно сделать, установив пакеты локально и запустив набор тестов для проверки их корректной работы.
npx -y @qwen-code/qwen-code@latest --version— проверить, что публикация прошла успешно (если вы не использовали тег rc или dev)npx -y @qwen-code/qwen-code@<тег релиза> --version— проверить, что нужный тег опубликован правильно- Это приведет к удалению локально
npm uninstall @qwen-code/qwen-code && npm uninstall -g @qwen-code/qwen-code && npm cache clean --force && npm install @qwen-code/qwen-code@<версия> - Рекомендуется выполнить проверку основных функций, запустив несколько команд llm и инструментов, чтобы убедиться, что пакеты работают должным образом. В будущем мы более формализуем этот процесс.
Когда объединять изменение версии, а когда нет?
Вышеуказанный шаблон для создания патчей или хотфиксов из текущих или более старых коммитов оставляет репозиторий в следующем состоянии:
- Тег (
vX.Y.Z-patch.1): Этот тег правильно указывает на исходный коммит в основной ветке, который содержит стабильный код, предназначенный для релиза. Это критически важно. Любой, кто делает checkout этого тега, получает точный код, который был опубликован. - Ветка (
release-vX.Y.Z-patch.1): Эта ветка содержит один новый коммит поверх помеченного коммита. Этот новый коммит содержит только изменение номера версии в package.json (и других связанных файлах, таких как package-lock.json).
Такое разделение хорошо. Оно сохраняет историю вашей основной ветки чистой от специфичных для релизов повышений версий до тех пор, пока вы не решите их объединить.
Это ключевое решение, и оно полностью зависит от характера релиза.
Объединение обратно для стабильных патчей и хотфиксов
Вы почти всегда захотите объединить ветку release-<tag> обратно в main для любого
стабильного патча или хотфикса.
- Почему? Основная причина — обновление версии в package.json в основной ветке. Если вы выпустите версию 1.2.1 из более старого коммита, но никогда не объедините обратно обновление версии, файл package.json в вашей основной ветке по-прежнему будет содержать “version”: “1.2.0”. Следующий разработчик, который начнет работу над следующим фичерелизом (v1.3.0), будет отпочковываться от кодовой базы с неправильным, устаревшим номером версии. Это приводит к путанице и требует ручного обновления версии позже.
- Процесс: После создания ветки release-v1.2.1 и успешной публикации пакета вы должны открыть пулреквест для объединения release-v1.2.1 в main. Этот PR будет содержать всего один коммит: “chore: bump version to v1.2.1”. Это чистая, простая интеграция, которая поддерживает вашу основную ветку в актуальном состоянии последней выпущенной версии.
НЕ СЛИВАЙТЕ ОБРАТНО Предварительные релизы (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 с тегом rc, и затем… ветка выполнила свою задачу. Вы можете просто удалить её. Код для RC уже находится в main (или в функциональной ветке), поэтому никакой функциональный код не теряется. Ветка релиза была лишь временным средством для номера версии.
Локальное тестирование и проверка: изменения в процессе упаковки и публикации
Если вам нужно протестировать процесс релиза без фактической публикации в NPM или создания публичного релиза на GitHub, вы можете запустить рабочий процесс вручную из интерфейса GitHub.
- Перейдите на вкладку Actions репозитория.
- Нажмите на выпадающий список “Run workflow”.
- Оставьте опцию
dry_runотмеченной (true). - Нажмите кнопку “Run workflow”.
Это запустит весь процесс релиза, но пропустит шаги npm publish и gh release create. Вы можете изучить логи рабочего процесса, чтобы убедиться, что все работает как ожидается.
Крайне важно тестировать любые изменения в процессе упаковки и публикации локально перед тем, как фиксировать их. Это гарантирует, что пакеты будут опубликованы правильно и будут работать как ожидается при установке пользователем.
Для проверки ваших изменений вы можете выполнить пробный запуск процесса публикации. Это смоделирует процесс публикации без фактической публикации пакетов в реестр npm.
npm_package_version=9.9.9 SANDBOX_IMAGE_REGISTRY="registry" SANDBOX_IMAGE_NAME="thename" npm run publish:npm --dry-runЭта команда выполнит следующие действия:
- Соберет все пакеты.
- Запустит все скрипты prepublish.
- Создаст архивы пакетов, которые будут опубликованы в npm.
- Выведет сводку по пакетам, которые будут опубликованы.
Затем вы можете изучить сгенерированные архивы, чтобы убедиться, что они содержат правильные файлы и что файлы package.json обновлены корректно. Архивы будут созданы в корне директории каждого пакета (например, 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. Основной пакет собирается первым, так как пакет cli зависит от него.
Этап 3: Упаковка и сборка окончательного публикуемого пакета
Это наиболее критический этап, на котором файлы перемещаются и преобразуются в их окончательное состояние для публикации. Процесс использует современные методы упаковки для создания окончательного пакета.
-
Создание бандла:
- Что происходит: Скрипт prepare-package.js создает чистый дистрибутивный пакет в директории
dist. - Ключевые преобразования:
- Копирует README.md и LICENSE в dist/
- Копирует папку locales для интернационализации
- Создает чистый package.json для дистрибуции с необходимыми зависимостями
- Поддерживает минимальные зависимости для дистрибуции (без связанных зависимостей времени выполнения)
- Сохраняет опциональные зависимости для node-pty
- Что происходит: Скрипт prepare-package.js создает чистый дистрибутивный пакет в директории
-
Создается JavaScript-бандл:
- Что происходит: Собранный JavaScript из packages/core/dist и packages/cli/dist объединяется в один исполняемый JavaScript-файл с использованием esbuild.
- Расположение файла: dist/cli.js
- Почему: Это создает один оптимизированный файл, содержащий весь необходимый код приложения. Это упрощает пакет за счет удаления необходимости сложного разрешения зависимостей во время установки.
-
Копируются статические и вспомогательные файлы:
- Что происходит: Важные файлы, которые не являются частью исходного кода, но необходимы для правильной работы пакета
или его надлежащего описания, копируются в директорию
dist. - Перемещение файлов:
- README.md -> dist/README.md
- LICENSE -> dist/LICENSE
- locales/ -> dist/locales/
- Внешние файлы -> dist/vendor/
- Почему:
- README.md и LICENSE — стандартные файлы, которые должны быть включены в любой NPM-пакет.
- Локали поддерживают функции интернационализации
- Внешние файлы содержат необходимые зависимости времени выполнения
- Что происходит: Важные файлы, которые не являются частью исходного кода, но необходимы для правильной работы пакета
или его надлежащего описания, копируются в директорию
Этап 4: Публикация в NPM
- Что происходит: Команда npm publish выполняется изнутри корневой директории
dist. - Почему: Выполняя npm publish изнутри директории
dist, загружаются только те файлы, которые мы тщательно собрали на Этапе 3 в реестр NPM. Это предотвращает случайную публикацию исходного кода, тестовых файлов или конфигураций разработки, в результате чего пользователи получают чистый и минимальный пакет.
Этот процесс гарантирует, что окончательный опубликованный артефакт представляет собой специально созданный, чистый и эффективный образ проекта, а не прямую копию рабочей области разработки.
Рабочие области NPM
Этот проект использует Рабочие области NPM для управления пакетами в этом монорепозитории. Это упрощает разработку, позволяя нам управлять зависимостями и запускать скрипты в нескольких пакетах из корня проекта.
Как это работает
Корневой файл package.json определяет рабочие области для этого проекта:
{
"workspaces": ["packages/*"]
}Это указывает NPM, что любая папка внутри каталога packages является отдельным пакетом, который должен управляться как часть рабочей области.
Преимущества рабочих пространств
- Упрощенное управление зависимостями: выполнение команды
npm installиз корня проекта установит все зависимости для всех пакетов в рабочем пространстве и свяжет их между собой. Это означает, что вам не нужно запускатьnpm installв каталоге каждого пакета. - Автоматическая привязка: пакеты внутри рабочего пространства могут зависеть друг от друга. При запуске
npm installNPM автоматически создаст символические ссылки между пакетами. Это означает, что при внесении изменений в один пакет, изменения сразу же становятся доступны другим пакетам, которые зависят от него. - Упрощенное выполнение скриптов: вы можете запускать скрипты в любом пакете из корня проекта с помощью флага
--workspace. Например, чтобы запустить скриптbuildв пакетеcli, можно выполнить командуnpm run build --workspace @qwen-code/qwen-code.