pipeline {
    agent { label '构建机1' }

    options {
        timestamps()
        disableConcurrentBuilds()
        skipDefaultCheckout(true)
    }

    environment {
        REGISTRY_URL      = 'reg.nxsir.cn'
        APP_IMAGE_NAME    = 'duplicati_preview/app'
        IMAGE_TAG         = "${env.BUILD_ID}"
        DOCKER_CREDS      = 'previewrobot_key'
        TARGET_PLATFORMS  = 'linux/amd64,linux/arm64'
        BUILDER_NAME      = 'duplicati-preview-buildx'
        NODE_IMAGE        = 'docker.m.daocloud.io/library/node:24-alpine'

        GIT_REPO_URL      = 'https://gitea.nxsir.cn/nanxun/duplicati_preview.git'
        GIT_BRANCH        = 'main'
        GIT_CREDS         = ''

        APP_IMAGE_TAGGED  = "${REGISTRY_URL}/${APP_IMAGE_NAME}:${IMAGE_TAG}"
        APP_IMAGE_LATEST  = "${REGISTRY_URL}/${APP_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
                '''
            }
        }

        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 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
                      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] Duplicati Preview multi-arch build still running at $(date -u +%Y-%m-%dT%H:%M:%SZ)"
                        fi
                        sleep 20
                      done
                      set +e
                      wait "$cmd_pid"
                      cmd_status=$?
                      set -e
                      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
                        if [ "$cmd_status" -ne 0 ] && [ -s "$log_file" ]; then
                          echo "[captured-log] Full buildx log follows because the command failed:"
                          cat "$log_file"
                        fi
                      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 image: ${APP_IMAGE_TAGGED}"

                    run_with_heartbeat /tmp/duplicati-preview-buildx-${IMAGE_TAG}.log \
                      sudo docker buildx build \
                        --builder ${BUILDER_NAME} \
                        --platform ${TARGET_PLATFORMS} \
                        --network host \
                        --progress=plain \
                        --provenance=false \
                        --build-arg NODE_IMAGE=${NODE_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,reg.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,reg.nxsir.cn \
                        -f Dockerfile \
                        -t ${APP_IMAGE_TAGGED} \
                        -t ${APP_IMAGE_LATEST} \
                        --push \
                        .
                '''
            }
        }
    }

    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()
        }
    }
}
