Files
live_recorder/Jenkinsfile
T
2026-05-08 20:33:03 +08:00

252 lines
11 KiB
Groovy

pipeline {
agent { label '构建机1' }
options {
timestamps()
disableConcurrentBuilds()
skipDefaultCheckout(true)
}
environment {
REGISTRY_URL = 'reg.nxsir.cn'
API_IMAGE_NAME = 'liverecorder/app-api'
WEB_IMAGE_NAME = 'liverecorder/app-web'
IMAGE_TAG = "${env.BUILD_ID}"
DOCKER_CREDS = 'harbor_key'
TARGET_PLATFORMS = 'linux/amd64,linux/arm64'
BUILDER_NAME = 'liverecorder-buildx'
WEB_NODE_IMAGE = 'docker.m.daocloud.io/library/node:22-alpine'
WEB_NGINX_IMAGE = 'docker.m.daocloud.io/library/nginx:1.27-alpine'
GIT_REPO_URL = 'https://gitea.nxsir.cn/nanxun/live_recorder.git'
GIT_BRANCH = 'main'
GIT_CREDS = ''
API_IMAGE_TAGGED = "${REGISTRY_URL}/${API_IMAGE_NAME}:${IMAGE_TAG}"
API_IMAGE_LATEST = "${REGISTRY_URL}/${API_IMAGE_NAME}:latest"
WEB_IMAGE_TAGGED = "${REGISTRY_URL}/${WEB_IMAGE_NAME}:${IMAGE_TAG}"
WEB_IMAGE_LATEST = "${REGISTRY_URL}/${WEB_IMAGE_NAME}:latest"
}
stages {
stage('Checkout') {
steps {
script {
def userRemoteConfig = [url: env.GIT_REPO_URL]
if (env.GIT_CREDS?.trim()) {
userRemoteConfig.credentialsId = env.GIT_CREDS.trim()
}
checkout([
$class: 'GitSCM',
branches: [[name: "*/${env.GIT_BRANCH}"]],
userRemoteConfigs: [userRemoteConfig]
])
}
}
}
stage('Prepare Buildx') {
steps {
sh """
set -e
sudo docker buildx version
sudo docker run --privileged --rm tonistiigi/binfmt --install arm64
# 强制清理旧的 builder 实例,防止僵尸状态
sudo docker buildx rm ${BUILDER_NAME} || true
"""
}
}
stage('Login Registry') {
steps {
withCredentials([
usernamePassword(
credentialsId: "${DOCKER_CREDS}",
usernameVariable: 'DOCKER_USERNAME',
passwordVariable: 'DOCKER_PASSWORD'
)
]) {
sh """
set -e
echo "\$DOCKER_PASSWORD" | sudo docker login ${REGISTRY_URL} -u "\$DOCKER_USERNAME" --password-stdin
"""
}
}
}
stage('Build And Push API Image') {
steps {
sh """
set -e
run_with_heartbeat() {
log_file="\$1"
shift
rm -f "\$log_file"
: > "\$log_file"
"\$@" >"\$log_file" 2>&1 &
cmd_pid=\$!
last_line=0
cmd_status=0
while kill -0 "\$cmd_pid" >/dev/null 2>&1; do
if [ -f "\$log_file" ]; then
total_lines=\$(wc -l < "\$log_file" || echo 0)
else
total_lines=0
fi
if [ "\$total_lines" -gt "\$last_line" ]; then
sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file"
last_line=\$total_lines
else
echo "[heartbeat] API multi-arch build still running at \$(date -u +%Y-%m-%dT%H:%M:%SZ)"
fi
sleep 20
done
wait "\$cmd_pid" || cmd_status=\$?
if [ -f "\$log_file" ]; then
total_lines=\$(wc -l < "\$log_file" || echo 0)
if [ "\$total_lines" -gt "\$last_line" ]; then
sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file"
fi
fi
if [ "\$cmd_status" -ne 0 ]; then
echo "[heartbeat] API multi-arch build failed with exit code \$cmd_status"
fi
return "\$cmd_status"
}
if ! sudo docker buildx inspect --builder ${BUILDER_NAME} >/dev/null 2>&1; then
sudo docker buildx create \
--name ${BUILDER_NAME} \
--driver docker-container \
--driver-opt network=host \
--driver-opt 'env.HTTP_PROXY=http://192.168.5.200:7890' \
--driver-opt 'env.HTTPS_PROXY=http://192.168.5.200:7890' \
--driver-opt 'env.NO_PROXY=reg.nxsir.cn' \
--driver-opt 'env.http_proxy=http://192.168.5.200:7890' \
--driver-opt 'env.https_proxy=http://192.168.5.200:7890' \
--driver-opt 'env.no_proxy=reg.nxsir.cn' \
--use
fi
sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null
echo 'Building and pushing multi-arch API image: ${API_IMAGE_TAGGED}'
run_with_heartbeat /tmp/live-recorder-api-buildx-${IMAGE_TAG}.log \
sudo docker buildx build \
--builder ${BUILDER_NAME} \
--platform ${TARGET_PLATFORMS} \
--network host \
--progress=plain \
--provenance=false \
--build-arg HTTP_PROXY=http://192.168.5.200:7890 \
--build-arg HTTPS_PROXY=http://192.168.5.200:7890 \
--build-arg NO_PROXY=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \
--build-arg http_proxy=http://192.168.5.200:7890 \
--build-arg https_proxy=http://192.168.5.200:7890 \
--build-arg no_proxy=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \
-f src/LiveRecorder.WebApi/Dockerfile \
-t ${API_IMAGE_TAGGED} \
-t ${API_IMAGE_LATEST} \
--push \
.
"""
}
}
stage('Build And Push Web Image') {
steps {
sh """
set -e
run_with_heartbeat() {
log_file="\$1"
shift
rm -f "\$log_file"
: > "\$log_file"
"\$@" >"\$log_file" 2>&1 &
cmd_pid=\$!
last_line=0
cmd_status=0
while kill -0 "\$cmd_pid" >/dev/null 2>&1; do
if [ -f "\$log_file" ]; then
total_lines=\$(wc -l < "\$log_file" || echo 0)
else
total_lines=0
fi
if [ "\$total_lines" -gt "\$last_line" ]; then
sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file"
last_line=\$total_lines
else
echo "[heartbeat] Web multi-arch build still running at \$(date -u +%Y-%m-%dT%H:%M:%SZ)"
fi
sleep 20
done
wait "\$cmd_pid" || cmd_status=\$?
if [ -f "\$log_file" ]; then
total_lines=\$(wc -l < "\$log_file" || echo 0)
if [ "\$total_lines" -gt "\$last_line" ]; then
sed -n "\$((last_line + 1)),\${total_lines}p" "\$log_file"
fi
fi
if [ "\$cmd_status" -ne 0 ]; then
echo "[heartbeat] Web multi-arch build failed with exit code \$cmd_status"
fi
return "\$cmd_status"
}
if ! sudo docker buildx inspect --builder ${BUILDER_NAME} >/dev/null 2>&1; then
sudo docker buildx create \
--name ${BUILDER_NAME} \
--driver docker-container \
--driver-opt network=host \
--driver-opt 'env.HTTP_PROXY=http://192.168.5.200:7890' \
--driver-opt 'env.HTTPS_PROXY=http://192.168.5.200:7890' \
--driver-opt 'env.NO_PROXY=reg.nxsir.cn' \
--driver-opt 'env.http_proxy=http://192.168.5.200:7890' \
--driver-opt 'env.https_proxy=http://192.168.5.200:7890' \
--driver-opt 'env.no_proxy=reg.nxsir.cn' \
--use
fi
sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null
echo 'Building and pushing multi-arch Web image: ${WEB_IMAGE_TAGGED}'
run_with_heartbeat /tmp/live-recorder-web-buildx-${IMAGE_TAG}.log \
sudo docker buildx build \
--builder ${BUILDER_NAME} \
--platform ${TARGET_PLATFORMS} \
--network host \
--progress=plain \
--provenance=false \
--build-arg NODE_IMAGE=${WEB_NODE_IMAGE} \
--build-arg NGINX_IMAGE=${WEB_NGINX_IMAGE} \
--build-arg HTTP_PROXY=http://192.168.5.200:7890 \
--build-arg HTTPS_PROXY=http://192.168.5.200:7890 \
--build-arg NO_PROXY=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \
--build-arg http_proxy=http://192.168.5.200:7890 \
--build-arg https_proxy=http://192.168.5.200:7890 \
--build-arg no_proxy=127.0.0.1,localhost,reg.nxsir.cn,gitea.nxsir.cn \
-f frontend/Dockerfile \
--build-arg VITE_API_BASE_URL=/api \
-t ${WEB_IMAGE_TAGGED} \
-t ${WEB_IMAGE_LATEST} \
--push \
frontend
"""
}
}
}
post {
success {
echo "Pipeline completed successfully."
}
failure {
echo "Pipeline failed. Please check the build log."
}
always {
sh """
set +e
sudo docker logout ${REGISTRY_URL} >/dev/null 2>&1 || true
true
"""
deleteDir()
}
}
}