mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-04 12:13:09 +00:00
hotfix(docker): select Alpine-compatible CLIProxy asset
This commit is contained in:
1 parent
a31f1ec79c
commit
003342f604
5 files changed
+108
-3
No files matched your search
@@ -365,6 +365,14 @@ jobs:
|
||||
-p 18317:8317 \
|
||||
"${{ steps.image.outputs.ref }}"
|
||||
|
||||
print_service_logs() {
|
||||
docker logs "${CONTAINER_NAME}" --tail 100 >&2 || true
|
||||
docker exec "${CONTAINER_NAME}" \
|
||||
sh -c 'tail -n 100 /var/log/ccs/cliproxy.log' >&2 || true
|
||||
docker exec "${CONTAINER_NAME}" \
|
||||
sh -c 'tail -n 100 /var/log/ccs/ccs-dashboard.log' >&2 || true
|
||||
}
|
||||
|
||||
echo "[i] Waiting for container healthcheck (up to 60s)..."
|
||||
HEALTHY=0
|
||||
for i in $(seq 1 12); do
|
||||
@@ -376,7 +384,7 @@ jobs:
|
||||
fi
|
||||
if [[ "${STATUS}" == "unhealthy" ]]; then
|
||||
echo "[X] Container marked unhealthy"
|
||||
docker logs "${CONTAINER_NAME}" --tail 50 >&2
|
||||
print_service_logs
|
||||
exit 1
|
||||
fi
|
||||
echo " [${i}/12] status=${STATUS}, waiting 5s..."
|
||||
@@ -384,7 +392,7 @@ jobs:
|
||||
done
|
||||
if [[ "${HEALTHY}" -ne 1 ]]; then
|
||||
echo "[X] Container did not become healthy within 60s (last status: ${STATUS})" >&2
|
||||
docker logs "${CONTAINER_NAME}" --tail 100 >&2
|
||||
print_service_logs
|
||||
docker inspect "${CONTAINER_NAME}" --format='{{json .State}}' >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
@@ -7,6 +7,8 @@ FROM eceasy/cli-proxy-api:latest@sha256:4fa722b9ff83adfbe6e350d433b7dcb754756aa6
|
||||
|
||||
ARG CCS_NPM_VERSION=latest
|
||||
|
||||
ENV CCS_CLIPROXY_NO_PLUGIN_ASSET=1
|
||||
|
||||
# CCS integrated image: CCS CLI + CLIProxy + supervisord.
|
||||
# Design choice (issue #1251 final scope): single-image strategy. The originally-
|
||||
# proposed `:full` variant bundling claude-code/gemini-cli/grok-cli/opencode was
|
||||
|
||||
@@ -166,7 +166,17 @@ export function detectPlatform(
|
||||
const ver = version || config.fallbackVersion;
|
||||
const extension: ArchiveExtension = os === 'windows' ? 'zip' : 'tar.gz';
|
||||
const assetArch = getReleaseArchForBackend(backend, ver, arch, releaseArch);
|
||||
const assetVariant = backend === 'plus' && usesPlusNoPluginAsset(ver, os) ? '_no-plugin' : '';
|
||||
// The integrated Alpine image opts into the portable static upstream asset.
|
||||
// Normal Linux installs keep plugin-capable archives for backward compatibility.
|
||||
const usesOriginalNoPluginAsset =
|
||||
process.env.CCS_CLIPROXY_NO_PLUGIN_ASSET === '1' &&
|
||||
backend === 'original' &&
|
||||
os === 'linux' &&
|
||||
isAtLeastVersion(ver, '7.1.52');
|
||||
const assetVariant =
|
||||
usesOriginalNoPluginAsset || (backend === 'plus' && usesPlusNoPluginAsset(ver, os))
|
||||
? '_no-plugin'
|
||||
: '';
|
||||
const binaryName = `${config.binaryPrefix}_${ver}_${os}_${assetArch}${assetVariant}.${extension}`;
|
||||
|
||||
return {
|
||||
|
||||
@@ -24,6 +24,26 @@ describe('Backend Selection', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function withEnvironmentVariable(name, value, callback) {
|
||||
const originalValue = process.env[name];
|
||||
|
||||
if (value === undefined) {
|
||||
delete process.env[name];
|
||||
} else {
|
||||
process.env[name] = value;
|
||||
}
|
||||
|
||||
try {
|
||||
callback();
|
||||
} finally {
|
||||
if (originalValue === undefined) {
|
||||
delete process.env[name];
|
||||
} else {
|
||||
process.env[name] = originalValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('BACKEND_CONFIG', () => {
|
||||
it('has correct configuration for original backend', () => {
|
||||
const config = platformDetector.BACKEND_CONFIG.original;
|
||||
@@ -73,6 +93,62 @@ describe('Backend Selection', () => {
|
||||
assert(!info.binaryName.includes('CLIProxyAPIPlus'));
|
||||
});
|
||||
|
||||
it('uses static no-plugin assets when the integrated Linux image opts in', () => {
|
||||
withEnvironmentVariable('CCS_CLIPROXY_NO_PLUGIN_ASSET', '1', () => {
|
||||
withMockedProcessPlatform('linux', 'x64', () => {
|
||||
assert.strictEqual(
|
||||
platformDetector.detectPlatform('7.2.88', 'original').binaryName,
|
||||
'CLIProxyAPI_7.2.88_linux_amd64_no-plugin.tar.gz'
|
||||
);
|
||||
assert.strictEqual(
|
||||
platformDetector.getDownloadUrl('7.2.88', 'original'),
|
||||
'https://github.com/router-for-me/CLIProxyAPI/releases/download/v7.2.88/CLIProxyAPI_7.2.88_linux_amd64_no-plugin.tar.gz'
|
||||
);
|
||||
});
|
||||
|
||||
withMockedProcessPlatform('linux', 'arm64', () => {
|
||||
assert.strictEqual(
|
||||
platformDetector.detectPlatform('7.2.88', 'original').binaryName,
|
||||
'CLIProxyAPI_7.2.88_linux_aarch64_no-plugin.tar.gz'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps plugin-capable original archives for normal Linux installs', () => {
|
||||
withMockedProcessPlatform('linux', 'arm64', () => {
|
||||
assert.strictEqual(
|
||||
platformDetector.detectPlatform('7.2.88', 'original').binaryName,
|
||||
'CLIProxyAPI_7.2.88_linux_aarch64.tar.gz'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps original archive names compatible before Linux no-plugin assets existed', () => {
|
||||
withEnvironmentVariable('CCS_CLIPROXY_NO_PLUGIN_ASSET', '1', () => {
|
||||
withMockedProcessPlatform('linux', 'x64', () => {
|
||||
assert.strictEqual(
|
||||
platformDetector.detectPlatform('7.1.51', 'original').binaryName,
|
||||
'CLIProxyAPI_7.1.51_linux_amd64.tar.gz'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
withMockedProcessPlatform('darwin', 'arm64', () => {
|
||||
assert.strictEqual(
|
||||
platformDetector.detectPlatform('7.2.88', 'original').binaryName,
|
||||
'CLIProxyAPI_7.2.88_darwin_aarch64.tar.gz'
|
||||
);
|
||||
});
|
||||
|
||||
withMockedProcessPlatform('win32', 'x64', () => {
|
||||
assert.strictEqual(
|
||||
platformDetector.detectPlatform('7.2.88', 'original').binaryName,
|
||||
'CLIProxyAPI_7.2.88_windows_amd64.zip'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps old plus non-Windows archive names unsuffixed', () => {
|
||||
withMockedProcessPlatform('darwin', 'arm64', () => {
|
||||
assert.strictEqual(
|
||||
|
||||
@@ -43,6 +43,15 @@ describe('docker release workflow context', () => {
|
||||
expect(dockerfile).toContain('HEALTHCHECK');
|
||||
expect(dockerfile).toContain('127.0.0.1:3000');
|
||||
expect(dockerfile).toContain('127.0.0.1:8317');
|
||||
expect(dockerfile).toContain('ENV CCS_CLIPROXY_NO_PLUGIN_ASSET=1');
|
||||
});
|
||||
|
||||
test('prints service logs when the integrated image fails its healthcheck', () => {
|
||||
const workflow = readFileSync(join(repoRoot, '.github/workflows/docker-release.yml'), 'utf8');
|
||||
|
||||
expect(workflow).toContain('docker logs "${CONTAINER_NAME}"');
|
||||
expect(workflow).toContain('/var/log/ccs/cliproxy.log');
|
||||
expect(workflow).toContain('/var/log/ccs/ccs-dashboard.log');
|
||||
});
|
||||
|
||||
test('lets network-contract smoke tests avoid fixed host port collisions', () => {
|
||||
|
||||
Reference in new issue
Block a user