Skip to content

Commit 727acde

Browse files
committed
ci: add qwen runtime source options
1 parent 99d6da0 commit 727acde

2 files changed

Lines changed: 127 additions & 8 deletions

File tree

.github/workflows/desktop-release.yml

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,22 @@ on:
1313
description: "Release title. Defaults to the tag."
1414
required: false
1515
type: string
16+
qwen_code_source:
17+
description: "Qwen Code runtime source to vendor into the desktop app."
18+
required: true
19+
default: pinned_package_version
20+
type: choice
21+
options:
22+
- npm_latest
23+
- source_branch
24+
- pinned_package_version
25+
qwen_code_ref:
26+
description: "QwenLM/qwen-code branch, tag, or commit when qwen_code_source is source_branch."
27+
required: false
28+
default: main
29+
type: string
1630
qwen_code_version:
17-
description: "Optional @qwen-code/qwen-code version to vendor into the desktop app."
31+
description: "Optional exact @qwen-code/qwen-code npm version for pinned_package_version. Defaults to package.json qwenCodeRuntime.version."
1832
required: false
1933
type: string
2034
dry_run:
@@ -48,7 +62,6 @@ concurrency:
4862
env:
4963
BUN_VERSION: 1.3.9
5064
CRAFT_BRAND: openwork
51-
QWEN_CODE_VERSION: ${{ inputs.qwen_code_version }}
5265

5366
jobs:
5467
release_metadata:
@@ -166,6 +179,14 @@ jobs:
166179
with:
167180
ref: ${{ needs.release_metadata.outputs.release_ref }}
168181

182+
- name: Check out Qwen Code source
183+
if: ${{ inputs.qwen_code_source == 'source_branch' }}
184+
uses: actions/checkout@v4
185+
with:
186+
repository: QwenLM/qwen-code
187+
ref: ${{ inputs.qwen_code_ref }}
188+
path: qwen-code-source
189+
169190
- name: Set up Bun
170191
uses: oven-sh/setup-bun@v2
171192
with:
@@ -180,12 +201,54 @@ jobs:
180201
- name: Install dependencies
181202
run: bun install --frozen-lockfile
182203

204+
- name: Install Qwen Code source dependencies
205+
if: ${{ inputs.qwen_code_source == 'source_branch' }}
206+
working-directory: qwen-code-source
207+
run: npm ci
208+
183209
- name: Bump desktop version
184210
run: bun run bump-desktop-version "${{ needs.release_metadata.outputs.version }}"
185211

186212
- name: Confirm release version
187213
run: bun run check-release-version --version "${{ needs.release_metadata.outputs.version }}"
188214

215+
- name: Configure Qwen Code runtime source
216+
shell: bash
217+
env:
218+
QWEN_CODE_REF_INPUT: ${{ inputs.qwen_code_ref }}
219+
QWEN_CODE_SOURCE_INPUT: ${{ inputs.qwen_code_source }}
220+
QWEN_CODE_SOURCE_ROOT: ${{ github.workspace }}/qwen-code-source
221+
QWEN_CODE_VERSION_INPUT: ${{ inputs.qwen_code_version }}
222+
run: |
223+
set -euo pipefail
224+
225+
case "$QWEN_CODE_SOURCE_INPUT" in
226+
npm_latest)
227+
echo "QWEN_CODE_VERSION=latest" >> "$GITHUB_ENV"
228+
echo "Using Qwen Code runtime from npm dist-tag: latest"
229+
;;
230+
source_branch)
231+
if [ -z "$QWEN_CODE_REF_INPUT" ]; then
232+
echo "::error::qwen_code_ref is required when qwen_code_source is source_branch."
233+
exit 1
234+
fi
235+
echo "QWEN_CODE_ROOT=$QWEN_CODE_SOURCE_ROOT" >> "$GITHUB_ENV"
236+
echo "Using Qwen Code runtime from QwenLM/qwen-code ref: $QWEN_CODE_REF_INPUT"
237+
;;
238+
pinned_package_version)
239+
if [ -n "$QWEN_CODE_VERSION_INPUT" ]; then
240+
echo "QWEN_CODE_VERSION=$QWEN_CODE_VERSION_INPUT" >> "$GITHUB_ENV"
241+
echo "Using exact Qwen Code npm version: $QWEN_CODE_VERSION_INPUT"
242+
else
243+
echo "Using Qwen Code runtime from package.json qwenCodeRuntime.version"
244+
fi
245+
;;
246+
*)
247+
echo "::error::Unknown qwen_code_source: $QWEN_CODE_SOURCE_INPUT"
248+
exit 1
249+
;;
250+
esac
251+
189252
- name: Configure optional signing secrets
190253
shell: bash
191254
env:

scripts/vendor-qwen-code.ts

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,27 @@ const desktopRoot = join(import.meta.dir, '..');
1414
const defaultRepoRoot = join(desktopRoot, '..', '..');
1515
const electronDir = join(desktopRoot, 'apps', 'electron');
1616
const vendorDir = join(electronDir, 'vendor', 'qwen-code');
17+
const qwenCodePackageName = '@qwen-code/qwen-code';
18+
const qwenCodeMetadataUrl = `https://registry.npmjs.org/${encodeURIComponent(qwenCodePackageName)}`;
1719

1820
interface DesktopPackageJson {
1921
qwenCodeRuntime?: {
2022
version?: string;
2123
};
2224
}
2325

26+
interface NpmPackageMetadata {
27+
'dist-tags'?: Record<string, string>;
28+
versions?: Record<
29+
string,
30+
{
31+
dist?: {
32+
tarball?: string;
33+
};
34+
}
35+
>;
36+
}
37+
2438
function npmCommand(): string {
2539
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
2640
}
@@ -106,17 +120,59 @@ async function vendorLocalCheckout(repoRoot: string): Promise<void> {
106120
console.log(`Vendored local Qwen Code CLI into ${vendorDir}`);
107121
}
108122

109-
async function vendorNpmVersion(version: string): Promise<void> {
110-
console.log(`Downloading Qwen Code ${version} from npm...`);
123+
async function readNpmPackageMetadata(): Promise<NpmPackageMetadata> {
124+
const response = await fetch(qwenCodeMetadataUrl);
125+
if (!response.ok) {
126+
throw new Error(
127+
`Failed to read ${qwenCodePackageName} metadata from npm: HTTP ${response.status}`,
128+
);
129+
}
130+
return (await response.json()) as NpmPackageMetadata;
131+
}
132+
133+
async function resolveNpmVersionOrTag(
134+
versionOrTag: string,
135+
): Promise<{ tarballUrl: string; version: string }> {
136+
const requested = versionOrTag.trim();
137+
if (!requested) {
138+
throw new Error('Qwen Code npm version or dist-tag is required.');
139+
}
140+
141+
const metadata = await readNpmPackageMetadata();
142+
const version = metadata.versions?.[requested]
143+
? requested
144+
: metadata['dist-tags']?.[requested];
145+
if (!version) {
146+
throw new Error(
147+
`Could not resolve ${qwenCodePackageName}@${requested} from npm.`,
148+
);
149+
}
150+
151+
const tarballUrl = metadata.versions?.[version]?.dist?.tarball;
152+
if (!tarballUrl) {
153+
throw new Error(
154+
`Could not find npm tarball for ${qwenCodePackageName}@${version}.`,
155+
);
156+
}
157+
158+
return { tarballUrl, version };
159+
}
160+
161+
async function vendorNpmVersion(versionOrTag: string): Promise<void> {
162+
const { tarballUrl, version } = await resolveNpmVersionOrTag(versionOrTag);
163+
const sourceLabel =
164+
versionOrTag === version ? version : `${versionOrTag} (${version})`;
165+
console.log(`Downloading Qwen Code ${sourceLabel} from npm...`);
111166

112167
const tempDir = mkdtempSync(join(tmpdir(), 'qwen-code-vendor-'));
113168
const tarballPath = join(tempDir, `qwen-code-${version}.tgz`);
114-
const url = `https://registry.npmjs.org/@qwen-code/qwen-code/-/qwen-code-${version}.tgz`;
115169

116170
try {
117-
const response = await fetch(url);
171+
const response = await fetch(tarballUrl);
118172
if (!response.ok) {
119-
throw new Error(`Failed to download ${url}: HTTP ${response.status}`);
173+
throw new Error(
174+
`Failed to download ${tarballUrl}: HTTP ${response.status}`,
175+
);
120176
}
121177
await Bun.write(tarballPath, await response.arrayBuffer());
122178

@@ -130,7 +186,7 @@ async function vendorNpmVersion(version: string): Promise<void> {
130186
);
131187

132188
verifyVendoredCli();
133-
console.log(`Vendored @qwen-code/qwen-code@${version} into ${vendorDir}`);
189+
console.log(`Vendored ${qwenCodePackageName}@${version} into ${vendorDir}`);
134190
} finally {
135191
rmSync(tempDir, { recursive: true, force: true });
136192
}

0 commit comments

Comments
 (0)