You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins Pipeline推送Git仓库时URL端口错误排查求助

Jenkins Kubernetes Agent推送Git仓库时出现URL端口错误问题

报错信息

fatal: unable to access 'https://example.org/git/usernamerepo/devops-gitops-apps.git/': URL rejected: Port number was not a decimal number between 0 and 65535

Jenkinsfile相关代码片段

pipeline {
    agent {
        kubernetes {
            yaml '''
apiVersion: v1
kind: Pod
metadata:
  labels:
    pod-name: jenkins-agent
spec:
  containers:
  - name: git
    image: alpine/git
    command:
    - cat
    tty: true
    env:
    - name: http_proxy
      value: proxyvalue
    - name: https_proxy
      value: proxyvalue
    - name: no_proxy
      value: somevalues,othersvalue
    volumeMounts:
    - name: yq-bin
      mountPath: /yq-bin
    resources:
      requests:
        memory: "256Mi"
        cpu: "0.25"
  - name: jnlp
    image: jenkins/inbound-agent:latest
    args: ['$(JENKINS_SECRET)', '$(JENKINS_NAME)']
  initContainers:
  - name: yq
    image: mikefarah/yq:4.43.1
    command: ["sh", "-c", "cp /usr/bin/yq /yq-bin/yq"]
    volumeMounts:
    - name: yq-bin
      mountPath: /yq-bin
  volumes:
  - name: yq-bin
    emptyDir: {}
            '''
        }
    }

    environment {
        HELM_HOME = "/usr/local/bin/helm"
        VALUES_FILE = "jenkins/values.yaml"
        GIT_REPO = "https://example.org/git/usernamerepo/devops-gitops-apps.git"
        GIT_BRANCH = "master"
        NEW_BRANCH = "jenkins-update"
        GIT_CREDENTIALS_ID = "giteaAccess" 
    }

    stages {
        stage('Checkout') {
            steps {
                container('git') {
                    git branch: "${env.GIT_BRANCH}", url: "${env.GIT_REPO}", credentialsId: "${env.GIT_CREDENTIALS_ID}"
                }
            }
        }

        stage('Debug YQ Path') {
            steps {
                container('git') {
                    script {
                        sh 'ls -l /yq-bin'
                        sh '/yq-bin/yq --version'
                    }
                }
            }
        }

        stage('Read Plugins') {
            steps {
                container('git') {
                    script {
                        def plugins = sh(script: "/yq-bin/yq e '.controller.installPlugins[]' ${env.VALUES_FILE}", returnStdout: true).trim().split("\n")
                        env.PLUGINS = plugins.join(" ")
                    }
                }
            }
        }

        stage('Update Plugins') {
            steps {
                container('git') {
                    script {
                        def pluginsList = env.PLUGINS.tokenize()
                        sh "sed -i '/installPlugins:/,\$d' ${env.VALUES_FILE}"
                        sh "echo 'controller:' >> ${env.VALUES_FILE}"
                        sh "echo '  installPlugins:' >> ${env.VALUES_FILE}"
                        pluginsList.each { plugin ->
                            sh "echo '    - ${plugin}' >> ${env.VALUES_FILE}"
                        }
                    }
                }
            }
        }

        stage('Configure Git Safe Directory') {
            steps {
                container('git') {
                    script {
                        sh "git config --global --add safe.directory /home/jenkins/agent/workspace/jenkinsupdater"
                    }
                }
            }
        }

        stage('Commit Changes') {
            steps {
                container('git') {
                    script {
                        withCredentials([usernamePassword(credentialsId: "${env.GIT_CREDENTIALS_ID}", usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                            sh "git checkout -b ${env.NEW_BRANCH}"
                            sh 'git config user.email "username@example.org"'
                            sh 'git config user.name "${USERNAME}"'
                            sh 'git add ${VALUES_FILE}'
                            sh 'git commit -m "Automated update of Jenkins plugins"'
                            sh '''
                            git remote set-url origin https://${USERNAME}:${PASSWORD}@example.org/git/usernamerepo/devops-gitops-apps.git
                            git push -u origin ${NEW_BRANCH}
                            '''
                        }
                    }
                }
            }
        }

        stage('Create Pull Request') {
            steps {
                container('git') {
                    script {
                        withCredentials([usernamePassword(credentialsId: "${env.GIT_CREDENTIALS_ID}", usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                            sh """
                            curl -X POST -H "Content-Type: application/json" -u ${USERNAME}:${PASSWORD} \
                            -d '{
                                  "title": "Automated update of Jenkins plugins",
                                  "body": "This PR includes automated updates of Jenkins plugins",
                                  "head": "${NEW_BRANCH}",
                                  "base": "master"
                                }' \
                            https://example.org/git/usernamerepo/devops-gitops-apps/pulls
                            """
                        }
                    }
                }
            }
        }
    }

    post {
        always {
            echo "Cleaning up and finalizing pipeline."
            cleanWs()
        }
    }
}

问题背景

该流水线负责拉取仓库代码、更新values.yaml中的Jenkins插件列表、提交变更、推送新分支到远程仓库并创建PR。使用Jenkins withCredentials块管理凭证,但仍触发上述URL端口相关错误。

已排查操作:

  • 确认withCredentials对凭证的处理逻辑正确
  • 尝试多种设置远程URL及推送变更的方式
  • 检查代理配置无异常

原因分析

  1. 凭证特殊字符破坏URL结构:如果Git凭证(密码/用户名)包含@、:等URL特殊字符,直接拼接进远程URL时会打乱URL格式,导致Git误将特殊字符后的内容解析为端口号,引发端口格式错误。
  2. Shell变量解析失败:多行sh脚本使用单引号包裹时,Jenkins环境变量(如${USERNAME})无法被正确替换,可能生成无效URL。
  3. 代理配置间接干扰:http_proxy/https_proxy环境变量若格式异常,或no_proxy未包含Git仓库域名,可能干扰Git对目标URL的解析逻辑。

解决建议

方案1:使用Git凭证助手替代URL拼接

避免手动拼接带凭证的URL,用Git凭证助手自动处理认证:

stage('Commit Changes') {
    steps {
        container('git') {
            script {
                withCredentials([usernamePassword(credentialsId: "${env.GIT_CREDENTIALS_ID}", usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                    sh "git checkout -b ${env.NEW_BRANCH}"
                    sh 'git config user.email "username@example.org"'
                    sh "git config user.name '${USERNAME}'"
                    sh "git add ${VALUES_FILE}"
                    sh 'git commit -m "Automated update of Jenkins plugins"'
                    // 配置临时凭证助手
                    sh "git config credential.helper '!f() { echo username=\$USERNAME; echo password=\$PASSWORD; }; f'"
                    sh "git push -u origin ${NEW_BRANCH}"
                    // 清理凭证配置
                    sh "git config --unset credential.helper"
                }
            }
        }
    }
}

方案2:对凭证特殊字符进行URL编码

若必须拼接URL,需对用户名和密码中的特殊字符编码:

stage('Commit Changes') {
    steps {
        container('git') {
            script {
                withCredentials([usernamePassword(credentialsId: "${env.GIT_CREDENTIALS_ID}", usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) {
                    // URL编码特殊字符
                    def encodedUser = java.net.URLEncoder.encode(USERNAME, "UTF-8")
                    def encodedPass = java.net.URLEncoder.encode(PASSWORD, "UTF-8")
                    def gitUrl = "https://${encodedUser}:${encodedPass}@example.org/git/usernamerepo/devops-gitops-apps.git"
                    
                    sh "git checkout -b ${env.NEW_BRANCH}"
                    sh 'git config user.email "username@example.org"'
                    sh "git config user.name '${USERNAME}'"
                    sh "git add ${VALUES_FILE}"
                    sh 'git commit -m "Automated update of Jenkins plugins"'
                    sh "git remote set-url origin ${gitUrl}"
                    sh "git push -u origin ${NEW_BRANCH}"
                }
            }
        }
    }
}

方案3:修正Shell变量解析问题

将多行sh脚本拆分为单行,或使用双引号保证变量替换:

// 替换原多行sh脚本为以下单行命令
sh "git remote set-url origin https://${USERNAME}:${PASSWORD}@example.org/git/usernamerepo/devops-gitops-apps.git"
sh "git push -u origin ${NEW_BRANCH}"

方案4:优化代理配置

  • 确认no_proxy环境变量包含Git仓库域名example.org,避免代理解析内部域名
  • 检查代理地址格式(如http://proxy-host:port),确保无多余特殊字符

内容的提问来源于stack exchange,提问作者Andres Cabrera

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 07:44:57