通过 CI runner 将文件推送到 gitlab-ci

Posted

技术标签:

【中文标题】通过 CI runner 将文件推送到 gitlab-ci【英文标题】:Push files to gitlab-ci via CI runner 【发布时间】:2017-02-28 14:03:06 【问题描述】:

我正在使用 gitlab CI runner 来测试我的代码并生成一些文件。我只想通过 CI runner 将生成的文件推送到 gitlab 存储库。有什么办法吗?

【问题讨论】:

thread 中涵盖了类似的问题 【参考方案1】:

您正在寻找的功能称为工件。工件是在构建成功时附加到构建的文件。

要启用 Artifact,请将其放入您的 .gitlab-ci.yml:

artifacts:
  paths:
    - dir/
    - singlefile

这会将dir 目录和文件singlefile 上传回GitLab。

【讨论】:

但我真的很想将文件作为源文件推送到存储库。 @VenkatGan 但是为什么呢?如果您使用 Runner 将任何内容推送到存储库,您将再次启动 runner。这将导致无限循环。 是的,它将开始一个无限循环。但是当我通过 runner 提交时,我使用 [skip ci] 关键字。通过这种方式,我可以消除无限循环。 @Fairy 基于docs.gitlab.com/ee/user/project/… 除了[skip ci],推送时可以使用git选项跳过ci:git push -o ci.skip 遗憾的是,这个答案根本没有帮助:(。需要注意的一点:如果您需要安装 git 并且您正在使用 docker,您可能必须实际安装和配置它。我可能会进入这个,因为我想在构建时增加构建版本并将其提交/推送回原始存储库。【参考方案2】:

在 gitlab 中生成 SSH 密钥

--> 配置文件设置--> SSH 密钥--> 生成它

在 gitlab variables 中生成名为 SSH

的 SSH 密钥库后

--> 项目设置--> 变量--> 添加变量

在 .gitlab-ci.yml 中添加以下行。

before_script:
   - mkdir -p ~/.ssh
   - echo "$SSH" | tr -d '\r' > ~/.ssh/id_rsa
   - chmod 600 ~/.ssh/id_rsa
   - ssh-keyscan -H 'Git_Domain' >> ~/.ssh/known_hosts 

然后使用下面的 js 代码将文件推送到存储库。

var child_process = require("child_process");
child_process.execSync("git checkout -B 'Your_Branch'");
child_process.execSync("git remote set-url origin Your_Repository_Git_Url");
child_process.execSync("git config --global user.email 'Your_Email_ID'");
child_process.execSync("git config --global user.name 'Your_User_Name'");
for (var i=0;i<filesToBeAdded.length;i++) 
          child_process.execSync("git add "+filesToBeAdded[i]);
   
var ciLog = child_process.execSync("git commit -m '[skip ci]Automated commit for CI'");
var pushLog = child_process.execSync("git push origin Your_Branch");

[skip ci] 在提交信息中是最重要的。否则会开始无限循环的CI流程。

【讨论】:

【参考方案3】:

我已经通过这样做解决了这个问题:

注意:如果你想 git push 到一个非受保护的分支,不要将 runner 变量设置为受保护

    使用 api 范围生成新的 gitlab 访问令牌:User Settings &gt; Access Tokens 使用新令牌将受保护的 CI 变量添加到您的项目设置中:Your project &gt; Settings &gt; Secret variable 使用变量名称 CI_PUSH_TOKEN 使用变量名CI_USERNAME 使用您的用户名添加另一个受保护的 CI 变量

然后您可以在 gitlab-ci 脚本中使用此令牌而不是默认令牌。例如:

before_script:
  - git remote set-url origin https://$CI_USERNAME:$CI_PUSH_TOKEN@gitlab.com/$CI_PROJECT_NAME.git
  - git config --global user.email '$GITLAB_USER_EMAIL'
  - git config --global user.name '$GITLAB_USER_ID'

...

- git checkout -B branch
- # do the file changes here
- git commit -m '[skip ci] commit from CI runner'
- git push --follow-tags origin branch

【讨论】:

我已经尝试过了,它抛出:fatal: Authentication failed for 'https://[secure]@example.com/dka/duma.git/',我是回购的所有者,令牌是我的。 我拒绝了你的答案,因为它似乎是错误的,我已经测试过了,我们一直在努力寻找证据 我们在许多项目中使用此设置而没有身份验证问题。您的设置中缺少某些内容,您可以为跑步者生成一个新令牌并尝试使用它吗? * 我忘了说,如果你想为非受保护的分支运行 git push,你必须禁用 ci runner 令牌变量上的受保护标签 1.请使用$CI_PROJECT_NAME 代替your-project$GITLAB_USER_EMAIL 代替your@email.com$GITLAB_USER_ID 代替yourname。 2.请注意CI_PUSH_TOKEN是变量,必须包含API Token。 3. 也许 Gitlab 用户界面在您回答后发生了变化,现在是:Your project &gt; Settings &gt; CI / CD &gt; Environment Variables,您必须在其中设置CI_PUSH_TOKEN。如果你设置了protected 属性,那么这个变量只会暴露给protected 分支上的gitlab 运行器(比如master branch,默认情况下是受保护的)。【参考方案4】:

您当然可以使用 SSH 密钥,但您也可以提供用户和密码(具有写入权限的用户)作为秘密变量并使用它们。

例子:

before_script:
 - git remote set-url origin https://$GIT_CI_USER:$GIT_CI_PASS@gitlab.com/$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

【讨论】:

嗨,你没有使用任何令牌?直接你的用户名和密码?这样维护是不是有点危险? 好吧,首先在我看来,Gitlab 应该提供在 CI 阶段提交到 repo 的选项 :) 因此,作为解决方法,您可以使用 SSH 密钥或密码(由 Gitlab 机密提供)。从我的角度来看,这与所有 Gitlab 机密的风险级别相同。 请考虑支持这些问题:gitlab.com/gitlab-org/gitlab-ce/issues/41084 和 gitlab.com/gitlab-org/gitlab-ce/issues/18106,以便我们以安全的方式执行此操作。【参考方案5】:

另一种解决方案使用 Gitlab API 在 $CI_COMMIT_BRANCH 上的 terraform/ 目录中用 [skip ci] 提交文件 .terraform.lock.hcl

script:
  - 'STATUS=$(curl -Ss --head --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/files/terraform%2F%2Eterraform%2Elock%2Ehcl?ref=$CI_COMMIT_BRANCH" | grep "HTTP/1.1" | cut -d " " -f2)'
  - if [[ $STATUS == "404" ]]; then ACTION="create"; else ACTION="update"; fi
  - 'curl --request POST --form "branch=$CI_COMMIT_BRANCH" --form "commit_message=[skip ci] terraform.lock.hcl from pipeline" --form "actions[][action]=$ACTION" --form "actions[][file_path]=terraform/.terraform.lock.hcl" --form "actions[][content]=<.terraform.lock.hcl" --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits"'

【讨论】:

对于那些试图使用这个答案的人,请参阅gitlab.com/gitlab-org/gitlab-foss/-/issues/40326。努力获得这个很好的工作答案,但不断收到“404:找不到项目”。简而言之(截至 2021 年 4 月),CI_JOB_TOKEN 的使用似乎仅适用于公共存储库,或者如果您拥有 GitLab EE 版本,则该令牌将适用于私有存储库。 根据我之前的说明,最终能够通过创建并传递 api 范围的项目令牌作为 CI/CD 变量(我将其命名为 CI_PROJECT_TOKEN)并更改JOB-TOKEN: $CI_JOB_TOKENPRIVATE-TOKEN: $CI_PROJECT_TOKEN 的实例。不如 Job Token 最佳,但易于管理。

以上是关于通过 CI runner 将文件推送到 gitlab-ci的主要内容,如果未能解决你的问题,请参考以下文章

什么是 gitlab runner

将标签推送到外部 git 不会触发 Azure Pipelines CI

Gitlab CI/CD 到 Digital Ocean 使用 docker-compose 进行多个 repos

如何使用 gitlab-ci 作业推送到 gitlab 存储库?

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

Windows 上的 Gitlab Build Runner 使用 HTTP 而不是 SSH