Help us understand the problem. What is going on with this article?

GitLab CI/CDパイプラインからGitLabにコミット(Push)し直す方法

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

GitLab CI/CDパイプラインを使っていて、変更内容をGitLabのリポジトリに戻すということを考えていましたが、やらなくなってしまいました。せっかく調べたので供養しておこうと思ってここに書き記しておきます と思っていたのですが、結局ちゃんと使いました。

GitLab CI/CDパイプラインを使って、Gitリポジトリに対する変更内容をGitLabのgitリポジトリに戻す

GitLabパイプラインはとても便利なのでついつい何でも動かしたくなってしまうのです。
GitLabパイプラインからGitLabパイプラインを動かしたGitリポジトリを修正しよう等と思ったのが事の発端です。
#まあ、そういうこともあるのではないかと。

<後で図をいれる>

GitLab CI/CDはDockerで動いていて、.gitlab-ci.ymlファイルのあるリポジトリをDocker内で
git cloneしてから動きます。なので、git add、git commit、git pushすればいいじゃん?
って思うと思いますが、残念ながらそうはいきません。
なぜなら、git cloneされるときのリポジトリのURLへの接続アカウントがリードオンリーだからです。

対応方法は、いくつか方法があるようです。

  1. GitLabの自分のアカウントにPersonal Access Tokenを作成して、そのTokenで接続する
  2. SSHの公開鍵を作成し、GitLabの自分のアカウントに割り当てし、その鍵で接続する
  3. SSHの公開鍵を作成し、プロジェクトにDeploy Keyとして登録して、その鍵で接続する

なるべく個人のアカウントに紐付けたくない(自分がプロジェクトから抜けたらCIが動かなくなったとか
非常に困る)ので、今回は3を選択しました。

手順を書いておきます。

1. SSH鍵を作成します

https://docs.gitlab.com/ce/ssh/README.html#generating-a-new-ssh-key-pair
を見て鍵を作成して下さい。パスワードは付けないで下さい。

公開鍵をコピーしておきます。

2. プロジェクトのリポジトリのDeploy KeyにSSH公開鍵を登録します

プロジェクトの「設定」--->「リポジトリ」にいきます。
image.png

1でコピーしておいたSSHの公開鍵以下の「key」に貼ります。
image.png

「タイトル」は何でもいいでしょう。

「Write access allowed」にチェックを入れます。

「Add Key」を押します。

3. プロジェクトのVariableにSSH秘密鍵を登録します

プロジェクトの「設定」--->「CI / CD」にいきます。
image.png

Variablesを開きます
image.png

1のSSH鍵で秘密鍵をコピーします。

image.png
「Key」を「SSH_PRIVATE_KEY」とします。
「value」に1のSSH秘密鍵を貼り付けます。
#Variableではなくて、Fileにするという手もあります。

4. .gitlab-ci.yml を書く

以下のようなコマンドを.gitlab-ci.ymlに書きます。

bash
  script:
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan -H "$CI_SERVER_HOST" >> ~/.ssh/known_hosts
    - 'which ssh-agent || ( apk add --update openssh )'
    - eval "$(ssh-agent -s)"
    - echo "$SSH_PRIVATE_KEY" | ssh-add - > /dev/null
    - git config --global user.name "hogehoge-runner@example.jp"
    - git config --global user.email "hogehoge-runner@example.jp"
    - git remote set-url --push origin git@$CI_SERVER_HOST:$CI_PROJECT_PATH.git
    - git checkout $CI_COMMIT_REF_NAME
    - git pull
    - git add ./commit-file-example.txt
    - git status
    - ret=$(git status| sed -ne 's|.*\(clean\)|\1|p')
    - if [ -z $ret ];then
    -   git commit -m '[ci skip] Push by GitLab runner'
    -   git push
    - fi

上記の.gitlab-ci.ymlの注意点がいくつかあるので解説しておきます。

1. .sshディレクトリが必要なの?

.sshは、known_hostsファイルを入れるためだけに作っています。
もしかしたら、SSHのオプションで回避することができるかも。

2. sshコマンドは必要?

はい、必要です。
image: で指定するDockerイメージファイルに入れておきましょう。
同様にgitコマンドも必要です。ssh-agentはsshパッケージに入っています。

3. git remote set-urlて何してる?

git cloneしたときにoriginとして入っているリモートURLが通常はhttps://hogehogeなので、
それをSSH接続に変更するために上書きしています。

4. なぜ、checkoutしているの?

Runnderでgit cloneされるのはブランチではなくコミットに対してです。そのため、
ワークツリーはDetached HEAD状態になります。そのままでは、コミットしても
Detached HEADでコミットできないので作業のワークツリーをコミットしたブランチ
に戻します。

5. git statusの戻り値で条件分岐してgit commitしているのはなぜ?

ワーキングコピーがcleanな状態でgit commitするとエラーが出てgitlab ciがfailと認識して
そこで終了してしまいます。git status でワーキングコピーがクリーンなときにはcommitしない
ようにしてあります。pushも同様

6. コミットメッセージの[ci skip]ってなに?

コミットメッセージに[ci skip]が入っているとGitLabパイプラインがそのコミットに対しては
動きません。これを入れておかないと、自分がコミットし直したトリガーにより再度パイプラインが
走って無限ループ状態になります。

ブランチを切るなどの操作も可能です。

参考資料

A gitlab-ci config to deploy to your server via ssh
https://medium.com/@hfally/a-gitlab-ci-config-to-deploy-to-your-server-via-ssh-43bf3cf93775

Push Git Tag from GitLab Runner | thoean.com
https://thoean.com/push-git-tag-from-gitlab-runner/

GitBot – automating boring Git operations with CI | GitLab
https://about.gitlab.com/2017/11/02/automating-boring-git-operations-gitlab-ci/

ssh - GitLab CI denies access to push using a deploy key with write access - Stack Overflow
https://stackoverflow.com/questions/55224376/gitlab-ci-denies-access-to-push-using-a-deploy-key-with-write-access

GitLabCIの結果をGitHubにコミットする - kawaken's blog
http://kawaken.hateblo.jp/entry/2018/09/20/210542

Using SSH keys with GitLab CI/CD | GitLab
https://docs.gitlab.com/ee/ci/ssh_keys/

GitLab and SSH keys | GitLab
https://docs.gitlab.com/ce/ssh/README.html

gitlab-ci-git-push/git-push at master · IlyaSemenov/gitlab-ci-git-push
https://github.com/IlyaSemenov/gitlab-ci-git-push/blob/master/git-push

Push files to gitlab-ci via CI runner - Stack Overflow
https://stackoverflow.com/questions/40122780/push-files-to-gitlab-ci-via-ci-runner

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away