Refactor VPN proxy client implementation
This commit is contained in:
@@ -8,6 +8,7 @@ on:
|
||||
env:
|
||||
DEPLOY_PATH: /opt/vpn-proxy
|
||||
BASE_IMAGE: vpn-proxy-runtime-base:bookworm-slim
|
||||
NODE_BUILD_IMAGE: node:20.19-alpine
|
||||
RUNTIME_BASE_SOURCE_IMAGE: mirror.gcr.io/library/debian:bookworm-slim
|
||||
APT_MIRROR: http://mirror.yandex.ru/debian
|
||||
APT_SECURITY_MIRROR: http://mirror.yandex.ru/debian-security
|
||||
@@ -16,6 +17,9 @@ env:
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-22.04
|
||||
outputs:
|
||||
affected_components: ${{ steps['gateway-build'].outputs.affected_components }}
|
||||
restart_scope: ${{ steps['gateway-build'].outputs.restart_scope }}
|
||||
steps:
|
||||
- name: Clone repository
|
||||
env:
|
||||
@@ -24,11 +28,12 @@ jobs:
|
||||
set -euo pipefail
|
||||
SERVER_HOST=$(echo "${{ gitea.server_url }}" | sed 's|https\?://||')
|
||||
rm -rf repo
|
||||
git clone --depth 2 "http://${{ gitea.actor }}:${GIT_TOKEN}@${SERVER_HOST}/${{ gitea.repository }}.git" repo
|
||||
git clone "http://${{ gitea.actor }}:${GIT_TOKEN}@${SERVER_HOST}/${{ gitea.repository }}.git" repo
|
||||
cd repo
|
||||
git checkout ${{ gitea.sha }}
|
||||
|
||||
- name: Build and push gateway image
|
||||
id: gateway-build
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd repo
|
||||
@@ -38,6 +43,68 @@ jobs:
|
||||
CONTROL_IMAGE="${IMAGE}-control"
|
||||
DATAPLANE_IMAGE="${IMAGE}-dataplane"
|
||||
|
||||
EVENT_NAME="${{ gitea.event_name }}"
|
||||
BEFORE_SHA="${{ gitea.event.before }}"
|
||||
ZERO_SHA="0000000000000000000000000000000000000000"
|
||||
if [ "$EVENT_NAME" = "push" ] \
|
||||
&& [ -n "$BEFORE_SHA" ] \
|
||||
&& [ "$BEFORE_SHA" != "$ZERO_SHA" ] \
|
||||
&& git cat-file -e "${BEFORE_SHA}^{commit}" 2>/dev/null; then
|
||||
CHANGED_FILES="$(git diff --no-renames --name-only "$BEFORE_SHA" "${{ gitea.sha }}")"
|
||||
elif [ "$EVENT_NAME" = "push" ]; then
|
||||
CHANGED_FILES="package.json"
|
||||
else
|
||||
CHANGED_FILES="$(git diff-tree --no-renames --no-commit-id --name-only -r -m HEAD)"
|
||||
fi
|
||||
if command -v node >/dev/null 2>&1; then
|
||||
RUNTIME_IMPACT="$(printf '%s\n' "$CHANGED_FILES" | node scripts/runtime-impact.mjs --stdin)"
|
||||
else
|
||||
if ! docker image inspect "${{ env.BASE_IMAGE }}" >/dev/null 2>&1 \
|
||||
|| ! docker run --rm "${{ env.BASE_IMAGE }}" sh -lc 'command -v node >/dev/null'; then
|
||||
echo "Cannot classify runtime impact: Node and the existing runtime base are unavailable." >&2
|
||||
exit 1
|
||||
fi
|
||||
RUNTIME_IMPACT="$(printf '%s\n' "$CHANGED_FILES" | docker run --rm -i \
|
||||
-v "$PWD:/work" \
|
||||
-w /work \
|
||||
"${{ env.BASE_IMAGE }}" \
|
||||
node scripts/runtime-impact.mjs --stdin)"
|
||||
fi
|
||||
AFFECTED_COMPONENTS="$(printf '%s\n' "$RUNTIME_IMPACT" | sed -n 's/^affected-components=//p')"
|
||||
RESTART_SCOPE="$(printf '%s\n' "$RUNTIME_IMPACT" | sed -n 's/^restart-scope=//p')"
|
||||
case "${AFFECTED_COMPONENTS}:${RESTART_SCOPE}" in
|
||||
none:none|control:control|dataplane:both|control+dataplane:both) ;;
|
||||
*) echo "Invalid runtime impact: ${RUNTIME_IMPACT}" >&2; exit 1 ;;
|
||||
esac
|
||||
echo "Affected components: ${AFFECTED_COMPONENTS}"
|
||||
echo "Restart scope: ${RESTART_SCOPE}"
|
||||
echo "affected_components=${AFFECTED_COMPONENTS}" >> "$GITHUB_OUTPUT"
|
||||
echo "restart_scope=${RESTART_SCOPE}" >> "$GITHUB_OUTPUT"
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
npm ci --no-audit --no-fund
|
||||
npm run typecheck
|
||||
npm run check:boundaries
|
||||
npm test
|
||||
npm run build:production
|
||||
else
|
||||
if ! docker image inspect "${{ env.NODE_BUILD_IMAGE }}" >/dev/null 2>&1 \
|
||||
|| ! docker run --rm "${{ env.NODE_BUILD_IMAGE }}" sh -lc 'command -v npm >/dev/null'; then
|
||||
echo "Cannot validate change: host npm and the existing Node 20.19 build image are unavailable." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Host npm not found; validating inside ${{ env.NODE_BUILD_IMAGE }}"
|
||||
docker run --rm \
|
||||
--network host \
|
||||
-v "$PWD:/work" \
|
||||
-w /work \
|
||||
"${{ env.NODE_BUILD_IMAGE }}" \
|
||||
sh -lc 'npm ci --no-audit --no-fund && npm run typecheck && npm run check:boundaries && npm test && npm run build:production'
|
||||
fi
|
||||
if [ "$RESTART_SCOPE" = "none" ]; then
|
||||
echo "Image build and push skipped: no Gateway runtime impact."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Build runner: $(hostname)"
|
||||
echo "Base image: ${{ env.BASE_IMAGE }}"
|
||||
echo "Docker context: $(docker context show 2>/dev/null || true)"
|
||||
@@ -54,23 +121,11 @@ jobs:
|
||||
./scripts/build-runtime-base.sh
|
||||
fi
|
||||
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
npm ci --no-audit --no-fund
|
||||
npm run build
|
||||
else
|
||||
echo "Host npm not found; building frontend inside ${{ env.BASE_IMAGE }}"
|
||||
docker run --rm \
|
||||
--network host \
|
||||
-v "$PWD:/work" \
|
||||
-w /work \
|
||||
"${{ env.BASE_IMAGE }}" \
|
||||
sh -lc 'npm ci --no-audit --no-fund && npm run build'
|
||||
fi
|
||||
|
||||
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "$REGISTRY_HOST" -u "${{ gitea.actor }}" --password-stdin
|
||||
DOCKER_BUILDKIT=1 docker build \
|
||||
--network host \
|
||||
--pull=false \
|
||||
--build-arg NODE_BUILD_IMAGE="${{ env.NODE_BUILD_IMAGE }}" \
|
||||
--build-arg BASE_IMAGE="${{ env.BASE_IMAGE }}" \
|
||||
--build-arg SINGBOX_VERSION="${{ env.SINGBOX_VERSION }}" \
|
||||
--build-arg INSTALL_RUNTIME_DEPS=false \
|
||||
@@ -109,13 +164,24 @@ jobs:
|
||||
IMAGE="${REGISTRY_HOST}/${{ gitea.repository }}/gateway"
|
||||
CONTROL_IMAGE="${IMAGE}-control:${{ gitea.sha }}"
|
||||
DATAPLANE_IMAGE="${IMAGE}-dataplane:${{ gitea.sha }}"
|
||||
AFFECTED_COMPONENTS="${{ needs['build-and-push'].outputs.affected_components }}"
|
||||
RESTART_SCOPE="${{ needs['build-and-push'].outputs.restart_scope }}"
|
||||
case "${AFFECTED_COMPONENTS}:${RESTART_SCOPE}" in
|
||||
none:none|control:control|dataplane:both|control+dataplane:both) ;;
|
||||
*) echo "Invalid runtime impact output: ${AFFECTED_COMPONENTS}:${RESTART_SCOPE}" >&2; exit 1 ;;
|
||||
esac
|
||||
if [ "$RESTART_SCOPE" = "none" ]; then
|
||||
echo "Deploy skipped: no Gateway runtime impact."
|
||||
exit 0
|
||||
fi
|
||||
UPDATE_DATAPLANE=false
|
||||
if git diff-tree --no-commit-id --name-only -r -m HEAD | grep -Eq \
|
||||
'^(Dockerfile|entrypoint\.sh|package(-lock)?\.json|scripts/build-runtime-base\.sh|\.gitea/workflows/gateway-build\.yml|src/server/(config|dataplane|gatewayRouting|singbox|singboxRuntime|version)\.js|src/server/(adapters/neighbors|services/(connectivityDiagnosticsService|deviceTrafficService|devicePolicyService))\.js|src/shared/(connectivityDiagnostics|errors)\.js)$'; then
|
||||
if [ "$RESTART_SCOPE" = "both" ]; then
|
||||
UPDATE_DATAPLANE=true
|
||||
fi
|
||||
|
||||
echo "Deploy runner: $(hostname)"
|
||||
echo "Affected components: ${AFFECTED_COMPONENTS}"
|
||||
echo "Restart scope: ${RESTART_SCOPE}"
|
||||
echo "Update dataplane: ${UPDATE_DATAPLANE}"
|
||||
echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "$REGISTRY_HOST" -u "${{ gitea.actor }}" --password-stdin
|
||||
DEPLOY_PATH="${{ env.DEPLOY_PATH }}" \
|
||||
|
||||
Reference in New Issue
Block a user