パッケージ概要
このモノレポには、@qwen-code/qwen-code と @qwen-code/qwen-code-core の2つの主要パッケージが含まれています。
@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 パッケージとして公開されます。これにより、必要に応じて他のプロジェクトでスタンドアロンパッケージとして使用できます。dist フォルダー内のすべてのトランスパイルされた JS コードはパッケージに含まれます。
リリースプロセス
このプロジェクトでは、すべてのパッケージが正しくバージョン管理および公開されるように、構造化されたリリースプロセスに従っています。このプロセスは、可能な限り自動化されるように設計されています。
リリース方法
リリースは、release.yml GitHub Actions ワークフローを通じて管理されます。パッチまたはホットフィックスの手動リリースを実行するには:
- リポジトリの Actions タブに移動します。
- リストから Release ワークフローを選択します。
- Run workflow ドロップダウンボタンをクリックします。
- 必要な入力項目を記入します:
- Version: リリースする正確なバージョン(例:
v0.2.1)。 - Ref: リリース元のブランチまたはコミット SHA(デフォルトは
main)。 - Dry Run: ワークフローをテストのみで実行する場合は
trueのままにし、本番リリースを行う場合はfalseに設定します。
- Version: リリースする正確なバージョン(例:
- Run workflow をクリックします。
リリースの種類
プロジェクトでは複数のタイプのリリースがサポートされています:
ステーブルリリース
本番環境での利用を目的とした通常のステーブルリリースです。
プレビューリリース
毎週火曜日 23:59 UTC に公開されるプレビューリリースで、次期機能を早期に試すことができます。
ナイトリーリリース
最先端の開発テストのために、UTC 時間の毎日深夜 0 時に日次ナイトリーリリースを実施しています。
自動リリーススケジュール
- ナイトリー: UTC 毎日深夜 0 時
- プレビュー: UTC 毎週火曜日 23:59
- ステーブル: メンテナーによる手動リリース
異なるリリースタイプの使い方
各タイプの最新バージョンをインストールするには:
# ステーブル(デフォルト)
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チェックと統合テストをすべて実行。- すべてのテストが成功すれば、リリースタイプに基づいて適切なバージョン番号を計算。
- 適切な dist-tag を付けて npm にパッケージをビルド・公開。
- そのバージョン用の GitHub Release を作成。
失敗時の処理
リリースワークフローのいずれかのステップが失敗した場合、自動的に新しい Issue がリポジトリに作成され、bug ラベルと失敗タイプ固有のラベル(例:nightly-failure、preview-failure)が付けられます。Issue には、簡単にデバッグできるように失敗したワークフロー実行へのリンクが含まれます。
リリースの検証
新しいリリースをプッシュした後は、パッケージが期待通りに動作することを確認するために、スモークテストを実行する必要があります。これは、ローカルにパッケージをインストールし、一連のテストを実行して正しく機能していることを確認することで行えます。
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> - 数個のLLMコマンドとツールを基本的に実行してみるスモークテストを推奨します。これにより、パッケージが期待通りに動作することを確認できます。将来的にはこれをさらに具体化する予定です。
バージョン変更をマージするタイミング、またはマージしない場合とは?
現在または古いコミットからパッチリリースやホットフィックスリリースを作成する上記のパターンでは、リポジトリは以下の状態になります:
- タグ(
vX.Y.Z-patch.1):このタグは、リリースしたい安定版コードを含むmainブランチ上の元のコミットを正しく指しています。これは非常に重要です。このタグをチェックアウトした人は、公開されたコードそのものを取得できます。 - ブランチ(
release-vX.Y.Z-patch.1):このブランチには、タグ付きコミットの上に新しいコミットが1つ含まれています。その新しいコミットには、package.json(およびpackage-lock.jsonなどの関連ファイル)のバージョン番号変更のみが含まれています。
このような分離は良いことです。これにより、マージするタイミングを決定するまで、mainブランチの履歴をリリース固有のバージョンアップで汚染することなく維持できます。
これが重要な判断ポイントであり、リリースの性質によって完全に異なります。
安定版パッチおよびホットフィックスのマージバック
安定版パッチやホットフィックスリリースを行う際は、ほぼ常に release-<tag> ブランチを main ブランチにマージバックする必要があります。
- なぜか? 主な理由は、main ブランチの package.json のバージョン情報を更新するためです。古いコミットから v1.2.1 をリリースしたが、バージョンアップの変更を main にマージし忘れると、main ブランチの 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」という1つのコミットのみが含まれます。これはクリーンでシンプルな統合であり、main ブランチを最新のリリースバージョンと同期した状態に保ちます。
プレリリース(RC、ベータ、開発版)ではマージバックしない
通常、プレリリース用のリリースブランチは main にマージバックしません。
- 理由:プレリリースバージョン(例:v1.3.0-rc.1、v1.3.0-rc.2)は、定義上、安定版ではなく一時的なものです。リリース候補のためのバージョン更新を一連の履歴として main ブランチに残したくはありません。main の package.json には RC ではなく最新の安定版バージョンが反映されているべきです。
- 手順:release-v1.3.0-rc.1 ブランチを作成し、npm publish —tag rc を実行したら、そのブランチの役目は終わりです。そのまま削除して構いません。RC のコードはすでに main(または機能ブランチ)にあるので、機能的なコードは失われません。リリースブランチはバージョン番号を扱う一時的な手段に過ぎません。
ローカルでのテストと検証:パッケージングおよび公開プロセスの変更
実際に NPM に公開したり、GitHub リリースを公開することなくリリースプロセスをテストする必要がある場合は、GitHub UI からワークフローを手動でトリガーできます。
- リポジトリの 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このコマンドは以下の処理を行います:
- すべてのパッケージをビルドします。
- すべての事前公開スクリプトを実行します。
- npm に公開されるパッケージの tarball を作成します。
- 公開されるパッケージのサマリーを出力します。
生成された tarball を確認して、正しいファイルが含まれていること、および package.json ファイルが正しく更新されていることを確認できます。tarball は各パッケージディレクトリのルートに作成されます(例:packages/cli/qwen-code-0.1.6.tgz)。
ドライランを実行することで、パッケージングプロセスへの変更が正しいことを確信し、パッケージが正常に公開されることを確認できます。
リリースの詳細
リリースプロセスの主な目的は、packages/ ディレクトリにあるソースコードをビルドし、プロジェクトのルートにある一時的な dist ディレクトリにクリーンで自己完結型のパッケージを構築することです。実際に NPM に公開されるのはこの dist ディレクトリの中身です。
以下が主要なステージです:
ステージ 1: リリース前の健全性チェックとバージョン管理
- 処理内容: ファイルを移動する前に、プロジェクトが良好な状態であることを確認します。これにはテスト、リンティング、型チェック(npm run preflight)が含まれます。ルートの package.json および packages/cli/package.json のバージョン番号が新しいリリースバージョンに更新されます。
- 理由: 高品質で動作するコードのみがリリースされることを保証します。バージョン管理は新しいリリースを示す最初のステップです。
ステージ 2: ソースコードのビルド
- 処理内容: packages/core/src および packages/cli/src 内の TypeScript ソースコードが JavaScript にコンパイルされます。
- ファイルの移動:
- packages/core/src/*/.ts -> コンパイル後 -> packages/core/dist/
- packages/cli/src/*/.ts -> コンパイル後 -> packages/cli/dist/
- 理由: 開発中に書かれた TypeScript コードは、Node.js で実行できるプレーンな JavaScript に変換する必要があります。cli パッケージは core パッケージに依存しているため、core パッケージが先にビルドされます。
ステージ 3: 最終的な公開可能パッケージのバンドルとアセンブル
これはファイルが最終的な公開状態に移動・変換される最も重要なステージです。プロセスでは最新のバンドル技術を使用して最終パッケージを作成します。
-
バンドルの作成:
- 処理内容: prepare-package.js スクリプトが
distディレクトリ内にクリーンな配布パッケージを作成します。 - 主な変換処理:
- README.md と LICENSE を dist/ にコピー
- 国際化対応のための locales フォルダをコピー
- 必要な依存関係のみを含む配布用のクリーンな package.json を作成
- tiktoken などのランタイム依存関係を含める
- node-pty のオプション依存関係を維持
- 処理内容: prepare-package.js スクリプトが
-
JavaScript バンドルの作成:
- 処理内容: packages/core/dist および packages/cli/dist のビルドされた JavaScript が、esbuild を使用して単一の実行可能な JavaScript ファイルにバンドルされます。
- ファイルの場所: dist/cli.js
- 理由: これにより、必要なすべてのアプリケーションコードを含む単一の最適化されたファイルが作成されます。インストール時に複雑な依存関係の解決が必要なくなるため、パッケージが簡素化されます。
-
静的ファイルとサポートファイルのコピー:
- 処理内容: ソースコードの一部ではないが、パッケージが正しく動作したり適切に記述されたりするために必要な必須ファイルが
distディレクトリにコピーされます。 - ファイルの移動:
- README.md -> dist/README.md
- LICENSE -> dist/LICENSE
- locales/ -> dist/locales/
- ベンダーファイル -> dist/vendor/
- 理由:
- README.md と LICENSE は、どの NPM パッケージにも含めるべき標準ファイルです。
- Locales は国際化機能をサポートします
- ベンダーファイルには必要なランタイム依存関係が含まれています
- 処理内容: ソースコードの一部ではないが、パッケージが正しく動作したり適切に記述されたりするために必要な必須ファイルが
ステージ 4: NPM への公開
- 処理内容: ルートの
distディレクトリ内で npm publish コマンドが実行されます。 - 理由:
distディレクトリ内から npm publish を実行することで、ステージ 3 で慎重にアセンブルしたファイルのみが NPM レジストリにアップロードされます。これにより、ソースコード、テストファイル、開発設定などが誤って公開されるのを防ぎ、ユーザー向けにクリーンで最小限のパッケージを提供できます。
このプロセスにより、最終的に公開される成果物は、開発ワークスペースの直接的なコピーではなく、目的に特化したクリーンで効率的なプロジェクト表現となることが保証されます。
NPM Workspaces
このプロジェクトでは、モノレポ内のパッケージを管理するために NPM Workspaces を使用しています。これにより、プロジェクトのルートから複数のパッケージの依存関係を管理し、スクリプトを実行することが可能になるため、開発が簡素化されます。
仕組み
ルートの package.json ファイルで、このプロジェクトのワークスペースが定義されています:
{
"workspaces": ["packages/*"]
}これは、packages ディレクトリ内の任意のフォルダが、ワークスペースの一部として管理されるべき別のパッケージであることを NPM に伝えます。
ワークスペースの利点
- 依存関係管理の簡素化: プロジェクトのルートから
npm installを実行すると、ワークスペース内のすべてのパッケージの依存関係がインストールされ、それらが相互にリンクされます。つまり、各パッケージのディレクトリでnpm installを実行する必要はありません。 - 自動リンク: ワークスペース内のパッケージは互いに依存できます。
npm installを実行すると、NPM はパッケージ間のシンボリックリンクを自動的に作成します。これにより、あるパッケージに変更を加えると、それに依存する他のパッケージですぐにその変更を利用できるようになります。 - スクリプト実行の簡素化: ルートプロジェクトから
--workspaceフラグを使用して、任意のパッケージ内のスクリプトを実行できます。たとえば、cliパッケージのbuildスクリプトを実行するには、npm run build --workspace @qwen-code/qwen-codeを実行します。