如何从 gitlab CI 管道中推送到仓库?
Posted
技术标签:
【中文标题】如何从 gitlab CI 管道中推送到仓库?【英文标题】:How do I push to a repo from within a gitlab CI pipeline? 【发布时间】:2019-01-13 21:50:32 【问题描述】:在我的 CI 管道中,我正在生成一个工件 public/graph.png
,它可以可视化我的代码的某些方面。在后面的步骤中,我想从 CI 管道中将其提交给 repo。这是.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
当管道在 gitlab 中运行时失败:
$ git config user.email "cipipeline@dhgitlab.dunnhumby.co.uk" $ git config user.name "CI 管道" $ cd /组/项目 $ mv public/graph.png . $ git add graph.png $ git commit -m "提交 graph.png [ci 跳过]" [分离 HEAD 22a50d1] 提交 graph.png [ci 跳过] 1 个文件已更改,0 个插入 (+),0 个删除 (-) 创建模式 100644 graph.png $ 回声 $CI_COMMIT_REF_NAME jamiet/我的分公司 $ 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.crt CRLfile:无
不确定我做错了什么,并且对 SSL 了解不足,无法理解该错误。谁能给点建议?
顺便说一句,我们自己托管 gitlab。
【问题讨论】:
【参考方案1】:我发现这个GitLab forum 链接很有帮助 根据用户的建议,您需要生成 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
仅使用当前版本的 GitLab,您需要更改源变量名称,如下所示:
export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | perl -pe 's#.*@(.+?(\:\d+)?)/#git@\1:#'`
【讨论】:
【参考方案2】:您可以将CI_SERVER_CLS_CA_FILE
添加到sslCAInfo
git config。
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
从管道克隆不同的存储库时,我遇到了同样的问题。它因服务器证书验证失败而失败。我不明白为什么会发生这种情况,Gitlab 本身克隆了存储库而没有任何问题。所以我设置CI_DEBUG_TRACE: "true"
并发现,Gitlab 创建这个文件配置 git 使用它来初始克隆存储库。由于某种原因,此配置稍后不再可用。 CI_SERVER_TLS_CA_FILE
仍然存在。
【讨论】:
我使用了类似的解决方案:我将export GIT_SSL_CAINFO="$CI_SERVER_TLS_CA_FILE"
放在脚本的顶部。它doesn't work if you put it under variables
.【参考方案3】:
解决了。在推送之前发出git config --global http.sslverify "false"
解决了该特定问题(它暴露了另一个问题,但这是另一个线程:))
【讨论】:
好问题,但这个答案是-1,因为它鼓励避免问题而不是解决问题。现在有很多获得免费 SSL 证书的好方法,没有理由不解决 SSL 问题而不是完全禁用它。【参考方案4】:我可以根据 tsr 的回答 https://***.com/a/57800614/5269825 与选定用户一起从 Gitlab-CI 提交,只需稍作更改:
# set remote URL to https://oauth2:<AccessToken>@server.com/project.git
CI_PUSH_REPO=`echo "$CI_REPOSITORY_URL $ACCESS_TOKEN_PARAM" | sed 's/^.*\(@.*\)\s\(.*\)/https:\/\/oauth2:\2\1/g'`
git config http.sslverify false
git remote set-url --push origin "$CI_PUSH_REPO"
git config user.name "Token Owner"
git config user.email "tokenowner@email.com"
# runner runs on a detached HEAD, create a temporary local branch for editing
git checkout -b ci_processing
# make your changes
# push changes
# always return true so that the build does not fail if there are no changes
git push origin ci_processing:$CI_BUILD_REF_NAME || true
ACCESS_TOKEN_PARAM
必须在项目的 CI/CD 变量配置中进行配置。
使用 Oauth2 和 Access Token 的想法来自 https://***.com/a/52074198/5269825 和 https://***.com/a/52154378/5269825。
此外,推送更改可能会触发新管道!
【讨论】:
【参考方案5】:仍然需要一些手指俯卧撑,但我在日常工作中使用了一种从其自己的 CI 推送到存储库的不那么脆弱的方法。它直接从一个分离的头部推送到 master:
-
生成 RSA 密钥并将其添加为具有写入权限的 Project Deploy Key(公共部分)。
将私有部分作为
SSH_PUSH_KEY
从您的项目设置内部放入您的 CI/CD 变量中。确保将其设置为受保护。
添加一个 CI_KNOWN_HOSTS
变量,其中包含您的 GitLab 实例的 SSH 指纹(还记得 ssh
在您第一次尝试连接到主机时询问您吗?那个。)。
使用ssh-keyscan <gitlab-host>
获取它。它看起来类似于:
my.gitlab.instance.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArlUMUmNj59PpoLyy4EsKbwhPUfXxuAzFN7dMKDXVvKMmN8344HqQV1tRx6fcmH+0BXK1JAP4f10V0VnYti3e1c5f9dhpl8pIqKLMJgdGDq3MLqjihL3bp5xm8nDsPTm5FoEPPYK1I3M2wr18pBB19evz64NHrK5R/HO5LyTrybVasFumt8cZoH6crnCFgfQWV1mHAG3j41Q0z4yxu6g8zBWESZcVVn90HxQH7+LDHx11122233344491MQGl5fZcKqVWsWQVEssaK87iBsWUxvsuoeVUrj4YRcmbi6F4+ZZZZZZZwwww3ZboWsSWxTk5ESR6WWHccBm8GQflXyY3ZQ==
-
在
.gitlab-ci.yml
中设置您的工作,如下所示。适当地设置 stage
和 resource_group
选项 - 如果没有后者,您可能会遇到竞争条件。另外,请确保正确设置only
,否则您的 CI 可能会自行触发:
"This CI job pushes to its own repo":
stage: my_push_stage
resource_group: this_option_comes_handy_when_pushing
only:
- triggers
before_script:
- mkdir ~/.ssh/
- echo "$CI_KNOWN_HOSTS" > ~/.ssh/known_hosts
- echo "$SSH_PUSH_KEY" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- git config user.email "ci@example.com"
- git config user.name "CI"
- git remote remove ssh_origin || true # Local repo state may be cached
- git remote add ssh_origin "git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git"
script:
- touch "xyz" # Make an edit
- git add "xyz"
- git commit -m "My CI commit"
- git push ssh_origin HEAD:master # ❗ this pushes to master,
# use $CI_BUILD_REF_NAME if you want to push to current branch
- git tag MyCiTag # If you need to add a tag you can do that too
- git push --tags ssh_origin
【讨论】:
【参考方案6】:您可以尝试实时获取,而不是声明 CI_KNOWN_HOST:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- ssh-keyscan -t rsa $CI_SERVER_HOST >> ~/.ssh/known_hosts
【讨论】:
【参考方案7】:在我的情况下,deploy keys 选项是 Gitlab Shell Runner 的最佳选择(与个人令牌或 CI 令牌相比 - 仅支持基本身份验证)。如果有人正在努力从 Gitlab CI 推送,这可以通过与 Gitlab 服务器共享运行器的公钥来完成
【讨论】:
【参考方案8】:这是一个截至今天的工作示例 环境:k8s gitlab:13.x gitlab 运行器:13.x 这个名为 convert 的工作的目标:- 将 excel 文件转换为 json 文件并提交和更新 repo 的分支。
convert:
variables:
REPO: "gitlab.com/group/myproject.git" # example
BRANCH: "BRANCHNAME" # example
# recommended to store the following as project variables to hide secrets away from the gitlab ci file.
GITLAB_USER_ID: "gitlab_user" # example
CI_USERNAME: "gitlab_user" # example
CI_PUSH_TOKEN: "<api token from gitlab" # example
GITLAB_USER_EMAIL: "gitlab_user@company.com" # example
stage: convert
image:
name: python:3.7-buster
entrypoint: ["/bin/ash"]
before_script:
- pip3 install openpyxl
- ls -altr
script:
- echo 'converting excel to json'
- python excel2json.py
- git remote set-url origin https://$CI_USERNAME:$CI_PUSH_TOKEN@$REPO
- git config --global user.email '$GITLAB_USER_EMAIL'
- git config --global user.name '$GITLAB_USER_ID'
- git add -A && git commit -m 'added/updated json files'
- git push origin HEAD:$BRANCH
注意:CI_USERNAME == GITLAB_USER_ID。就我而言,两者都是一样的。
【讨论】:
【参考方案9】:另一种方式:
-
创建专用 Gitlab 帐户
将包含密码的 CI/CD 变量 GIT_CICDUSER_PASSWORD 添加到运行管道的主帐户内的项目中
然后一个工作可能看起来像:
task_requiring_a_push:
stage: some-stage
variables:
GIT_STRATEGY: none
script:
- git config --global user.email "user@mail.com"
- git config --global user.name "CI/CD User"
- git clone https://<dedicated_gitlab_user_username>:$GIT_CICDUSER_PASSWORD@gitlab.com/$CI_PROJECT_PATH .
- git checkout $CI_COMMIT_REF_NAME
- # do something
- git add *
- git commit -m "message"
- git push --push-option=ci.skip origin $CI_COMMIT_REF_NAME
only:
- release-*
【讨论】:
以上是关于如何从 gitlab CI 管道中推送到仓库?的主要内容,如果未能解决你的问题,请参考以下文章