import groovy.json.JsonSlurper def resultHtml = '' // 初始化一个变量来存储最终的 HTML try { // --- 1. 参数处理 --- def rawInput = IMAGE_NAME ?: '' def pureTag = rawInput.split(/\s*\|\s*/)[0].trim() if (!pureTag) { resultHtml = '
(请选择镜像 tag)
' return resultHtml // 立即返回 } // --- 2. 硬编码凭据 --- def user = '100038894437' // 你的 TCR 用户名 (UIN) def pass = 'h8H1o6Fd!HLXn' // 你的 TCR 登录密码 if (!user || !pass) { resultHtml = '
❌ 凭据为空
' return resultHtml // 立即返回 } // --- 3. API 查询 --- final String REG = "https://uswccr.ccs.tencentyun.com" final String REPO = "lessiesit/flymoon-email" // 3.1. Token def auth = "Basic " + "${user}:${pass}".bytes.encodeBase64().toString() def tokenUrl = new URL("${REG}/service/token?service=uswccr&scope=repository:${REPO}:pull") def tokenConn = tokenUrl.openConnection() tokenConn.setRequestProperty("Authorization", auth) tokenConn.connect() if (tokenConn.responseCode != 200) { def errorBody = tokenConn.errorStream?.text ?: "No error body" resultHtml = "
❌ Token 请求失败 (${tokenConn.responseCode}): ${errorBody.take(200)}
" return resultHtml // 立即返回 } def tokenJson = new JsonSlurper().parse(tokenConn.inputStream) def token = tokenJson?.token if (!token) { resultHtml = '
❌ 无法从响应中获取 Token
' return resultHtml // 立即返回 } // 3.2. Manifest def manifestUrl = new URL("${REG}/v2/${REPO}/manifests/${pureTag}") def manifestConn = manifestUrl.openConnection() manifestConn.setRequestProperty("Authorization", "Bearer ${token}") manifestConn.setRequestProperty("Accept", "application/vnd.docker.distribution.manifest.v2+json") manifestConn.connect() if (manifestConn.responseCode != 200) { if (manifestConn.responseCode == 404) { resultHtml = "
⚠️ Tag '${pureTag}' 不存在
" return resultHtml // 立即返回 } def errorBody = manifestConn.errorStream?.text ?: "No error body" resultHtml = "
❌ Manifest 请求失败 (${manifestConn.responseCode}): ${errorBody.take(200)}
" return resultHtml // 立即返回 } def manifestJson = new JsonSlurper().parse(manifestConn.inputStream) def configDigest = manifestJson?.config?.digest if (!configDigest) { resultHtml = '
❌ Manifest 中无 config.digest
' return resultHtml // 立即返回 } // 3.3. Config Blob (Labels) def blobUrl = new URL("${REG}/v2/${REPO}/blobs/${configDigest}") def blobConn = blobUrl.openConnection() blobConn.setRequestProperty("Authorization", "Bearer ${token}") blobConn.connect() if (blobConn.responseCode != 200) { def errorBody = blobConn.errorStream?.text ?: "No error body" resultHtml = "
❌ Config Blob 请求失败 (${blobConn.responseCode}): ${errorBody.take(200)}
" return resultHtml // 立即返回 } def configJson = new JsonSlurper().parse(blobConn.inputStream) def labels = configJson?.config?.Labels ?: [:] // --- 4. 格式化输出 --- // 再次确保 labels 是 Map if (!(labels instanceof Map)) { labels = [:] } resultHtml = "
🏷️ Labels for ${pureTag}:
" if (labels.isEmpty()) { resultHtml += "(无 Labels)
" } else { labels.each { k, v -> def key = (k != null) ? k.toString() : 'null_key' def value = (v != null) ? v.toString().replaceAll(/^'|'$/, '') : 'null_value' resultHtml += "${key}: ${value}
" } } resultHtml += "
" // ✅ 修复:在 try 块结束前,确保 resultHtml 是字符串 resultHtml = resultHtml.toString() } catch (Exception e) { def errorMsg = e.message?.toString() ?: '未知错误' def errorClass = e.class.simpleName resultHtml = "
🚨 脚本异常: ${errorClass} - ${errorMsg}
" } // ✅ 修复:确保在所有路径下,最终返回的都是字符串 return resultHtml.toString()