无法从 gitlab-ci.yml 推送

Posted

技术标签:

【中文标题】无法从 gitlab-ci.yml 推送【英文标题】:Cannot push from gitlab-ci.yml 【发布时间】:2018-03-10 09:08:03 【问题描述】:

与我的同事一起,我们致力于开发一个日益重要的 C++ 库。我们已经通过gitlab-ci.yml 文件构建了持续集成实用程序,它让我们:

在调试模式下构建和测试 在发布模式下构建和测试 使用 Valgrind 执行内存泄漏等安全检查,并检查我们的库中是否有任何我们不想要的明确符号 生成文档

所有让我们选择 GitLab 的东西!

我们想对整个库进行概要分析,并将基准测试推送到一个单独的项目中。我们已经使用 SSH 密钥 方法为输出文档做了类似的事情,但这次我们想避免这种情况。

我们尝试了这样的脚本:

test_ci_push:
  tags:
    - linux
    - shell
    - light
  stage: profiling
  allow_failure: false
  only:
    - new-benchmark-stage
  script:
    - git clone http://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.mycompany.home/developers/benchmarks.git &> /dev/null
    - cd benchmarks
    - touch test.dat
    - echo "This is a test" > test.dat
    - git config --global user.name "$GITLAB_USER_NAME"
    - git config --global user.email "$GITLAB_USER_EMAIL"
    - git add --all
    - git commit -m "GitLab Runner Push"
    - git push http://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.mycompany.home/developers/benchmarks.git HEAD:master
    - cd ..

我们还尝试了基本的git push origin master 来推送我们更新的文件,但每次我们得到相同的答案:

remote: You are not allowed to upload code for this project.
fatal: unable to access 'http://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@gitlab.mycompany.home/developers/benchmarks.git/': The requested URL returned error: 403

这两个项目都在同一个site 下,我有权推动这两个项目。我在哪里做错了什么?

【问题讨论】:

【参考方案1】:

我正在使用以下 GitLab 作业:

repo_pull_sync:
  image: danger89/repo_mirror_pull:latest
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
    - if: $REMOTE_URL
    - if: $REMOTE_BRANCH
    - if: $ACCESS_TOKEN
  before_script:
    - git config --global user.name "$GITLAB_USER_NAME"
    - git config --global user.email "$GITLAB_USER_EMAIL"
  script:
    - git checkout $CI_DEFAULT_BRANCH
    - git pull
    - git remote remove upstream || true
    - git remote add upstream $REMOTE_URL
    - git fetch upstream
    - git merge upstream/$REMOTE_BRANCH
    - git push "https://$GITLAB_USER_LOGIN:$ACCESS_TOKEN@$CI_REPOSITORY_URL#*@" "HEAD:$CI_DEFAULT_BRANCH"

我正在使用我自己的基于 alpine 的 danger89/repo_mirror_pull docker 映像,check this GitHub repository for more info。

此 GitLab 作业从预定义的远程存储库 + 分支中提取上游更改(请参阅下面的变量),并将它们本地合并到 CI/CD 中,然后再次将它们推送到 GitLab 中。

基本上我创建了一个存储库pull mirror(在GitLab CE 上官方不提供免费的,GitLab 仅支持push mirror)。

首先在 GitLab 中创建项目访问令牌。通过:设置->访问令牌。检查 'api' 作为范围。 通过以下方式创建新计划:CI/CD->计划->新计划。使用以下 3 个变量: REMOTE_URL(例如:https://github.com/project/repo.git) REMOTE_BRANCH(例如:master) ACCESS_TOKEN:(参见第一步中的访问令牌!示例:gplat-234hcand9q289rba89dghqa892agbd89arg2854,) 保存管道计划

再次,另请参阅:https://github.com/danger89/repo_pull_sync_docker_image

关于这个问题,请参阅上面的 git push 命令,它允许您使用 GitLab(项目)访问令牌将更改推送回 GitLab。

【讨论】:

【参考方案2】:

您还可以提供用户和密码(具有写入权限的用户)作为秘密变量并使用它们。

例子:

before_script:
 - git remote set-url origin https://$GIT_CI_USER:$GIT_CI_PASS@$CI_SERVER_HOST/$CI_PROJECT_PATH.git
 - git config --global user.email 'myuser@mydomain.com'
 - git config --global user.name 'MyUser'

您必须将GIT_CI_USERGIT_CI_PASS 定义为秘密变量(您始终可以为此创建专用用户)。

通过此配置,您通常可以使用 git。我正在使用这种方法在发布后推送标签(使用 Axion Release Gradle Pluing - http://axion-release-plugin.readthedocs.io/en/latest/index.html

发布工作示例:

release:
  stage: release
  script:
    - git branch
    - gradle release -Prelease.disableChecks -Prelease.pushTagsOnly
    - git push --tags
  only:
   - master

【讨论】:

我用$CI_SERVER_HOST而不是gitlab.com更新了这个答案。【参考方案3】:

虽然前面的答案或多或少都不错,但还是有一些重要的问题。

  before_script:
    - git config --global user.name "$GITLAB_USER_NAME"
    - git config --global user.email "$GITLAB_USER_EMAIL"
  script:
    - <do things>
    - git push "https://$GITLAB_USER_LOGIN:$CI_GIT_TOKEN@$CI_REPOSITORY_URL#*@" "HEAD:$CI_COMMIT_TAG"

一,我们只需要设置用户名/邮箱来请git。

其次,将它放在之前的脚本中,不是很重要,但在进行“扩展”时可以更轻松地重用。

最后,推送 https 是“好的”,但由于我们没有使用存储的 ssh 密钥,所以我们应该避免任何可能泄露令牌的事情。一方面,虽然 gitlab 不会在此命令中打印令牌,但 git 会很高兴地通知我们新的上游设置为 https://username:thetokeninplaintexthere@url 所以你的令牌是纯文本的,所以不要使用 -u 来设置上游。

另外,也不需要,我们只做一次推送。

此外,在确定 URL 时,我发现使用现有 CI_REPOSITORY_URL 是最可靠的解决方案(例如,在移动 repo 时)。所以我们只需替换 URL 字符串中的用户名/令牌。

【讨论】:

你能告诉我们@$CI_REPOSITORY_URL#*@到底是什么吗?替换是如何工作的,我在哪里可以找到对这个语法的引用? @ 实际上是 HTTP 协议的一部分,表示您想使用 username:password@hostname 登录。变量:$CI_REPOSITORY_URL 是变量。 “#*@”是正则表达式(regex),但我也不知道它是做什么的。或者,您也可以在@-symbol 之后使用:$CI_SERVER_HOST/$CI_PROJECT_PATH.git 而不是使用提交标签。我实际上在使用"HEAD:$CI_DEFAULT_BRANCH"【参考方案4】:

gitlab ci 令牌更像是 github.com 中的部署密钥,因此它只有对存储库的读取权限。要真正推送,您需要生成个人访问令牌并使用它。

首先您需要生成令牌,如here in the gitlab documentation 所示。确保同时检查读取用户和 api 范围。此外,这只适用于 GitLab 8.15 及更高版本。如果您使用的是旧版本并且不想升级,我可以向您展示另一种方法,但它更复杂且安全性较低。

最后你的 gitlab-ci.yml 应该是这样的:

test_ci_push:
  tags:
    - linux
    - shell
    - light
  stage: profiling
  allow_failure: false
  only:
    - new-benchmark-stage
  script:
    - git clone http://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.mycompany.home/developers/benchmarks.git &> /dev/null
    - cd benchmarks
    - echo "This is a test" > test.dat
    - git config --global user.name "$GITLAB_USER_NAME"
    - git config --global user.email "$GITLAB_USER_EMAIL"
    - git add --all
    - git commit -m "GitLab Runner Push"
    - git push http://$YOUR_USERNAME:$PERSONAL_ACCESS_TOKEN@gitlab.mycompany.home/developers/benchmarks.git HEAD:master
    - cd ..

【讨论】:

好的!我现在必须弄清楚如何在 .yml > 中通用这个令牌 我已经更新了我的答案,以便更轻松地获得您需要的东西;) 我想使用我的用户令牌在 CI 中执行 git push。我生成了一个API access token,除了我的 git https url 之外,我还使用它。这不起作用,它说我是所有者时没有推送权限。我能怎么做 ? (没有 SSH) 每个访问令牌都附加了作用域,访问令牌需要 api 作用域,否则你不能用它做任何事情 我已经检查了所有范围,包括 api 范围,但我仍然无法推送到我的存储库。您确定可以使用令牌吗?我之前使用的是手动配置的 ssh,因为我认为这是一种解决方案

以上是关于无法从 gitlab-ci.yml 推送的主要内容,如果未能解决你的问题,请参考以下文章

在项目上运行Gitlab-CI以获取两个不同的Docker镜像

从 Jenkins Ci 服务迁移到 gitlab-ci.yml

如何让 gitlab-runner 从指定文件中读取而不是 .gitlab-ci.yml?

Gitlab-ci.yml 创建合并请求

如何排除 gitlab-ci.yml 更改触发作业

如何从 .net 项目文件中获取 gitlab-ci.yml 文件中的项目版本?