くりにっき

フルスタックキュアエンジニアです

create-merge-requestを作った

これ何?

GitLab CI上で行った変更をMerge Requestとして投げるためのツールです。(開発期間は1週間くらい)

gitlab.com

GitHub Actionsだと peter-evans/create-pull-request が便利でよく使っているのですが、同じようなことをGitLab CIでもやりたくて作りました。

サンプル

一番簡単なサンプルはこれ。

stages:
  - build

create_mr_for_changes:
  stage: build
  
  image: debian:stable-slim

  before_script:
    # Download and install latest create-merge-request
    - apt-get update
    - apt-get install -y curl
    - VERSION=$(curl -s --fail https://gitlab.com/sue445/create-merge-request/-/raw/main/VERSION?ref_type=heads)
    - pushd /tmp
    - curl --retry 3 -L -o create-merge-request.tar.gz https://gitlab.com/sue445/create-merge-request/-/releases/${VERSION}/downloads/create-merge-request_Linux_x86_64.tar.gz
    - tar xzvf create-merge-request.tar.gz
    - mv create-merge-request /usr/local/bin
    - popd

  script:
    # TODO: Add your changes
    - date > now.txt

    # Create Merge Request if repo is changed
    - create-merge-request

  rules:
    # Run only scheduled pipeline
    # ref. https://docs.gitlab.com/ee/ci/pipelines/schedules.html
    - if: $CI_PIPELINE_SOURCE == "schedule"

このサンプルでは実行時にnow.txtを更新して、その差分をMerge Requestとして投げています。

頑張りポイント

gitコマンドを使わずにgitリポジトリにアクセスした

create-merge-requestはGoで作りスタンドアローンバイナリとして配布しています。

しかしスタンドアローンバイナリとして配布しているツールが実行環境にインストールされているgitコマンドに依存していると真のスタンドアローンとはいえないため、 https://github.com/go-git/go-git というGo実装のgitを利用して実行環境にgitがインストールされていなくても使えるようにしました。(システムにインストールされているgitコマンドを使うとgitのバージョンが変わった時に振る舞いが変わると面倒なので内部に組み込んだ方が依存を管理しやすいという嬉しさもある)

可能な限りパラメータを省略できるようにした

下記のhelpを見てもらえれば分かりますが、GitLabのリポジトリに新しいcommitをpushしてMerge Requestを投げるだけでも下記のパラメータが登場します。

REQUIRED PARAMETERS:
   --gitlab-api-endpoint value  GitLab API Endpoint (e.g. https://gitlab.com/api/v4) [$GITLAB_API_ENDPOINT, $CI_API_V4_URL]
   --gitlab-access-token value  GitLab access token [$GITLAB_ACCESS_TOKEN]
   --gitlab-project value       GitLab Project Path (e.g. gitlab-org/gitlab) [$GITLAB_PROJECT, $CI_PROJECT_PATH]

OPTIONAL PARAMETERS:
   --author-email value                     author email for commit (default: [email protected])
   --author-name value                      author name for commit (default: create-merge-request)
   --commit-message value, -m value         commit message (default: [create-merge-request] automated change)
   --source-branch value                    Merge Request branch name (default: create-merge-request/patch)
   --source-branch-suffix value             Merge Request branch name suffix (none,random,timestamp,short-commit-hash) (default: none)
   --target-branch value                    Send Merge Request to this branch (e.g. main, master) (default: main) [$CI_DEFAULT_BRANCH]
   --title value, -t value                  Merge Request title (default: Changes by create-merge-request)
   --description value                      Merge Request description (default: Automated changes by [create-merge-request](https://gitlab.com/sue445/create-merge-request))
   --labels value [ --labels value ]        Merge Request labels
   --assignees value [ --assignees value ]  Merge Request assignees (e.g. user1,user2)
   --reviewers value [ --reviewers value ]  Merge Request reviewers (e.g. user1,user2)

しかし初手で大量にパラメータを設定させるのは大変です。

GitLab CIでは $CI_API_V4_URL や $CI_PROJECT_PATH などの環境変数が自動で用意されているため、可能な限りそれらから設定を読み込むようにしました。

それによりGitLab CIで実行する時には GITLAB_ACCESS_TOKEN でGitLabのアクセストークンだけ設定されていればとりあえずMerge Requestが作成できるようにしました。

おまけ

GoのバイナリをGitLabのリポジトリのreleasesに添付する時に https://github.com/goreleaser/goreleaser を利用したのですが、GitLab CI用の設定が現在のGitLabではDeprecatedなものだったのでパッチを投げました。

github.com