// Jenkinsfile —— jp-rakuten（乐天 / ラクマ 抓取服务）
//
// 默认 registry: git.jerryyan.net/jp/rakuten-api
// 构建参数说明见各 stage 顶部；首次使用前请在 Jenkins 里配置凭据：
//   - git-credentials : 拉代码的 SSH / HTTPS 凭据
//   - gitea-registry  : docker login git.jerryyan.net 的凭据（username/password）

pipeline {
    agent any

    options {
        timestamps()
        timeout(time: 30, unit: 'MINUTES')
        disableConcurrentBuilds()
        buildDiscarder(logRotator(numToKeepStr: '20', daysToKeepStr: '14'))
    }

    parameters {
        string(name: 'IMAGE_NAME',
               defaultValue: 'git.jerryyan.net/jp/rakuten-api',
               description: '镜像完整名（含 registry host）')
        string(name: 'IMAGE_TAG',
               defaultValue: '',
               description: '自定义 tag；留空则用 <BUILD_NUMBER>-<git short sha>')
        booleanParam(name: 'SKIP_TEST',
                     defaultValue: false,
                     description: '跳过单测（紧急发版用，正常构建不要勾）')
    }

    environment {
        // 让 docker build 看到 BuildKit 缓存挂载等特性
        DOCKER_BUILDKIT = '1'
        // 禁掉 pip 警告、Jenkins 写 .pyc
        PYTHONUNBUFFERED = '1'
        PYTHONDONTWRITEBYTECODE = '1'
        // 国内镜像：uv / pip 拉包走阿里云 PyPI 镜像，避免拉取缓慢
        UV_INDEX_URL = 'https://mirrors.aliyun.com/pypi/simple/'
    }

    stages {

        stage('Checkout') {
            steps {
                checkout scm
                script {
                    env.GIT_SHA = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
                    env.GIT_TAG = sh(script: 'git describe --tags --always --dirty 2>/dev/null || echo ""', returnStdout: true).trim()
                    if (!params.IMAGE_TAG?.trim()) {
                        env.IMAGE_TAG = "${env.BUILD_NUMBER}-${env.GIT_SHA}"
                    }
                    echo "镜像目标: ${env.IMAGE_NAME}:${env.IMAGE_TAG}（git=${env.GIT_SHA}）"
                }
            }
        }

        stage('Test') {
            // 跳过逻辑：SKIP_TEST=true 时整个 stage 不跑
            when {
                expression { return !params.SKIP_TEST }
            }
            // 在官方 Python 镜像里跑测试，避免污染宿主机；只装 dev extra，不装 browser
            // 用 -u root 是因为 Jenkins 默认把容器用户映射到 jenkins uid，HOME=/，
            // pip user-site 会解析到 /.local 直接报错；测试容器跑完即销毁，跑 root 无副作用
            agent {
                docker {
                    image 'registry.jerryyan.top/library/python:3.13-slim'
                    reuseNode true
                    args '-u root:root'
                }
            }
            steps {
                sh '''
                    set -e
                    export HOME=/root
                    export PIP_CACHE_DIR=/root/.cache/pip
                    # 阿里云 PyPI 镜像，UV_INDEX_URL 由 pipeline environment 注入
                    python -m pip install --quiet --upgrade pip -i "$UV_INDEX_URL"
                    pip install --quiet uv -i "$UV_INDEX_URL"
                    uv sync --frozen --extra dev
                    .venv/bin/python -m pytest -q
                '''
            }
        }

        stage('Build image') {
            steps {
                sh """
                    docker build \
                        -t ${env.IMAGE_NAME}:${env.IMAGE_TAG} \
                        -t ${env.IMAGE_NAME}:latest \
                        --label org.opencontainers.image.revision=${env.GIT_SHA} \
                        --label org.opencontainers.image.version=${env.IMAGE_TAG} \
                        -f Dockerfile .
                """
            }
        }

        stage('Push image') {
            steps {
                withCredentials([usernamePassword(
                    credentialsId: 'gitea-registry',
                    usernameVariable: 'REGISTRY_USER',
                    passwordVariable: 'REGISTRY_PASS',
                )]) {
                    sh """
                        echo "\$REGISTRY_PASS" | docker login git.jerryyan.net -u "\$REGISTRY_USER" --password-stdin
                        docker push ${env.IMAGE_NAME}:${env.IMAGE_TAG}
                        docker push ${env.IMAGE_NAME}:latest
                    """
                }
            }
        }
    }

    post {
        always {
            // 清理本次构建产生的镜像，避免 Jenkins agent 磁盘膨胀
            sh """
                docker rmi -f ${env.IMAGE_NAME}:${env.IMAGE_TAG} 2>/dev/null || true
                docker rmi -f ${env.IMAGE_NAME}:latest 2>/dev/null || true
            """
        }
        success {
            echo "构建成功：${env.IMAGE_NAME}:${env.IMAGE_TAG}"
        }
        failure {
            echo "构建失败，请查看上方日志"
        }
    }
}