mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
feat(web-shell): publish the package with the cli release (#12178)
* feat(web-shell): publish the package with the cli release The release workflow published the cli and the channel packages but never @qwen-code/web-shell, so the npm artifact only moved when someone published it by hand. Add the package to the release step and record its repository so npm accepts the provenance attestation the workflow requests. * fix(release): probe @qwen-code/web-shell in the push-time version guard publish_package 'packages/web-shell' made the package CI-published, but PUBLISHED_PACKAGES — the sole input to assertVersionUnreleased — still listed only twelve names. A release shipped only as @qwen-code/web-shell therefore read as unshipped: the version-collision bump never fired and the force-push guard could proceed over an already-published version. Widen the guard list, its pin in get-release-version.test.js, and generalise "keeps the publish allowlist and the guard package set in step" so every bare publish_package '<dir>' target is resolved through the package.json it publishes. The channel-loop comparison alone could not see this addition, which is how it shipped unguarded. Co-authored-by: Qwen-Coder <[email protected]> Patrol-Run: qwen-pr-closeout/jmu6tb0j73c * test(release): simplify publish guard coverage * fix(release): publish web-shell after the channels Review on #12178 (R1-3): the step runs under `set -eo pipefail` and every publish_package call is bare, so inserting the newest name ahead of the channel packages makes a failure of its first CI publish strand all of them. Publish it last instead. Also append the new entry to PUBLISHED_PACKAGES rather than inserting it after audio-capture: the version-guard tests read that array by index, so its position is load-bearing. Record that in the pinned assertion. --------- Co-authored-by: Qwen-Coder <[email protected]>
This commit is contained in:
1 parent
ab47e38197
commit
e596a410bb
6 files changed
+46
-7
No files matched your search
@@ -197,6 +197,12 @@ case "${step}" in
|
||||
publish_package "packages/channels/${channel}" "${publish_marker}" "${channel}"
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
# Last on purpose: this is the only name in the sequence CI has never
|
||||
# published, so a failure here leaves every long-shipped package already
|
||||
# out instead of stranding them under `set -eo pipefail`.
|
||||
publish_package 'packages/web-shell'
|
||||
|
||||
if [[ "${IS_DRY_RUN}" != "true" ]] && [[ ! -s "${publish_marker}" ]]; then
|
||||
echo "::warning::Every channel package was already published; nothing shipped"
|
||||
fi
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
{
|
||||
"name": "@qwen-code/web-shell",
|
||||
"version": "0.24.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/QwenLM/qwen-code.git",
|
||||
"directory": "packages/web-shell"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
|
||||
@@ -22,6 +22,7 @@ export const PUBLISHED_PACKAGES = [
|
||||
'@qwen-code/channel-telegram',
|
||||
'@qwen-code/channel-wecom',
|
||||
'@qwen-code/channel-weixin',
|
||||
'@qwen-code/web-shell',
|
||||
];
|
||||
|
||||
// Deliberately a copy of `scripts/lib/release-helpers.js`, not an import:
|
||||
|
||||
@@ -738,12 +738,13 @@ describe('assertVersionUnreleased', () => {
|
||||
`Version 1.2.3 has already shipped; refusing to force-push the release branch over it. Found on: ${foundOn}. If a previous attempt published only part of the release, complete the remaining artifacts manually — re-running this job will keep failing here while the version stays published.`;
|
||||
|
||||
it('pins the full published-package set', () => {
|
||||
// The push-time guard derives from this list; the publish allowlist in
|
||||
// `.github/scripts/run-release-step.sh` enumerates the same channels
|
||||
// separately, so adding or removing a package must update both. The two
|
||||
// are pinned against each other by "keeps the publish allowlist and the
|
||||
// guard package set in step" in release-workflow.test.js — release.yml
|
||||
// itself no longer contains any publish step.
|
||||
// The push-time guard and the release-version picker derive from this
|
||||
// list; the publish allowlist in `.github/scripts/run-release-step.sh`
|
||||
// enumerates the same packages separately, so adding or removing one must
|
||||
// update both. They are pinned against each other by "keeps the publish
|
||||
// allowlist and the guard package set in step" in release-workflow.test.js
|
||||
// — release.yml itself no longer contains any publish step. Append rather
|
||||
// than insert: the tests below read this array by index.
|
||||
expect(PUBLISHED_PACKAGES).toEqual([
|
||||
'@qwen-code/qwen-code',
|
||||
'@qwen-code/external-context-mem0',
|
||||
@@ -757,6 +758,7 @@ describe('assertVersionUnreleased', () => {
|
||||
'@qwen-code/channel-telegram',
|
||||
'@qwen-code/channel-wecom',
|
||||
'@qwen-code/channel-weixin',
|
||||
'@qwen-code/web-shell',
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -1772,6 +1772,7 @@ describe('package scripts', () => {
|
||||
'packages/mobile-mcp',
|
||||
'packages/node-repl',
|
||||
'packages/sdk-typescript',
|
||||
'packages/web-shell',
|
||||
]) {
|
||||
const packageJson = JSON.parse(
|
||||
readFileSync(path.join(root, packageDirectory, 'package.json'), 'utf8'),
|
||||
|
||||
@@ -524,6 +524,28 @@ describe('release workflow', () => {
|
||||
.filter((name) => name !== 'base')
|
||||
.sort();
|
||||
expect(published).toEqual(guarded);
|
||||
|
||||
// Non-channel packages are literal calls, so verify those against the
|
||||
// guard too. Resolve their names from package.json to avoid a second map.
|
||||
const publishStep = releaseStepScript.slice(
|
||||
releaseStepScript.indexOf('\n publish-packages)'),
|
||||
releaseStepScript.indexOf('\n verify-archives)'),
|
||||
);
|
||||
const literalTargets = [
|
||||
...publishStep.matchAll(/publish_package '([^']+)'/g),
|
||||
].map(([, directory]) => directory);
|
||||
expect(literalTargets.length).toBeGreaterThan(1);
|
||||
const guardedNames = new Set(PUBLISHED_PACKAGES);
|
||||
for (const directory of literalTargets) {
|
||||
// `dist` is the root package's bundle output rather than a workspace
|
||||
// directory, and does not exist in a source checkout.
|
||||
const manifest =
|
||||
directory === 'dist' ? 'package.json' : `${directory}/package.json`;
|
||||
const { name } = JSON.parse(readFileSync(manifest, 'utf8'));
|
||||
expect(guardedNames.has(name), `${directory} publishes ${name}`).toBe(
|
||||
true,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps the workflow focused on orchestration', () => {
|
||||
@@ -598,6 +620,7 @@ describe('release workflow', () => {
|
||||
mkdirSync(bin);
|
||||
for (const path of [
|
||||
'dist',
|
||||
'packages/web-shell',
|
||||
'packages/channels/base',
|
||||
...channels.map((channel) => `packages/channels/${channel}`),
|
||||
]) {
|
||||
@@ -643,12 +666,13 @@ describe('release workflow', () => {
|
||||
expect(publishCalls.map(([cwd]) => cwd)).toEqual([
|
||||
join(canonicalDirectory, 'dist'),
|
||||
join(canonicalDirectory, 'packages/channels/base'),
|
||||
join(canonicalDirectory, 'packages/web-shell'),
|
||||
]);
|
||||
// The dist-tag is the reason NPM_TAG is set in this child env at all.
|
||||
// Without it `npm publish` defaults to `latest`, so the 21:00 UTC
|
||||
// nightly would take over the tag every end-user install and the ECS
|
||||
// fleet updater resolve through. `--access public` is here for the
|
||||
// same reason: one array feeds all twelve published packages.
|
||||
// same reason: one array feeds all thirteen published packages.
|
||||
for (const [cwd, args] of publishCalls) {
|
||||
expect(args, cwd).toContain('--access public');
|
||||
expect(args, cwd).toContain('--tag=latest');
|
||||
|
||||
Reference in new issue
Block a user