GitLab Private Host環境におけるgoreleaserを利用したCI設定の留意事項

# はじめに

独自にホストしているGitLab環境化における[goreleaser](https://goreleaser.com/)の設定手順についてです。
下記のような人向けの内容となります。

- GitLabを独自のサーバーとして運用している。
- Golangで開発しており、 goreleaserを利用してビルドモジュールとタグでバージョン管理したい。

いつもはコンテナのimageとしてビルド結果を残していますが、ツールとして各環境向けの実行可能ファイルを残す必要がありました。
その際、ハマった点等記載しています。

# 前提

- GitLabのバージョンとしては、11.11.Xを利用していること。
- GitLab Runnerとして[Docker Executor](https://docs.gitlab.com/runner/executors/docker.html)を利用すること。
- GitLab RunnerのDocker Executorの[セットアップ](https://docs.gitlab.com/runner/install/)が既に行われていること。

# 手順

## Gitlab Runner用イメージの作成

Gitlab Runnerでgoreleaserを動かすためのdocker imageを作成します。
dockerhubにある[goreleaser](https://hub.docker.com/r/goreleaser/goreleaser)を利用しようとしましたが、shell実行ができずに下記のようにエラーになってしまいました。

```shell:pipeline-console
goreleaser: error: unexpected sh, try --help
```

なので、独自のimageを作成しました。
golangのベースイメージに対して、goreleaserをインストールしたdockerイメージを作成します。
そのために、下記のようにDockerfileを作成します。今回は、goのバージョンは、1.12ベースで作成しています。

```dockerfile:goreleaser
FROM golang:1.12-alpine

RUN apk update && apk add --no-cache git
RUN go get github.com/goreleaser/goreleaser
```

そして、下記のようにdockerイメージをPrivate Container Resitryにpushします。
Private Container Resitryとして、[GitLab Container Registry](https://docs.gitlab.com/ee/user/packages/container_registry/)を利用しています。パスはDockerfileを管理しているリポジトリにしています。

```shell:dokcer-build
$ docker build . -t gitlab.xxxx.jp:4567/group/subgroup/goreleaser:1.0
$ docker push gitlab.xxxx.jp:4567/group/subgroup/goreleaser:1.0
```

## goreleaserを使うリポジトリ側の設定

.goreleaser.ymlにてgoreleaserの動作設定と、.gitlab-ci.ymlでCIの設定を行います。
`https://gitlab.xxxx.jp:4567/group/subgroup/project-x.git` に対しての設定を行うとします。

### .goreleaser.ymlの設定

```yaml:.goreleaser.yml
project_name: project-x

builds:
  - env:
      - CGO_ENABLED=0
    goos:
      - windows
      - darwin
      - linux
    goarch:
      - amd64

archives:
  - replacements:
      darwin: Darwin
      linux: Linux
      windows: Windows
      amd64: x86_64"
    name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
checksum:
  name_template: "checksums.txt"
changelog:
  sort: asc
  filters:
    exclude:
      - "^docs:"
      - "^test:"
release:
  gitlab:
    owner: group/subgroup
    name: project-x
gitlab_urls:
  api: https://gitlab.xxxx.jp/api/v4
  download: https://gitlab.xxxx.jp/

```

**注意事項**

**`project_name` は必ず設定しましょう。**
下記のようにMac、Linux環境化で展開できない圧縮ファイルが出来上がってしまいます。

```shell
$ tar zxvf _1.0.0_Linux_x86_64.gz
tar: This does not look like a tar archive
tar: Skipping to next header
tar: Exiting with failure status due to previous errors
$
```

**`gitlab_urls` で、GitlabのAPIのURLを指定してください。**
でなければ、下記のように　`gitlab.com` 側にアクセスしてしまいます。

```shell
      • GITHUB/GITLAB/GITEA RELEASES
         • creating or updating release repo= tag=v1.0.0
   ⨯ release failed after 31.06s error=GitHub/GitLab/Gitea Releases: failed to publish artifacts: GET https://gitlab.com/api/v4/projects/group/project/releases/v1.0.0: 401 {message: 401 Unauthorized}
```

**GitLabの[Subgroups](https://docs.gitlab.com/ee/user/group/subgroups/)を使う場合は、`release.gitlab.onwer` にてgroup/subgroupsを指定する必要があります。**

```yaml:
release:
  gitlab:
    owner: group/subgroup
    name: project-x
```

### .gitlab-ci.ymlの設定

下記のように設定しています。

```yaml:.gitlab-ci.yml
services:
  - docker:dind

stages:
  - build

build:
  image: gitlab.xxxx.jp:4567/group/subgroup/goreleaser:1.0
  stage: build
  tags:
    - goreleaser-shared-docker
  script:
    - goreleaser
  only:
    - tags
  except:
    - branches
```

imageは、 [Gitlab Runner用イメージの作成](#Gitlab Runner用イメージの作成)で作成したimageを指定します。
また、tagsは、各自の環境のRunnerを指定するようにしてください。


### リポジトリ(プロジェクト)側の設定

GITLAB_TOKENを[Settings]->[CI/CD]->[Variables]にて、APIを実行するためのTOKENを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/0ff6eef9-b66e-83da-9207-1787b2456fa3.png)


## 結果

タグをつける事により、CIが動作して下記のように Release情報が自動的に作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/268550/037e0b7e-9721-a410-82af-05da8d27d7de.png)


# 参考

- https://docs.gitlab.com/runner/
- https://goreleaser.com/