如何在gitlab CI管道中推送到仓库?

jam*_*iet 11 gitlab gitlab-ci

在我的CI管道中,我正在生成一个public/graph.png可视化我的代码某些方面的工件。在以后的步骤中,我想将其从CI管道中提交给仓库。这是相关的部分.gitlab-ci.yml

commit-graph:
  stage: pages
  script:
    - git config user.email "cipipeline@example.com"
    - git config user.name "CI Pipeline"
    - cd /group/project
    - mv public/graph.png .
    - git add graph.png
    - git commit -m "committing graph.png [ci skip]"
    - echo $CI_COMMIT_REF_NAME
    - git push origin HEAD:$CI_COMMIT_REF_NAME
Run Code Online (Sandbox Code Playgroud)

当管道在gitlab中运行时,它失败并显示:

$ git config user.email“ cipipeline@dhgitlab.dunnhumby.co.uk”
$ git config user.name“ CI管道”
$ cd / group / project
$ mv public / graph.png。
$ git add graph.png
$ git commit -m“ committing graph.png [ci skip]”
[分离头22a50d1] commiting graph.png [ci skip]
1个文件已更改,0个插入(+),0个删除(-)
创建模式100644 graph.png
$ echo $ CI_COMMIT_REF_NAME
jamiet / my-branch
$ git push origin HEAD:$ CI_COMMIT_REF_NAME
致命:无法访问' https:// gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx@example.com/group/project/project。 git / ':服务器证书验证失败。CAfile:/ etc / ssl / certs / ca-certificates。

不知道我在做什么错,对SSL的了解还不足以理解该错误。有人可以建议吗?

顺便说一下,我们自己托管了gitlab。

Rob*_*per 88

如今,有一种更简洁的方法可以解决此问题,无需使用 SSH,而是使用项目范围的访问令牌,另请参阅此答案

在 GitLab 项目中创建一个项目范围的访问令牌,以便它链接到项目,而不是个人。接下来将此令牌存储为 GitLab CI/CD 变量。您现在可以使用以下命令进行连接:

push-back-to-remote:
  script:
    - git config user.email "my-email@email.com"
    - git config user.name "ci-bot"
    - git remote add gitlab_origin https://oauth2:$ACCESS_TOKEN@gitlab.com/path-to-project.git
    - git add .
    - git commit -m "push back from pipeline"
    - git push gitlab_origin HEAD:main -o ci.skip # prevent triggering pipeline again
Run Code Online (Sandbox Code Playgroud)

  • 听起来是最好的选择,尽管项目访问令牌仅适用于高级或更高级别。 (13认同)
  • 最好的解决方案!项目访问令牌可在自托管实例上使用。但请注意:从 GitLab 16 开始,他们将需要一个到期日期! (9认同)
  • 注意:项目访问令牌可用于自我管理实例上的所有层。 (5认同)
  • 如果您的 git 推送由于启用的设置“存储库设置 > 推送规则 > 拒绝未经验证的用户”而被拒绝,请注意,每个项目访问令牌都会隐式创建一个“机器人用户”,该用户还附带代表已验证用户的电子邮件地址。因此,您可以通过将 git 的“user.email”配置设置为机器人的电子邮件地址来解决问题 - 按照 [GitLab 文档中的模式描述](https://docs.gitlab.com/ee/user/project/设置/project_access_tokens.html#bot-users-for-projects)。 (5认同)

kid*_*oca 28

TL;博士;

\n

如果您只想release在将内容合并到 时进行版本升级提交main,那么可能存在现有的 CLI 工具,您可以以更简单且有据可查的方式使用它们。
\n (请参阅使用 gitlabapi作为示例)

\n

怎么做

\n
必要的步骤:
\n
commitingJob:\n  stage: some_stage\n  script:\n    # in order to commit we have to have a user set\n    # this would also make it easy to distinct the CI-made commits\n    - git config user.name "CI Pipeline"\n    - git config user.email "cipipeline@example.com"\n    # stage some changes\n    - git add src/*\n    # We can use `-o ci.skip`, but AFAIK it doesn\'t work for Merge Request pipelines, while having it inside the commit message works there as well\n    - git commit -m "A commit message [skip ci]"\n    # we\'re on a detached head but we can push the commits we made to the remote branch like so:\n    - git push HEAD:$CI_COMMIT_REF_NAME\n
Run Code Online (Sandbox Code Playgroud)\n

这里缺少的一件事是使用遥控器进行身份验证。它可以通过多种方式进行设置(ssh、令牌、api)。其他答案讨论了一些不同的选项。我的偏好是使用 ACCESS_TOKEN,请参阅下面的方式和原因

\n

对可用身份验证选项的总结和批评

\n

添加或复制ssh在 CI 步骤中

\n

与仅使用访问令牌相比,ssh为了获得相同的结果,这种方式似乎需要做太多工作

\n
    \n
  • 生成 ssh 密钥
  • \n
  • 将公钥保存为项目部署令牌
  • \n
  • 将私钥保存为项目 CI 变量
  • \n
  • 致力于一些 CI 步骤\n
      \n
    • 添加私钥
    • \n
    • 添加已知主机
    • \n
    • 添加/更新ssh遥控器
    • \n
    \n
  • \n
\n

总的来说,这似乎是你会做的事情user而不是管道所做的事情

\n

您必须将私钥添加为项目级 CI 变量 - 由于模式限制,该变量无法被屏蔽。它可以作为文件添加,但随后您必须chmod获得适当的权限...

\n

我在这里看到的积极的事情是ssh密钥仅限于您将其添加到部署令牌的项目

\n
\n

最简单的选择似乎是使用 ACCESS_TOKEN

\n

使用令牌来推送提交就像更新push远程一样简单,如下所示:

\n
git remote set-url --push origin "https://$TOKEN_NAME:$ACCESS_TOKEN@gitlab.com/<project>.git"\n
Run Code Online (Sandbox Code Playgroud)\n

TOKEN_NAME - 您在 gitlab 中为令牌设置的名称(最好选择一个不带空格字符的名称)\nACCESS_TOKEN - 这可以是个人访问令牌(免费层)项目访问令牌(高级层)

\n

它必须存储为项目级 CI 变量,并且可以被屏蔽。\n我只需保存一个变量,例如CI_COMMITTER_USER_AND_TOKEN包含这两个<token_name>:<access_token>内容

\n
\xe2\x9a\xa0 关于个人访问令牌的警告
\n

即使运行者应该提交到多个存储库,授予 CI 运行者的权限也太宽泛,我更喜欢每个项目单独的访问令牌,只需要所需的最低权限

\n

请记住,如果有人掌握了您的个人访问令牌,他们可以代表您执行某些操作(例如在本例中进行提交)。授予write_repository权限意味着您可以使用令牌写入您帐户有权访问的任何存储库。

\n
CI_JOB_TOKEN
\n

如果您想知道是否可以使用 来CI_JOB_TOKEN推送提交 - 您不能。你只能pull使用那个东西
\n (你也可以用它来发布包和图像,但不能推送提交)

\n
为什么git remote set-url --push origin
\n

我们可以为 CI 提交添加一个单独的远程,但请记住它可能会被缓存,所以如果我们这样做

\n
script: \n  - git remote add ci "https://$TOKEN_NAME:$ACCESS_TOKEN@gitlab.com/<project>.git"\n
Run Code Online (Sandbox Code Playgroud)\n

下次管道运行时,我们会收到错误git remote add,因为我们尝试添加的远程已经添加

\n

set-url在现有的基础上origin确保使用最新的网址

\n

为了达到同样的目的,git remote add我们必须首先尝试删除ci遥控器,然后将其添加回来

\n
script: \n  - git remote remove ci || true\n  - git remote add ci "https://$TOKEN_NAME:$ACCESS_TOKEN@gitlab.com/<project>.git"\n
Run Code Online (Sandbox Code Playgroud)\n
\n

使用gitlabapi推送更改

\n

这与方法几乎相同,但令牌具有权限ACCESS_TOKEN而不是write_repositoryapi

\n

如果作为 CI 的一部分提交和推送的原因是在合并时发布新版本,那么main使用 CLI 工具和这样的指南可能比自己设置提交和推送更好:https://docs.gitlab。 com/ee/ci/examples/semantic-release.html

\n

上述指南设置了版本提升、包更新和发行说明。\n请注意此步骤如何指示我们创建具有api权限的访问令牌,以便底层 CLI 提交更改:https://docs.gitlab.com/ ee/ci/examples/semantic-release.html#set-up-cicd-variables

\n


Bła*_*lik 22

仍然需要一些手指俯卧撑,但这里有一种不太脆弱的方法,可以从自己的 CI 推送到存储库,我在日常工作中使用它。它直接从独立的头推送到 master:

\n

在此输入图像描述

\n
    \n
  1. 生成 RSA 密钥并将其添加为具有写入权限的项目部署密钥(公共部分)。
  2. \n
  3. 将私有部分从项目设置内部放入 CI/CD 变量中,如下所示SSH_PUSH_KEY. 确保将其设置为受保护。
  4. \n
  5. 添加一个CI_KNOWN_HOSTS变量,其中包含您的 GitLab 实例的 SSH 指纹(还记得它ssh会询问您第一次尝试连接到主机的情况吗?就是这样。)。
  6. \n
\n

使用ssh-keyscan <gitlab-host>即可获得。它看起来类似于:

\n
my.gitlab.instance.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArlUMUmNj59PpoLyy4EsKbwhPUfXxuAzFN7dMKDXVvKMmN8344HqQV1tRx6fcmH+0BXK1JAP4f10V0VnYti3e1c5f9dhpl8pIqKLMJgdGDq3MLqjihL3bp5xm8nDsPTm5FoEPPYK1I3M2wr18pBB19evz64NHrK5R/HO5LyTrybVasFumt8cZoH6crnCFgfQWV1mHAG3j41Q0z4yxu6g8zBWESZcVVn90HxQH7+LDHx11122233344491MQGl5fZcKqVWsWQVEssaK87iBsWUxvsuoeVUrj4YRcmbi6F4+ZZZZZZZwwww3ZboWsSWxTk5ESR6WWHccBm8GQflXyY3ZQ==\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 按如下方式在里面设置您的工作.gitlab-ci.yml。适当地设置stageresource_group选项 - 如果没有后者,您可能会遇到竞争条件。另外,请确保设置only正确,否则您的 CI 可能会自行触发:
  2. \n
\n
"This CI job pushes to its own repo":\n    stage: my_push_stage\n    resource_group: this_option_comes_handy_when_pushing\n    only:\n        - triggers\n    before_script:\n        - mkdir ~/.ssh/\n        - echo "${CI_KNOWN_HOSTS}" > ~/.ssh/known_hosts\n        - echo "${SSH_PUSH_KEY}" > ~/.ssh/id_rsa\n        - chmod 600 ~/.ssh/id_rsa\n        - git config user.email "ci@example.com"\n        - git config user.name "CI"\n        - git remote remove ssh_origin || true  # Local repo state may be cached\n        - git remote add ssh_origin "git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git"\n    script:\n        - touch "xyz"  # Make an edit\n        - git add "xyz"\n        - git commit -m "My CI commit"\n        - git push ssh_origin HEAD:master  # \xe2\x9d\x97 this pushes to master, \n                                           # use $CI_COMMIT_REF_NAME if you want to push to current branch\n        - git tag MyCiTag  # If you need to add a tag you can do that too\n        - git push --tags ssh_origin\n
Run Code Online (Sandbox Code Playgroud)\n

  • @TomChiverton虽然这有效,但它基本上与设置`GIT_SSH_COMMAND =“ssh -o StrictHostKeyChecking = no”`相同。 (2认同)
  • @MKakaGrisu 您将部署 _keys_ 与部署 _tokens_ 混淆了。请参阅 https://docs.gitlab.com/ee/user/project/deploy_keys/ _“读写部署密钥可以从存储库中读取和写入。”_ (2认同)

tsr*_*tsr 7

我发现这个GitLab 论坛链接很有帮助 根据用户的建议,您需要生成 SSH 密钥,将其与专用于此工作的新 GitLab 用户相关联,并将密钥添加到运行程序。一个小缺点是您需要在 gitlab 中使用交换源作为原始 ssh 源(而不是在作业中使用的沙盒源),这导致提交者被更改为提到的新帐户而不是触发管道的人。来自链接的来源:

# for your information
whoami
printenv

# we need to extract the ssh/git URL as the runner uses a tokenized URL
export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | perl -pe 's#.*@(.+?(\:\d+)?)/#git@\1:#'`

# runner runs on a detached HEAD, create a temporary local branch for editing
git checkout -b ci_processing
git config --global user.name "My Runner"
git config --global user.email "runner@gitlab.example.org"
git remote set-url --push origin "${CI_PUSH_REPO}"

# make your changes
touch test.txt

# push changes
# always return true so that the build does not fail if there are no changes
git push origin ci_processing:${CI_COMMIT_REF_NAME} || true
Run Code Online (Sandbox Code Playgroud)

仅使用当前版本的 GitLab,您需要按如下方式更改源变量名称:

export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | perl -pe 's#.*@(.+?(\:\d+)?)/#git@\1:#'`
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以添加CI_SERVER_CLS_CA_FILEsslCAInfogit 配置。

checkout alchemy:
    stage: prepare
    script:
        - git config --global "http.${CI_SERVER_URL}.sslCAInfo" "$CI_SERVER_TLS_CA_FILE"
        - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/sparklemuffin/alchemy.git
Run Code Online (Sandbox Code Playgroud)

从管道克隆不同的存储库时,我遇到了同样的问题。它因服务器证书验证失败而失败。我不明白为什么会发生这种情况,Gitlab 本身克隆存储库没有任何问题。所以我设置CI_DEBUG_TRACE: "true"并发现,Gitlab 创建这个文件配置 git 使用它来最初克隆存储库。由于某种原因,此配置以后不再可用。CI_SERVER_TLS_CA_FILE坚持,虽然。

  • 我使用了类似的解决方案:我将 `export GIT_SSL_CAINFO="$CI_SERVER_TLS_CA_FILE"` 放在脚本的顶部。[如果你把它放在`variables`下,它就不起作用](https://gitlab.com/gitlab-org/gitlab/-/issues/292220)。 (2认同)

jam*_*iet 1

解决了。在推送git config --global http.sslverify "false"之前发出解决了该特定问题(它暴露了另一个问题,但那是另一个线程:))

  • 好问题,但这个答案为-1,因为它鼓励避免问题而不是解决问题。现在有很多获得免费 SSL 证书的好方法,没有理由不解决 SSL 问题而不是完全禁用它。 (35认同)