diff --git a/.gitea/workflows/gateway-build.yml b/.gitea/workflows/gateway-build.yml index 0e56d10..d6aed6c 100644 --- a/.gitea/workflows/gateway-build.yml +++ b/.gitea/workflows/gateway-build.yml @@ -119,8 +119,9 @@ jobs: docker info 2>/dev/null | sed -n '/HTTP Proxy:/p;/HTTPS Proxy:/p;/Name:/p' if ! docker image inspect "${{ env.BASE_IMAGE }}" >/dev/null 2>&1 \ - || ! docker run --rm "${{ env.BASE_IMAGE }}" sh -lc 'command -v npm >/dev/null'; then - echo "Runtime base image ${{ env.BASE_IMAGE }} is missing npm; building it now." + || ! docker run --rm "${{ env.BASE_IMAGE }}" sh -lc \ + 'command -v npm >/dev/null && sing-box version 2>&1 | grep -Fx "sing-box version ${{ env.SINGBOX_VERSION }}"'; then + echo "Runtime base image ${{ env.BASE_IMAGE }} is missing npm or sing-box ${{ env.SINGBOX_VERSION }}; building it now." BASE_IMAGE="${{ env.RUNTIME_BASE_SOURCE_IMAGE }}" \ RUNTIME_BASE_IMAGE="${{ env.BASE_IMAGE }}" \ APT_MIRROR="${{ env.APT_MIRROR }}" \ @@ -143,6 +144,10 @@ jobs: -t "${DATAPLANE_IMAGE}:latest" \ -t "${DATAPLANE_IMAGE}:${{ gitea.sha }}" \ . + docker run --rm --entrypoint sing-box "${CONTROL_IMAGE}:${{ gitea.sha }}" version 2>&1 \ + | grep -Fx "sing-box version ${{ env.SINGBOX_VERSION }}" + docker run --rm --entrypoint sing-box "${DATAPLANE_IMAGE}:${{ gitea.sha }}" version 2>&1 \ + | grep -Fx "sing-box version ${{ env.SINGBOX_VERSION }}" docker push "${CONTROL_IMAGE}:latest" docker push "${CONTROL_IMAGE}:${{ gitea.sha }}" docker push "${DATAPLANE_IMAGE}:latest" @@ -197,3 +202,7 @@ jobs: DATAPLANE_IMAGE="${DATAPLANE_IMAGE}" \ UPDATE_DATAPLANE="${UPDATE_DATAPLANE}" \ bash scripts/deploy-gateway.sh + VERSION_JSON="$(curl --noproxy '*' -fsS http://127.0.0.1:3456/api/version)" + printf '%s\n' "$VERSION_JSON" + printf '%s\n' "$VERSION_JSON" \ + | grep -F "\"singBox\":\"${{ env.SINGBOX_VERSION }}\"" diff --git a/scripts/install-macos-client.sh b/scripts/install-macos-client.sh index ed5ccac..048b5cd 100755 --- a/scripts/install-macos-client.sh +++ b/scripts/install-macos-client.sh @@ -9,6 +9,7 @@ COMPOSE_FILE="docker-compose.client.yml" DEFAULT_PROXY_PORT="8082" REQUESTED_PROXY_PORT="${VPN_PROXY_CLIENT_PORT:-}" REQUESTED_UI_PORT="${VPN_PROXY_CLIENT_UI_PORT:-${CLIENT_UI_PORT:-}}" +TARGET_SINGBOX_VERSION="${SINGBOX_VERSION:-1.13.18}" CLIENT_CONTAINER_NAME="harbor-connect" LEGACY_CLIENT_CONTAINER_NAME="vpn-proxy-client" NETWORK_MONITOR_LABEL="com.dokril.harbor-connect.network" @@ -319,6 +320,7 @@ UI_PORT="$(choose_ui_port "$UI_PORT")" assert_ui_outside_proxy_range set_env_value APP_MODE client +set_env_value SINGBOX_VERSION "$TARGET_SINGBOX_VERSION" set_env_value CLIENT_UI_PORT "$UI_PORT" set_env_value CLIENT_PROXY_PORT "$PROXY_PORT" set_env_value PROXY_PORT "$PROXY_PORT" diff --git a/src/shared/versions.ts b/src/shared/versions.ts index 1067ceb..26a4367 100644 --- a/src/shared/versions.ts +++ b/src/shared/versions.ts @@ -1,7 +1,7 @@ export const HARBOR_VERSIONS = Object.freeze({ - macClient: '0.21.3', + macClient: '0.21.4', gatewayClient: '0.22.0', - gatewayBackend: '0.22.3', + gatewayBackend: '0.22.4', }); export interface ParsedVersion { diff --git a/test/install-script.test.js b/test/install-script.test.js index 12c59f9..8b83664 100644 --- a/test/install-script.test.js +++ b/test/install-script.test.js @@ -49,3 +49,10 @@ test('macOS installer removes stale archive files without deleting local state', assert.match(installer, /--exclude='\.runtime'/); assert.match(installer, /--exclude='\.git'/); }); + +test('macOS installer refreshes a stale pinned sing-box version', () => { + const installer = fs.readFileSync(path.join(root, 'scripts', 'install-macos-client.sh'), 'utf8'); + + assert.match(installer, /TARGET_SINGBOX_VERSION="\$\{SINGBOX_VERSION:-1\.13\.18\}"/); + assert.match(installer, /set_env_value SINGBOX_VERSION "\$TARGET_SINGBOX_VERSION"/); +}); diff --git a/test/server/deploy-split.test.js b/test/server/deploy-split.test.js index 75bf60b..f375ce0 100644 --- a/test/server/deploy-split.test.js +++ b/test/server/deploy-split.test.js @@ -26,6 +26,9 @@ test('gateway deploy updates control without recreating dataplane', () => { assert.match(workflow, /npm_status=\$\?[\s\S]*! -x node_modules\/\.bin\/tsc[\s\S]*tail -n 200 \/root\/\.npm\/_logs\/\*-debug-0\.log[\s\S]*exit 1/); assert.match(workflow, /npm test[\s\S]*Image build and push skipped: no Gateway runtime impact\.[\s\S]*exit 0[\s\S]*docker login/); assert.match(workflow, /Image build and push skipped: no Gateway runtime impact\.[\s\S]*exit 0[\s\S]*\.\/scripts\/build-runtime-base\.sh/); + assert.match(workflow, /sing-box version \$\{\{ env\.SINGBOX_VERSION \}\}[\s\S]*\.\/scripts\/build-runtime-base\.sh/); + assert.match(workflow, /--entrypoint sing-box[\s\S]*grep -Fx "sing-box version \$\{\{ env\.SINGBOX_VERSION \}\}"/); + assert.match(workflow, /api\/version[\s\S]*singBox/); assert.match(workflow, /Deploy skipped: no Gateway runtime impact\.[\s\S]*exit 0[\s\S]*bash scripts\/deploy-gateway\.sh/); assert.doesNotMatch(workflow, /grep -Eq/); });