mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-11-07 06:19:43 -10:00
fix(ci): Decouple managed runtime distribution from Maven Central (#15782)
Co-authored-by: Qwen-Coder <[email protected]>
This commit is contained in:
1 parent
11ef1988d8
commit
db88f2da5e
7 files changed
+144
-161
No files matched your search
@@ -10,7 +10,7 @@ on:
|
||||
type: 'string'
|
||||
required: true
|
||||
dry_run:
|
||||
description: 'Build and verify without publishing to Central, GitHub, or OSS.'
|
||||
description: 'Build and verify without publishing to GitHub or OSS.'
|
||||
type: 'boolean'
|
||||
required: true
|
||||
default: true
|
||||
@@ -151,7 +151,6 @@ jobs:
|
||||
# Older release tags shipped the executable as the main artifact.
|
||||
if [[ ! -f "${runtime_jar}" ]]; then runtime_jar="packages/managed-agent-server/target/qwen-managed-agent-server-${CLI_VERSION}.jar"; fi
|
||||
unzip -p "${runtime_jar}" META-INF/MANIFEST.MF | tr -d '\r' | grep -Fx 'Main-Class: org.springframework.boot.loader.launch.JarLauncher'
|
||||
echo "MANAGED_RUNTIME_JAR=${runtime_jar}" >> "${GITHUB_ENV}"
|
||||
node .qwen/managed-release-tools/scripts/managed-runtime-release.js --jar "${runtime_jar}" --version "${CLI_VERSION}" --out-dir dist/managed-runtime
|
||||
|
||||
- name: 'Retain verified JAR and checksum'
|
||||
@@ -206,21 +205,6 @@ jobs:
|
||||
fi
|
||||
gh api "repos/QwenLM/qwen-code/releases/tags/${RELEASE_TAG}" | jq --exit-status '.draft == false'
|
||||
jar="qwen-managed-agent-server-${CLI_VERSION}.jar"
|
||||
central_files=("packages/managed-agent-server/target/${jar}")
|
||||
if [[ "${MANAGED_RUNTIME_JAR}" != "${central_files[0]}" ]]; then central_files+=("${MANAGED_RUNTIME_JAR}"); fi
|
||||
present=0
|
||||
missing=0
|
||||
for file in "${central_files[@]}"; do
|
||||
central="https://repo.maven.apache.org/maven2/com/alibaba/qwen-managed-agent-server/${CLI_VERSION}/$(basename "${file}")"
|
||||
state=$(node .qwen/managed-release-tools/scripts/managed-runtime-release.js --check-url "${central}" --file "${file}") || exit 1
|
||||
case "${state}" in present) present=$((present+1));; missing) missing=$((missing+1));; *) exit 1;; esac
|
||||
done
|
||||
if (( present > 0 && missing > 0 )); then
|
||||
echo 'Partial Central publication; refusing an immutable redeploy.' >&2
|
||||
exit 1
|
||||
fi
|
||||
if (( missing > 0 )); then state=missing; else state=present; fi
|
||||
echo "central=${state}" >> "${GITHUB_OUTPUT}"
|
||||
: > "${RUNNER_TEMP}/managed-github-missing"
|
||||
: > "${RUNNER_TEMP}/managed-oss-missing"
|
||||
for asset in "${jar}" "${jar}.sha256"; do
|
||||
@@ -236,52 +220,6 @@ jobs:
|
||||
fi
|
||||
done
|
||||
|
||||
- name: 'Configure signed Central publication'
|
||||
if: "${{ (github.event_name == 'release' || !inputs.dry_run) && steps.publication.outputs.central == 'missing' }}"
|
||||
uses: 'actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654' # v5.2.0
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
server-id: 'central'
|
||||
server-username: 'MAVEN_USERNAME'
|
||||
server-password: 'MAVEN_PASSWORD'
|
||||
gpg-private-key: '${{ secrets.MAVEN_GPG_PRIVATE_KEY }}'
|
||||
gpg-passphrase: 'MAVEN_GPG_PASSPHRASE'
|
||||
|
||||
- name: 'Publish the signed server artifact to Central'
|
||||
if: "${{ (github.event_name == 'release' || !inputs.dry_run) && steps.publication.outputs.central == 'missing' }}"
|
||||
env:
|
||||
MAVEN_USERNAME: '${{ secrets.CENTRAL_USERNAME }}'
|
||||
MAVEN_PASSWORD: '${{ secrets.CENTRAL_PASSWORD }}'
|
||||
MAVEN_GPG_PRIVATE_KEY: '${{ secrets.MAVEN_GPG_PRIVATE_KEY }}'
|
||||
MAVEN_GPG_PASSPHRASE: '${{ secrets.MAVEN_GPG_PASSPHRASE }}'
|
||||
run: |-
|
||||
set -euo pipefail
|
||||
for name in MAVEN_USERNAME MAVEN_PASSWORD MAVEN_GPG_PRIVATE_KEY MAVEN_GPG_PASSPHRASE; do
|
||||
[[ -n "${!name}" ]] || { echo "Missing production-release secret: ${name}" >&2; exit 1; }
|
||||
done
|
||||
mvn --batch-mode --no-transfer-progress -f packages/managed-agent-server/pom.xml deploy -Pcentral-release -DskipTests -Dproject.build.outputTimestamp="${BUILD_TIMESTAMP}"
|
||||
cmp "${MANAGED_RUNTIME_JAR}" "dist/managed-runtime/qwen-managed-agent-server-${CLI_VERSION}.jar"
|
||||
|
||||
- name: 'Verify Central availability before distribution'
|
||||
if: "${{ github.event_name == 'release' || !inputs.dry_run }}"
|
||||
run: |-
|
||||
set -euo pipefail
|
||||
jar="qwen-managed-agent-server-${CLI_VERSION}.jar"
|
||||
central_files=("packages/managed-agent-server/target/${jar}")
|
||||
if [[ "${MANAGED_RUNTIME_JAR}" != "${central_files[0]}" ]]; then central_files+=("${MANAGED_RUNTIME_JAR}"); fi
|
||||
for attempt in {1..40}; do
|
||||
missing=0
|
||||
for file in "${central_files[@]}"; do
|
||||
state=$(node .qwen/managed-release-tools/scripts/managed-runtime-release.js --check-url "https://repo.maven.apache.org/maven2/com/alibaba/qwen-managed-agent-server/${CLI_VERSION}/$(basename "${file}")" --file "${file}")
|
||||
case "${state}" in present) ;; missing) missing=$((missing+1));; *) exit 1;; esac
|
||||
done
|
||||
if (( missing == 0 )); then exit 0; fi
|
||||
sleep 30
|
||||
done
|
||||
echo 'The exact server JAR is not yet available on Central.' >&2
|
||||
exit 1
|
||||
|
||||
- name: 'Attach only missing GitHub release assets'
|
||||
if: "${{ github.event_name == 'release' || !inputs.dry_run }}"
|
||||
env:
|
||||
|
||||
@@ -223,12 +223,27 @@ service children are created.
|
||||
|
||||
A dedicated protected release workflow builds from an existing CLI release tag,
|
||||
checks its package version, and verifies the Java SDK and server using Java 21.
|
||||
The server JAR is published as the independent Maven coordinate
|
||||
`com.alibaba:qwen-managed-agent-server:<cli-version>` using the SDK's signed
|
||||
Central publication conventions, including sources and Javadoc. Auxiliary
|
||||
operator executable JARs are not attached to that publication. The exact same
|
||||
primary JAR and checksum are attached to the CLI GitHub Release and copied to
|
||||
the existing versioned OSS prefix, outside the standalone archive allowlist.
|
||||
After full verification, the executable server JAR and checksum are attached to the
|
||||
CLI GitHub Release and copied to the existing versioned OSS prefix, outside the
|
||||
standalone archive allowlist. The workflow selects the `-exec.jar` build output
|
||||
when present and falls back to the main JAR for older tags; the public versioned
|
||||
JAR name stays unchanged. The workflow verifies both public channels against
|
||||
the staged bytes. Runtime distribution does not check for the server coordinate
|
||||
on Maven Central, publish it there, or wait for that publication. Central
|
||||
publishing authorization and artifact synchronization no longer gate delivery
|
||||
to the channels the installer actually uses. It needs OSS credentials and GitHub
|
||||
release access, without loading Central publishing credentials or a GPG private key.
|
||||
|
||||
Java compilation and normal Maven dependency resolution, the complete SDK/server
|
||||
verification, test-fork isolation and the existing `central-release` build profile
|
||||
remain unchanged. GPG signing is
|
||||
skipped during verification; the profile does not publish anything before the
|
||||
Maven deploy phase. Independent signed publication of
|
||||
`com.alibaba:qwen-managed-agent-server:<cli-version>` remains available through
|
||||
that Maven profile when needed for Maven consumers, including sources and
|
||||
Javadoc and excluding auxiliary operator JARs. It is a separate release
|
||||
operation, with no dependency edge in the runtime distribution workflow.
|
||||
|
||||
Reproducible timestamps and checksum comparisons prevent a retry from replacing
|
||||
an existing version with different bytes. Dry runs build and verify without
|
||||
publishing. Production credentials and publication remain protected by the
|
||||
@@ -320,7 +335,7 @@ they do not describe the current main branch. The results above belong to the
|
||||
pre-split trial. Current split-head verification and limitations are recorded
|
||||
in the PR test report.
|
||||
|
||||
The first-use download path passed fourteen built-bundle scenarios with the real Java 21 server and Hosted Harness: initial installation, offline restart, OSS-to-GitHub fallback, interrupted-download retry, and refusal of invalid downloads or selected payloads. Transport was intercepted at the exact production URLs to serve the locally built JAR; public production assets have not been published or validated. The release profile builds the primary executable JAR, sources, and Javadoc locally; signed Central publication and protected GitHub/OSS upload require a production release run.
|
||||
The first-use download path passed fourteen built-bundle scenarios with the real Java 21 server and Hosted Harness: initial installation, offline restart, OSS-to-GitHub fallback, interrupted-download retry, and refusal of invalid downloads or selected payloads. Transport was intercepted at the exact production URLs to serve the locally built JAR; public production assets have not been published or validated. The release profile builds the primary executable JAR, sources, and Javadoc locally. The runtime-distribution change still requires a protected GitHub/OSS release run and clean first-install acceptance; signed Central publication is independent.
|
||||
|
||||
## Open questions
|
||||
|
||||
|
||||
@@ -174,11 +174,21 @@ runtime,后续调用可以重试。已有显式、相邻或已安装的 payloa
|
||||
应用凭据、数据或服务子进程之前。
|
||||
|
||||
独立的受保护发行 workflow 从已存在的 CLI release tag 构建,检查 package 版本,
|
||||
并使用 Java 21 验证 Java SDK 和服务。服务 JAR 沿用 SDK 的 Central 签名发布约定,
|
||||
以独立 Maven 坐标 `com.alibaba:qwen-managed-agent-server:<cli-version>` 发布,
|
||||
同时提供源码和 Javadoc。辅助运维可执行 JAR 不附加到这次发布。完全相同的主 JAR
|
||||
和校验文件附加到 CLI GitHub Release,再复制到现有版本化 OSS 前缀,位于
|
||||
standalone archive 允许列表之外。可重现时间戳和校验和比较防止重试时用不同字节
|
||||
并使用 Java 21 验证 Java SDK 和服务。完整验证通过后,可执行服务 JAR 和校验文件
|
||||
附加到 CLI GitHub Release,再复制到现有版本化 OSS 前缀,位于 standalone archive
|
||||
允许列表之外。workflow 优先选择 `-exec.jar` 构建产物,对旧 tag 回退到主 JAR;
|
||||
公开的版本化 JAR 名称保持不变。workflow 将两个公开渠道的制品与暂存字节核对。runtime 分发不探测
|
||||
服务坐标在 Maven Central 上是否存在,不向 Central 发布或等待该发布完成。Central
|
||||
发布授权与制品同步状态不再阻塞安装器实际使用的渠道交付。分发需要 OSS 凭据和
|
||||
GitHub release 权限,无需加载 Central 发布凭据或 GPG 私钥。
|
||||
|
||||
Java 编译与正常 Maven 依赖解析、完整 SDK/server 验证、测试 fork 隔离和现有
|
||||
`central-release` 构建 profile 保持不变。验证时跳过 GPG 签名;该 profile 在 Maven deploy 阶段之前不会
|
||||
执行发布。需要服务于 Maven 使用者时,仍可通过该 profile 独立签名发布
|
||||
`com.alibaba:qwen-managed-agent-server:<cli-version>`,包含源码和 Javadoc,
|
||||
排除辅助运维 JAR。该操作与 runtime 分发独立,分发 workflow 不依赖它。
|
||||
|
||||
可重现时间戳和校验和比较防止重试时用不同字节
|
||||
替换已有版本。dry-run 只构建和验证,不发布。生产凭据与发布操作继续受现有
|
||||
`production-release` environment 保护。
|
||||
|
||||
@@ -246,7 +256,7 @@ CLI 的生命周期验收。十五项选择检查通过,包括 JAVA_HOME/PATH
|
||||
本地验收分别记录,不代表当前 main 分支状态。上述结果属于拆分前试验;当前
|
||||
拆分 head 的验证和限制记录在 PR 测试报告中。
|
||||
|
||||
首次下载路径使用真实 Java 21 服务与 Hosted Harness,通过十四项 built-bundle 场景:首次安装、离线重启、OSS 转 GitHub 回退、中断下载后重试,以及无效下载和选中 payload 拒绝。测试在精确生产 URL 处拦截 transport,提供本地构建的 JAR;公开生产产物尚未发布或验证。发布 profile 已在本地构建主可执行 JAR、源码与 Javadoc;Central 签名发布及受保护的 GitHub/OSS 上传仍需执行生产发行。
|
||||
首次下载路径使用真实 Java 21 服务与 Hosted Harness,通过十四项 built-bundle 场景:首次安装、离线重启、OSS 转 GitHub 回退、中断下载后重试,以及无效下载和选中 payload 拒绝。测试在精确生产 URL 处拦截 transport,提供本地构建的 JAR;公开生产产物尚未发布或验证。发布 profile 已在本地构建主可执行 JAR、源码与 Javadoc。runtime 分发改动仍需受保护的 GitHub/OSS 生产发行及空缓存首装验收;Central 签名发布独立进行。
|
||||
|
||||
## 未决问题
|
||||
|
||||
|
||||
@@ -239,16 +239,25 @@ CLI release tag, using the SDK and server from that exact source revision. A
|
||||
manual run must be dispatched from `main` and defaults to a dry run. It verifies
|
||||
the CLI and Java module, builds the `central-release` profile, and retains the
|
||||
JAR and checksum as workflow artifacts without changing public repositories.
|
||||
The workflow selects the `-exec.jar` build output when present and falls back to
|
||||
the main JAR for older tags; the public versioned JAR name stays unchanged.
|
||||
|
||||
After verifying the dry run, release operators can run the same tag with
|
||||
`dry_run=false` through the protected `production-release` environment. The
|
||||
workflow sets the server artifact version to the CLI version, publishes
|
||||
`com.alibaba:qwen-managed-agent-server:<cli-version>` to Maven Central with
|
||||
sources, Javadoc and signatures, and distributes the same primary JAR plus its
|
||||
`.sha256` through that GitHub Release and the existing versioned OSS mirror.
|
||||
Auxiliary operator JARs are not attached to the Central publication. Existing
|
||||
assets are compared byte-for-byte and never replaced with different content.
|
||||
Published CLI release events also run this workflow automatically.
|
||||
the verified executable JAR plus its `.sha256` through that GitHub Release and the
|
||||
existing versioned OSS mirror, and checks both public download channels against
|
||||
the staged bytes. Existing assets are compared byte-for-byte and never replaced
|
||||
with different content. Published CLI release events also run this workflow
|
||||
automatically.
|
||||
|
||||
Runtime distribution requires the existing OSS upload credentials and GitHub
|
||||
release access. It does not need Central publishing credentials or a GPG private
|
||||
key, and does not check, publish or wait for the server coordinate on Central.
|
||||
Maven still builds and fully verifies the SDK and server, including normal
|
||||
dependency resolution. The existing `central-release` profile can
|
||||
be used separately for signed Maven publication when required; that operation
|
||||
does not gate runtime delivery.
|
||||
|
||||
The CLI downloads from OSS/GitHub, not Maven Central. It does not resolve the
|
||||
SDK as a separate user dependency: the executable server JAR includes its Java
|
||||
|
||||
@@ -201,15 +201,21 @@ Qwen home 下的版本化安装。存在相邻 payload 时,它优先于 Qwen h
|
||||
`Release Managed server runtime` workflow 从已公开的 CLI release tag 构建,使用
|
||||
相同源码修订的 SDK 和服务。手动运行必须从 `main` 发起,默认是 dry-run。它验证
|
||||
CLI 和 Java 模块,构建 `central-release` profile,并将 JAR 与校验文件保留为
|
||||
workflow artifact,不修改公开仓库。
|
||||
workflow artifact,不修改公开仓库。workflow 优先选择 `-exec.jar` 构建产物,
|
||||
对旧 tag 回退到主 JAR;公开的版本化 JAR 名称保持不变。
|
||||
|
||||
验证 dry-run 后,发行运维可通过受保护的 `production-release` environment,用
|
||||
相同 tag 和 `dry_run=false` 运行。workflow 将服务制品版本设为 CLI 版本,向
|
||||
Maven Central 发布 `com.alibaba:qwen-managed-agent-server:<cli-version>` 及源码、
|
||||
Javadoc 和签名,再将相同主 JAR 及其 `.sha256` 分发到该 GitHub Release 和现有的
|
||||
版本化 OSS 镜像。辅助运维 JAR 不附加到 Central 发布。已有产物逐字节比较,绝不
|
||||
相同 tag 和 `dry_run=false` 运行。workflow 将服务制品版本设为 CLI 版本,
|
||||
将验证后的可执行 JAR 及其 `.sha256` 分发到该 GitHub Release 和现有的版本化 OSS
|
||||
镜像,再将两个公开下载渠道的制品与暂存字节核对。已有产物逐字节比较,绝不
|
||||
用不同内容替换。公开的 CLI release 事件也会自动运行该 workflow。
|
||||
|
||||
runtime 分发需要现有 OSS 上传凭据和 GitHub release 权限,无需 Central 发布凭据或
|
||||
GPG 私钥,不探测服务坐标在 Central 上是否存在,不向 Central 发布或等待其完成。
|
||||
Maven 仍负责构建和完整验证 SDK 与服务,正常依赖解析保持不变。
|
||||
需要签名发布 Maven 制品时,可独立使用现有 `central-release`
|
||||
profile;该操作不阻塞 runtime 交付。
|
||||
|
||||
CLI 从 OSS/GitHub 下载,不从 Maven Central 下载,也不要求用户单独解析 SDK:
|
||||
可执行服务 JAR 包含其 Java 依赖。精确匹配 CLI release 的 runtime 产物必须已存在,
|
||||
首次下载才能成功。本 PR 的本地验证不会发布这些产物,也不会绕过生产发行环境。
|
||||
|
||||
@@ -28,12 +28,15 @@ existing MySQL defaults. Design:
|
||||
[简体中文](../../docs/design/2026-10-20-managed-local-serve.zh-CN.md).
|
||||
|
||||
The `central-release` Maven profile attaches sources, Javadoc and GPG signatures
|
||||
for the main executable server JAR, without attaching the auxiliary operator
|
||||
JARs. Ordinary builds keep the existing attachments and do not activate Central
|
||||
for server publication, without attaching the auxiliary operator JARs. The
|
||||
executable server JAR uses the `exec` classifier. Ordinary builds keep the existing attachments and do not activate Central
|
||||
publishing. The protected `Release Managed server runtime` workflow sets the
|
||||
artifact version from an existing CLI release tag and publishes identical JAR
|
||||
bytes to Central, GitHub Release assets and the official OSS mirror. The CLI's
|
||||
first-use download uses OSS/GitHub and requires no Maven installation. See the
|
||||
bytes and checksums to GitHub Release assets and the official OSS mirror after
|
||||
full SDK/server verification. Distribution does not require Central credentials,
|
||||
GPG signing or a successful Central publication. Signed Maven publication remains
|
||||
an independent operation using the existing profile. The CLI's first-use download
|
||||
uses OSS/GitHub and requires no Maven installation. See the
|
||||
[release procedure](../../docs/users/managed-local-serve.md#publish-the-first-use-jar)
|
||||
and its [Chinese version](../../docs/users/managed-local-serve.zh-CN.md#发布首次使用的-jar).
|
||||
|
||||
|
||||
@@ -364,7 +364,7 @@ setInterval(() => {}, 1000);
|
||||
describe('Managed runtime publication gates', () => {
|
||||
const steps = workflow.jobs.release.steps;
|
||||
const step = (name) => steps.find((item) => item.name === name);
|
||||
it('separates the Central dependency and executable bytes while retaining runtime download names', () => {
|
||||
it('stages the executable classifier while retaining legacy fallback and runtime download names', () => {
|
||||
const verification = step(
|
||||
'Verify the executable JAR and publication profile',
|
||||
).run;
|
||||
@@ -374,23 +374,12 @@ describe('Managed runtime publication gates', () => {
|
||||
expect(verification).toContain(
|
||||
'Main-Class: org.springframework.boot.loader.launch.JarLauncher',
|
||||
);
|
||||
expect(verification).toContain('MANAGED_RUNTIME_JAR=${runtime_jar}');
|
||||
const preflight = step(
|
||||
'Recheck the immutable tag and existing publication bytes',
|
||||
).run;
|
||||
expect(preflight).toContain(
|
||||
'central_files=("packages/managed-agent-server/target/${jar}")',
|
||||
expect(verification).toContain(
|
||||
'if [[ ! -f "${runtime_jar}" ]]; then runtime_jar="packages/managed-agent-server/target/qwen-managed-agent-server-${CLI_VERSION}.jar"; fi',
|
||||
);
|
||||
expect(preflight).toContain('central_files+=("${MANAGED_RUNTIME_JAR}")');
|
||||
expect(preflight).toContain(
|
||||
'Partial Central publication; refusing an immutable redeploy.',
|
||||
expect(verification).toContain(
|
||||
'--jar "${runtime_jar}" --version "${CLI_VERSION}" --out-dir dist/managed-runtime',
|
||||
);
|
||||
expect(step('Publish the signed server artifact to Central').run).toContain(
|
||||
'cmp "${MANAGED_RUNTIME_JAR}"',
|
||||
);
|
||||
expect(
|
||||
step('Verify Central availability before distribution').run,
|
||||
).toContain('missing == 0');
|
||||
expect(step('Verify both public download channels').run).toContain(
|
||||
'jar="qwen-managed-agent-server-${CLI_VERSION}.jar"',
|
||||
);
|
||||
@@ -409,8 +398,6 @@ describe('Managed runtime publication gates', () => {
|
||||
);
|
||||
for (const name of [
|
||||
'Recheck the immutable tag and existing publication bytes',
|
||||
'Configure signed Central publication',
|
||||
'Publish the signed server artifact to Central',
|
||||
'Attach only missing GitHub release assets',
|
||||
'Install the verified OSS uploader',
|
||||
'Configure authenticated OSS access',
|
||||
@@ -427,10 +414,31 @@ describe('Managed runtime publication gates', () => {
|
||||
(item) =>
|
||||
item.name === 'Verify the executable JAR and publication profile',
|
||||
);
|
||||
expect(build).toBeLessThan(
|
||||
steps.findIndex(
|
||||
(item) => item.name === 'Publish the signed server artifact to Central',
|
||||
),
|
||||
for (const name of [
|
||||
'Attach only missing GitHub release assets',
|
||||
'Upload only missing OSS release assets',
|
||||
]) {
|
||||
expect(build).toBeLessThan(steps.indexOf(step(name)));
|
||||
}
|
||||
});
|
||||
|
||||
it('distributes the verified runtime without Central publication access or signing credentials', () => {
|
||||
const definition = JSON.stringify(workflow);
|
||||
for (const dependency of [
|
||||
'CENTRAL_USERNAME',
|
||||
'CENTRAL_PASSWORD',
|
||||
'MAVEN_GPG_PRIVATE_KEY',
|
||||
'MAVEN_GPG_PASSPHRASE',
|
||||
'repo.maven.apache.org',
|
||||
'gpg-private-key',
|
||||
]) {
|
||||
expect(definition).not.toContain(dependency);
|
||||
}
|
||||
expect(steps.some((item) => /\bmvn\b.*\bdeploy\b/u.test(item.run))).toBe(
|
||||
false,
|
||||
);
|
||||
expect(workflow.on.workflow_dispatch.inputs.dry_run.description).toBe(
|
||||
'Build and verify without publishing to GitHub or OSS.',
|
||||
);
|
||||
});
|
||||
|
||||
@@ -444,8 +452,9 @@ describe('Managed runtime publication gates', () => {
|
||||
expect(steps.indexOf(install)).toBeLessThan(steps.indexOf(configure));
|
||||
expect(steps.indexOf(configure)).toBeLessThan(steps.indexOf(preflight));
|
||||
expect(steps.indexOf(preflight)).toBeLessThan(
|
||||
steps.indexOf(step('Publish the signed server artifact to Central')),
|
||||
steps.indexOf(step('Attach only missing GitHub release assets')),
|
||||
);
|
||||
expect(steps.indexOf(preflight)).toBeLessThan(steps.indexOf(upload));
|
||||
expect(install.env.OSSUTIL_URL).toContain('/1.7.19/');
|
||||
expect(install.env.OSSUTIL_SHA256).toBe(
|
||||
'dcc512e4a893e16bbee63bc769339d8e56b21744fd83c8212a9d8baf28767343',
|
||||
@@ -513,9 +522,6 @@ describe('Managed runtime publication gates', () => {
|
||||
expect(
|
||||
step('Verify the executable JAR and publication profile').run,
|
||||
).toContain('clean verify');
|
||||
expect(step('Publish the signed server artifact to Central').run).toContain(
|
||||
'cmp ',
|
||||
);
|
||||
});
|
||||
|
||||
it('isolates server test classes without filtering or bypassing release verification', () => {
|
||||
@@ -580,8 +586,6 @@ describe.skipIf(process.platform === 'win32')('release gate execution', () => {
|
||||
RELEASE_TAG: 'v0.25.4',
|
||||
EVENT_NAME: 'workflow_dispatch',
|
||||
WORKFLOW_REF: 'refs/heads/main',
|
||||
MANAGED_RUNTIME_JAR:
|
||||
'packages/managed-agent-server/target/qwen-managed-agent-server-0.25.4-exec.jar',
|
||||
...env,
|
||||
},
|
||||
encoding: 'utf8',
|
||||
@@ -648,58 +652,56 @@ describe.skipIf(process.platform === 'win32')('release gate execution', () => {
|
||||
expect(fs.existsSync(path.join(temporary, 'gh-called'))).toBe(false);
|
||||
});
|
||||
|
||||
it('refuses partial Central publication before attempting runtime channel writes', () => {
|
||||
it('prepares both distribution channels when Central publication is unavailable and its credentials are absent', () => {
|
||||
executable('git', "printf '%s\\tref\\n' original-sha");
|
||||
executable('gh', "printf '%s\\n' '{\"draft\":false}'");
|
||||
executable(
|
||||
'node',
|
||||
'case "$*" in *repo.maven.apache.org*exec.jar*) echo missing ;; *repo.maven.apache.org*) echo present ;; *) touch unexpected-channel; echo missing ;; esac',
|
||||
);
|
||||
const result = run(preflight, {
|
||||
SOURCE_SHA: 'original-sha',
|
||||
CLI_VERSION: '0.25.4',
|
||||
});
|
||||
expect(result.status).not.toBe(0);
|
||||
expect(result.stderr).toContain('Partial Central publication');
|
||||
expect(fs.existsSync(path.join(temporary, 'unexpected-channel'))).toBe(
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
it('retains the single Central artifact check for legacy executable release tags', () => {
|
||||
executable('git', "printf '%s\\tref\\n' original-sha");
|
||||
executable('gh', "printf '%s\\n' '{\"draft\":false}'");
|
||||
executable(
|
||||
'node',
|
||||
'case "$*" in *exec.jar*) echo unexpected-exec >&2; exit 1 ;; *) echo missing ;; esac',
|
||||
'case "$*" in *repo.maven.apache.org*) echo unexpected-central >&2; exit 7 ;; *) echo missing ;; esac',
|
||||
);
|
||||
const result = run(preflight, {
|
||||
SOURCE_SHA: 'original-sha',
|
||||
CLI_VERSION: '0.25.4',
|
||||
ALIYUN_OSS_BUCKET: 'release-bucket',
|
||||
MANAGED_RUNTIME_JAR:
|
||||
'packages/managed-agent-server/target/qwen-managed-agent-server-0.25.4.jar',
|
||||
CENTRAL_USERNAME: '',
|
||||
CENTRAL_PASSWORD: '',
|
||||
MAVEN_USERNAME: '',
|
||||
MAVEN_PASSWORD: '',
|
||||
MAVEN_GPG_PRIVATE_KEY: '',
|
||||
MAVEN_GPG_PASSPHRASE: '',
|
||||
});
|
||||
expect(result.status, result.stderr).toBe(0);
|
||||
expect(fs.readFileSync(path.join(temporary, 'output'), 'utf8')).toContain(
|
||||
'central=missing',
|
||||
);
|
||||
expect(result.status).toBe(0);
|
||||
for (const channel of ['github', 'oss']) {
|
||||
expect(
|
||||
fs.readFileSync(
|
||||
path.join(temporary, `managed-${channel}-missing`),
|
||||
'utf8',
|
||||
),
|
||||
).toBe(
|
||||
'dist/managed-runtime/qwen-managed-agent-server-0.25.4.jar\n' +
|
||||
'dist/managed-runtime/qwen-managed-agent-server-0.25.4.jar.sha256\n',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('aborts preflight on an artifact-verification error instead of treating it as present', () => {
|
||||
executable('git', "printf '%s\\tref\\n' original-sha");
|
||||
executable('gh', "printf '%s\\n' '{\"draft\":false}'");
|
||||
executable(
|
||||
'node',
|
||||
'case "$*" in *github.com*".jar --file "*) echo mismatch >&2; exit 7 ;; *repo.maven.apache.org*) echo present ;; *) echo missing ;; esac',
|
||||
);
|
||||
const result = run(preflight, {
|
||||
SOURCE_SHA: 'original-sha',
|
||||
CLI_VERSION: '0.25.4',
|
||||
OSS_PUBLIC_BASE_URL: 'https://example.com',
|
||||
ALIYUN_OSS_BUCKET: 'release-bucket',
|
||||
});
|
||||
expect(result.status).not.toBe(0);
|
||||
expect(result.stderr).toContain('mismatch');
|
||||
});
|
||||
it.each(['github.com', 'oss://'])(
|
||||
'aborts preflight on a %s artifact-verification error instead of treating it as present',
|
||||
(channel) => {
|
||||
executable('git', "printf '%s\\tref\\n' original-sha");
|
||||
executable('gh', "printf '%s\\n' '{\"draft\":false}'");
|
||||
executable(
|
||||
'node',
|
||||
'case "$*" in *"$MISMATCH_HOST"*) echo mismatch >&2; exit 7 ;; *) echo missing ;; esac',
|
||||
);
|
||||
const result = run(preflight, {
|
||||
SOURCE_SHA: 'original-sha',
|
||||
CLI_VERSION: '0.25.4',
|
||||
OSS_PUBLIC_BASE_URL: 'https://example.com',
|
||||
ALIYUN_OSS_BUCKET: 'release-bucket',
|
||||
MISMATCH_HOST: channel,
|
||||
});
|
||||
expect(result.status).not.toBe(0);
|
||||
expect(result.stderr).toContain('mismatch');
|
||||
},
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user