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

从Jenkins流水线触发GitLab CI Runner任务失败,寻求替代方案

问题

我有一个多阶段Jenkins流水线,其中一个阶段需要连接远程GitLab,触发其他业务单元(BU)所属Runner上的GitLab CI任务。尝试用curl调用GitLab API实现时,始终返回权限拒绝错误,且curl无法正确获取任务执行结果,求其他可行的实现方法。

原实现相关代码

测试用GitLab CI任务脚本

my-test-job:
  script:
    - echo "This is a test"

原Jenkins流水线代码

pipeline {
    agent any

    stages {
        stage('Trigger GitLab Runner Job') {
            steps {
                script {
                    // Trigger the GitLab job using the GitLab Runner API
                    def triggerResponse = sh(
                        script: "curl --insecure --request POST --header 'PRIVATE-TOKEN: oauySh5_YRAuWDaPD_Le' 'https://my-gitlab.fr/myjob/test-ci/-/jobs/play'",
                        returnStatus: true
                    )
                    
                    if (triggerResponse == 0) {
                        echo 'GitLab job triggered successfully.'
                    } else {
                        error 'Failed to trigger GitLab job.'
                    }
                                                                                   
                }
            }
        }
    }
}

返回的错误信息

</h1>
10:01:53    <div class="container">
10:01:53      <h3>The change you requested was rejected.</h3>
10:01:53      <hr />
10:01:53      <p>Make sure you have access to the thing you tried to change.</p>
10:01:53      <p>Please contact your GitLab administrator if you think this is a mistake.</p>
10:01:53      <a href="javascript:history.back()" class="js-go-back go-back">Go back</a>
10:01:53    </div>
10:01:53    <script>
10:01:53      (function () {
10:01:53        var goBack = document.querySelector('.js-go-back');
10:01:53  
10:01:53        if (history.length > 1) {
10:01:53          goBack.style.display = 'inline';
10:01:53        }
10:01:53      })();
10:01:53  
10:01:53    </script>
10:01:53  </body>
10:01:53  </html>
10:01:53  [Pipeline] echo
10:01:53  GitLab job triggered successfully.
可行实现方法

原curl实现存在三个核心问题:API路径错误(/-/jobs/play是针对单个已存在job的重跑,而非触发新流水线)、仅依赖curl状态码判断成功(即使返回权限拒绝页面,curl状态码仍为0)、个人访问令牌权限不足。以下是三种可行解决方式:

方法1:修正GitLab API调用(触发完整流水线+轮询结果)

使用GitLab官方的流水线触发API,同时加入结果轮询逻辑:

  1. 确保个人访问令牌拥有api和write_repository权限
  2. 使用项目路径编码(如myjob%2Ftest-ci)或项目ID替换API中的:id参数
  3. 解析API响应内容判断触发结果,而非仅依赖curl状态码
  4. 可选:轮询流水线状态直到完成,确保获取最终执行结果

示例Jenkins流水线代码:

pipeline {
    agent any

    stages {
        stage('Trigger GitLab Pipeline') {
            steps {
                script {
                    // 建议将令牌存储在Jenkins凭据中,避免硬编码
                    def gitlabToken = credentials('gitlab-personal-token') 
                    def projectPath = "myjob%2Ftest-ci"
                    def apiBase = "https://my-gitlab.fr/api/v4/projects/${projectPath}"

                    // 触发指定分支的流水线,可传入变量指定要运行的job
                    def triggerOutput = sh(
                        script: "curl --insecure --request POST --header 'PRIVATE-TOKEN: ${gitlabToken}' '${apiBase}/pipeline' -F 'ref=main' -F 'variables[0][key]=TARGET_JOB' -F 'variables[0][value]=my-test-job'",
                        returnStdout: true
                    ).trim()

                    // 解析响应判断触发是否成功
                    def triggerJson = readJSON text: triggerOutput
                    if (!triggerJson.id) {
                        error "触发GitLab流水线失败:${triggerOutput}"
                    }
                    echo "GitLab流水线触发成功,ID:${triggerJson.id}"

                    // 轮询等待流水线完成
                    def pipelineStatus = ""
                    while (!["success", "failed", "canceled"].contains(pipelineStatus)) {
                        sleep 30 // 每30秒轮询一次
                        def statusOutput = sh(
                            script: "curl --insecure --header 'PRIVATE-TOKEN: ${gitlabToken}' '${apiBase}/pipelines/${triggerJson.id}'",
                            returnStdout: true
                        ).trim()
                        def statusJson = readJSON text: statusOutput
                        pipelineStatus = statusJson.status
                        echo "当前流水线状态:${pipelineStatus}"
                    }

                    // 根据最终状态判断是否失败
                    if (pipelineStatus != "success") {
                        error "GitLab流水线执行失败,最终状态:${pipelineStatus}"
                    }
                }
            }
        }
    }
}

方法2:使用Jenkins GitLab插件(无代码集成)

通过Jenkins官方GitLab插件实现更简洁的集成,无需手动编写curl逻辑:

  1. 先在Jenkins插件市场安装GitLab Plugin
  2. 在Jenkins系统设置中配置GitLab服务器连接:填入GitLab地址,添加个人访问令牌作为凭据
  3. 在流水线中使用gitlabBuild步骤触发流水线并自动等待结果

示例Jenkins流水线代码:

pipeline {
    agent any

    stages {
        stage('Trigger GitLab via Plugin') {
            steps {
                gitlabBuild(
                    gitlabConnection: 'MyGitLabServer', // Jenkins中配置的GitLab连接名称
                    projectId: 'myjob/test-ci', // GitLab项目路径
                    branchName: 'main',
                    waitForCompletion: true, // 等待流水线完成
                    variables: [
                        [key: 'TARGET_JOB', value: 'my-test-job'] // 传递变量指定要运行的job
                    ]
                )
            }
        }
    }
}

方法3:使用GitLab触发令牌(无API权限需求)

如果无法获取高权限的个人访问令牌,可使用GitLab项目的流水线触发令牌:

  1. 在GitLab项目的「设置」→「CI/CD」→「流水线触发令牌」中生成专属令牌
  2. 使用触发令牌API触发流水线,该令牌仅拥有触发流水线的权限,安全性更高

示例curl命令(可直接替换到Jenkins的sh步骤中):

curl --insecure --request POST 'https://my-gitlab.fr/api/v4/projects/myjob%2Ftest-ci/trigger/pipeline' \
  --form 'token=你的触发令牌' \
  --form 'ref=main' \
  --form 'variables[TARGET_JOB]=my-test-job'

内容的提问来源于stack exchange,提问作者Rayan Denver

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:25:55