ci: scope Docker privilege to Jenkins credential
This commit is contained in:
Vendored
+66
-30
@@ -16,6 +16,7 @@ pipeline {
|
|||||||
WEB_IMAGE_REPO = 'reg.nxsir.cn/live_recorder/app-web'
|
WEB_IMAGE_REPO = 'reg.nxsir.cn/live_recorder/app-web'
|
||||||
HARBOR_CREDENTIALS = 'harbor_key'
|
HARBOR_CREDENTIALS = 'harbor_key'
|
||||||
OPENLIST_CREDENTIALS = 'openlist_key'
|
OPENLIST_CREDENTIALS = 'openlist_key'
|
||||||
|
NODE_CREDENTIALS = 'bbb939ea-4f01-4b47-aecb-c5ee2a551ef4'
|
||||||
OPENLIST_BASE_URL = 'https://openlist.nxsir.cn'
|
OPENLIST_BASE_URL = 'https://openlist.nxsir.cn'
|
||||||
OPENLIST_REMOTE_DIR = '/yidongpan/构建产物/liverecorder'
|
OPENLIST_REMOTE_DIR = '/yidongpan/构建产物/liverecorder'
|
||||||
|
|
||||||
@@ -72,6 +73,11 @@ pipeline {
|
|||||||
currentBuild.description = "${env.IMMUTABLE_TAG}"
|
currentBuild.description = "${env.IMMUTABLE_TAG}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withCredentials([usernamePassword(
|
||||||
|
credentialsId: "${NODE_CREDENTIALS}",
|
||||||
|
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||||
|
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||||
|
)]) {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
test "$(uname -m)" = x86_64
|
test "$(uname -m)" = x86_64
|
||||||
@@ -81,9 +87,8 @@ pipeline {
|
|||||||
test -x "$DOTNET"
|
test -x "$DOTNET"
|
||||||
test -x "$FNPACK_BIN"
|
test -x "$FNPACK_BIN"
|
||||||
printf '%s %s\n' "$FNPACK_SHA256" "$FNPACK_BIN" | sha256sum --check --status
|
printf '%s %s\n' "$FNPACK_SHA256" "$FNPACK_BIN" | sha256sum --check --status
|
||||||
sudo -n true
|
./scripts/ci-docker.sh version >/dev/null
|
||||||
sudo docker version >/dev/null
|
./scripts/ci-docker.sh buildx version
|
||||||
sudo docker buildx version
|
|
||||||
|
|
||||||
available_kb=$(df -Pk "$WORKSPACE" | awk 'NR == 2 { print $4 }')
|
available_kb=$(df -Pk "$WORKSPACE" | awk 'NR == 2 { print $4 }')
|
||||||
if [ "$available_kb" -lt 2097152 ]; then
|
if [ "$available_kb" -lt 2097152 ]; then
|
||||||
@@ -106,6 +111,7 @@ pipeline {
|
|||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stage('Restore And Test') {
|
stage('Restore And Test') {
|
||||||
steps {
|
steps {
|
||||||
@@ -132,24 +138,30 @@ pipeline {
|
|||||||
|
|
||||||
stage('Prepare Docker Builder') {
|
stage('Prepare Docker Builder') {
|
||||||
steps {
|
steps {
|
||||||
|
withCredentials([usernamePassword(
|
||||||
|
credentialsId: "${NODE_CREDENTIALS}",
|
||||||
|
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||||
|
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||||
|
)]) {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
if ! sudo docker run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m 2>/dev/null | grep -q aarch64; then
|
if ! ./scripts/ci-docker.sh run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m 2>/dev/null | grep -q aarch64; then
|
||||||
sudo docker run --privileged --rm "$BINFMT_IMAGE" --install arm64
|
./scripts/ci-docker.sh run --privileged --rm "$BINFMT_IMAGE" --install arm64
|
||||||
fi
|
fi
|
||||||
sudo docker run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m | grep -q aarch64
|
./scripts/ci-docker.sh run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m | grep -q aarch64
|
||||||
|
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
./scripts/ci-docker.sh buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx create \
|
./scripts/ci-docker.sh buildx create \
|
||||||
--name "$BUILDER_NAME" \
|
--name "$BUILDER_NAME" \
|
||||||
--driver docker-container \
|
--driver docker-container \
|
||||||
--driver-opt "image=$BUILDKIT_IMAGE" \
|
--driver-opt "image=$BUILDKIT_IMAGE" \
|
||||||
--driver-opt network=host \
|
--driver-opt network=host \
|
||||||
--use
|
--use
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx inspect "$BUILDER_NAME" --bootstrap
|
./scripts/ci-docker.sh buildx inspect "$BUILDER_NAME" --bootstrap
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stage('Prepare Harbor Authentication') {
|
stage('Prepare Harbor Authentication') {
|
||||||
steps {
|
steps {
|
||||||
@@ -170,6 +182,11 @@ pipeline {
|
|||||||
|
|
||||||
stage('Build And Push amd64') {
|
stage('Build And Push amd64') {
|
||||||
steps {
|
steps {
|
||||||
|
withCredentials([usernamePassword(
|
||||||
|
credentialsId: "${NODE_CREDENTIALS}",
|
||||||
|
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||||
|
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||||
|
)]) {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
arch=amd64
|
arch=amd64
|
||||||
@@ -177,7 +194,7 @@ pipeline {
|
|||||||
api_ref="$API_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
api_ref="$API_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||||
web_ref="$WEB_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
web_ref="$WEB_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||||
|
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
./scripts/ci-docker.sh buildx build \
|
||||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||||
--progress=plain --provenance=false --no-cache \
|
--progress=plain --provenance=false --no-cache \
|
||||||
--build-arg HTTP_PROXY="$HTTP_PROXY_URL" \
|
--build-arg HTTP_PROXY="$HTTP_PROXY_URL" \
|
||||||
@@ -187,10 +204,10 @@ pipeline {
|
|||||||
--build-arg https_proxy="$HTTP_PROXY_URL" \
|
--build-arg https_proxy="$HTTP_PROXY_URL" \
|
||||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||||
-f src/LiveRecorder.WebApi/Dockerfile -t "$api_ref" --load .
|
-f src/LiveRecorder.WebApi/Dockerfile -t "$api_ref" --load .
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$api_ref"
|
./scripts/ci-docker.sh push "$api_ref"
|
||||||
sudo docker rmi "$api_ref" >/dev/null
|
./scripts/ci-docker.sh rmi "$api_ref" >/dev/null
|
||||||
|
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
./scripts/ci-docker.sh buildx build \
|
||||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||||
--progress=plain --provenance=false --no-cache \
|
--progress=plain --provenance=false --no-cache \
|
||||||
--build-arg NODE_IMAGE="$NODE_BUILD_IMAGE" \
|
--build-arg NODE_IMAGE="$NODE_BUILD_IMAGE" \
|
||||||
@@ -203,14 +220,20 @@ pipeline {
|
|||||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||||
--build-arg VITE_API_BASE_URL=/api \
|
--build-arg VITE_API_BASE_URL=/api \
|
||||||
-f frontend/Dockerfile -t "$web_ref" --load frontend
|
-f frontend/Dockerfile -t "$web_ref" --load frontend
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$web_ref"
|
./scripts/ci-docker.sh push "$web_ref"
|
||||||
sudo docker rmi "$web_ref" >/dev/null
|
./scripts/ci-docker.sh rmi "$web_ref" >/dev/null
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stage('Build And Push arm64') {
|
stage('Build And Push arm64') {
|
||||||
steps {
|
steps {
|
||||||
|
withCredentials([usernamePassword(
|
||||||
|
credentialsId: "${NODE_CREDENTIALS}",
|
||||||
|
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||||
|
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||||
|
)]) {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
arch=arm64
|
arch=arm64
|
||||||
@@ -218,7 +241,7 @@ pipeline {
|
|||||||
api_ref="$API_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
api_ref="$API_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||||
web_ref="$WEB_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
web_ref="$WEB_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||||
|
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
./scripts/ci-docker.sh buildx build \
|
||||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||||
--progress=plain --provenance=false --no-cache \
|
--progress=plain --provenance=false --no-cache \
|
||||||
--build-arg HTTP_PROXY="$HTTP_PROXY_URL" \
|
--build-arg HTTP_PROXY="$HTTP_PROXY_URL" \
|
||||||
@@ -228,10 +251,10 @@ pipeline {
|
|||||||
--build-arg https_proxy="$HTTP_PROXY_URL" \
|
--build-arg https_proxy="$HTTP_PROXY_URL" \
|
||||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||||
-f src/LiveRecorder.WebApi/Dockerfile -t "$api_ref" --load .
|
-f src/LiveRecorder.WebApi/Dockerfile -t "$api_ref" --load .
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$api_ref"
|
./scripts/ci-docker.sh push "$api_ref"
|
||||||
sudo docker rmi "$api_ref" >/dev/null
|
./scripts/ci-docker.sh rmi "$api_ref" >/dev/null
|
||||||
|
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
./scripts/ci-docker.sh buildx build \
|
||||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||||
--progress=plain --provenance=false --no-cache \
|
--progress=plain --provenance=false --no-cache \
|
||||||
--build-arg NODE_IMAGE="$NODE_BUILD_IMAGE" \
|
--build-arg NODE_IMAGE="$NODE_BUILD_IMAGE" \
|
||||||
@@ -244,36 +267,43 @@ pipeline {
|
|||||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||||
--build-arg VITE_API_BASE_URL=/api \
|
--build-arg VITE_API_BASE_URL=/api \
|
||||||
-f frontend/Dockerfile -t "$web_ref" --load frontend
|
-f frontend/Dockerfile -t "$web_ref" --load frontend
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$web_ref"
|
./scripts/ci-docker.sh push "$web_ref"
|
||||||
sudo docker rmi "$web_ref" >/dev/null
|
./scripts/ci-docker.sh rmi "$web_ref" >/dev/null
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stage('Publish Multi-arch Manifests') {
|
stage('Publish Multi-arch Manifests') {
|
||||||
steps {
|
steps {
|
||||||
|
withCredentials([usernamePassword(
|
||||||
|
credentialsId: "${NODE_CREDENTIALS}",
|
||||||
|
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||||
|
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||||
|
)]) {
|
||||||
sh '''
|
sh '''
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
||||||
immutable_ref="$repository:$IMMUTABLE_TAG"
|
immutable_ref="$repository:$IMMUTABLE_TAG"
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools create \
|
./scripts/ci-docker.sh buildx imagetools create \
|
||||||
--tag "$immutable_ref" \
|
--tag "$immutable_ref" \
|
||||||
"$immutable_ref-amd64" "$immutable_ref-arm64"
|
"$immutable_ref-amd64" "$immutable_ref-arm64"
|
||||||
|
|
||||||
manifest=$(sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools inspect --raw "$immutable_ref")
|
manifest=$(./scripts/ci-docker.sh buildx imagetools inspect --raw "$immutable_ref")
|
||||||
printf '%s' "$manifest" | grep -q '"architecture"[[:space:]]*:[[:space:]]*"amd64"'
|
printf '%s' "$manifest" | grep -q '"architecture"[[:space:]]*:[[:space:]]*"amd64"'
|
||||||
printf '%s' "$manifest" | grep -q '"architecture"[[:space:]]*:[[:space:]]*"arm64"'
|
printf '%s' "$manifest" | grep -q '"architecture"[[:space:]]*:[[:space:]]*"arm64"'
|
||||||
done
|
done
|
||||||
|
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools create \
|
./scripts/ci-docker.sh buildx imagetools create \
|
||||||
--tag "$API_IMAGE_REPO:$APP_VERSION" --tag "$API_IMAGE_REPO:latest" \
|
--tag "$API_IMAGE_REPO:$APP_VERSION" --tag "$API_IMAGE_REPO:latest" \
|
||||||
"$API_IMAGE_REPO:$IMMUTABLE_TAG"
|
"$API_IMAGE_REPO:$IMMUTABLE_TAG"
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools create \
|
./scripts/ci-docker.sh buildx imagetools create \
|
||||||
--tag "$WEB_IMAGE_REPO:$APP_VERSION" --tag "$WEB_IMAGE_REPO:latest" \
|
--tag "$WEB_IMAGE_REPO:$APP_VERSION" --tag "$WEB_IMAGE_REPO:latest" \
|
||||||
"$WEB_IMAGE_REPO:$IMMUTABLE_TAG"
|
"$WEB_IMAGE_REPO:$IMMUTABLE_TAG"
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stage('Upload fnOS Artifact') {
|
stage('Upload fnOS Artifact') {
|
||||||
steps {
|
steps {
|
||||||
@@ -319,23 +349,29 @@ pipeline {
|
|||||||
echo 'LiveRecorder pipeline failed; stable Docker tags were only updated if all architecture builds succeeded.'
|
echo 'LiveRecorder pipeline failed; stable Docker tags were only updated if all architecture builds succeeded.'
|
||||||
}
|
}
|
||||||
always {
|
always {
|
||||||
|
withCredentials([usernamePassword(
|
||||||
|
credentialsId: "${NODE_CREDENTIALS}",
|
||||||
|
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||||
|
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||||
|
)]) {
|
||||||
sh '''
|
sh '''
|
||||||
set +e
|
set +e
|
||||||
if [ -n "${BUILDER_NAME:-}" ]; then
|
if [ -x ./scripts/ci-docker.sh ] && [ -n "${BUILDER_NAME:-}" ]; then
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
./scripts/ci-docker.sh buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
if [ -n "${IMMUTABLE_TAG:-}" ]; then
|
if [ -x ./scripts/ci-docker.sh ] && [ -n "${IMMUTABLE_TAG:-}" ]; then
|
||||||
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
||||||
for suffix in amd64 arm64; do
|
for suffix in amd64 arm64; do
|
||||||
sudo docker rmi "$repository:$IMMUTABLE_TAG-$suffix" >/dev/null 2>&1 || true
|
./scripts/ci-docker.sh rmi "$repository:$IMMUTABLE_TAG-$suffix" >/dev/null 2>&1 || true
|
||||||
done
|
done
|
||||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker manifest rm "$repository:$IMMUTABLE_TAG" >/dev/null 2>&1 || true
|
./scripts/ci-docker.sh manifest rm "$repository:$IMMUTABLE_TAG" >/dev/null 2>&1 || true
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
if [ -f "$DOCKER_CONFIG/config.json" ]; then
|
if [ -f "$DOCKER_CONFIG/config.json" ]; then
|
||||||
: >"$DOCKER_CONFIG/config.json"
|
: >"$DOCKER_CONFIG/config.json"
|
||||||
fi
|
fi
|
||||||
'''
|
'''
|
||||||
|
}
|
||||||
cleanWs(deleteDirs: true, notFailBuild: true)
|
cleanWs(deleteDirs: true, notFailBuild: true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Executable
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
: "${JENKINS_NODE_PASSWORD:?JENKINS_NODE_PASSWORD is required}"
|
||||||
|
|
||||||
|
printf '%s\n' "$JENKINS_NODE_PASSWORD" | \
|
||||||
|
sudo -S -p '' -- \
|
||||||
|
/usr/bin/env "DOCKER_CONFIG=${DOCKER_CONFIG:-}" \
|
||||||
|
/usr/bin/docker "$@"
|
||||||
Reference in New Issue
Block a user