この記事は、ニフティグループ Advent Calendar 2024 10日目の記事です。
CLIツールを社内にプライベートtapリポジトリを作成し、社内に配布しました。
意外と記事がなかったのでその方法をご紹介します。
アプリケーションのリリースに使っているのはGoReleaserです。
きっかけ
ニフティ株式会社では現在Oneloginを使っています。
AWSのIAM RoleにAssumeRoleする際は以下のOneloginが提供しているツールを使っている社員がほとんどです。
https://github.com/onelogin/onelogin-python-aws-assume-role
このツールはjava版もあるのですが、どちらにせよランタイムのインストールが必要です。
また比較的頻繁に更新されているわけではないため、バージョンによっては依存ライブラリの問題でセットアップが失敗するなどの問題がありました。
そこで、これをGoで作り直すことでシングルバイナリかつセットアップ不要にしつつ、brewで配布することでMacやWSL環境への導入をより簡単にしようと決めました。
サードパーティ製の他のツールを使うという手段もありましたが、私自身がインフラ管理者ではない(全社向けの選定権がない)ことや、現在使っているツールからの移行モチベーションを上げるため設定ファイルを流用することが重要だったこと、インナーソース化することでより柔軟に開発者自身が必要な機能を追加していけることを重視し、自作することに優位性があると判断しました。
Tapリポジトリの作成
バイナリを配布するためのtapリポジトリを作成します。
このリポジトリの名前は homebrew-<repo>
の形式である必要があります。
https://docs.brew.sh/Taps#repository-naming-conventions-and-assumptions
プライベートなtapリポジトリを作成する場合、GitHubのトークンを使ってダウンロードURLを作る必要があります。
以下のGistが非常に参考になるため、これを使います。
https://gist.github.com/ZPascal/b21c652b811872b3f56db9d54d61d6c6
GitHubPrivateRepositoryDownloadStrategy
というクラスがダウンロード戦略となります。
指示通り、tapリポジトリのlib/配下に配置します。
アプリケーションの作成
今回はHomebrewで配布する部分がメインなので、ここではGoReleaserの設定について紹介します。
GoReleaserは簡単に複数のOSやCPUアーキテクチャ向けにBuildしたり、パブリッシュすることができるツールです。
https://github.com/goreleaser/goreleaser
このツールを使ってGitHub Actionsでリリースしています。
アプリケーションリポジトリからtapリポジトリにpushしてPRを作成する必要があるため、PrivateAccessTokenが必要になります。
ダウンロード戦略として先ほど作成したGitHubPrivateRepositoryDownloadStrategy
を使うよう指定します。
.goreleaser.yaml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
version: 2 before: hooks: - go mod tidy - go generate ./... builds: - main: ./cmd/ binary: onelogin env: - CGO_ENABLED=0 goos: - linux - windows - darwin archives: - format: tar.gz name_template: >- {{ .ProjectName }}_ {{- title .Os }}_ {{- if eq .Arch "amd64" }}x86_64 {{- else if eq .Arch "386" }}i386 {{- else }}{{ .Arch }}{{ end }} {{- if .Arm }}v{{ .Arm }}{{ end }} format_overrides: - goos: windows format: zip changelog: sort: asc filters: exclude: - "^docs:" - "^test:" brews: - name: onelogin download_strategy: GitHubPrivateRepositoryReleaseDownloadStrategy custom_require: lib/private_strategy repository: owner: niftycorporation name: homebrew-tap branch: "{{ .ProjectName }}" token: "{{ .Env.PRIVATE_GITHUB_TOKEN }}" pull_request: enabled: true draft: false base: branch: master |
workflow
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
name: Upload Release Asset on: push: tags: - 'v*' permissions: contents: write jobs: build: name: Upload Release Asset runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Go uses: actions/setup-go@v5 with: go-version-file: go.mod cache: true - uses: goreleaser/goreleaser-action@v6 with: distribution: goreleaser version: "~> v2" args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PRIVATE_GITHUB_TOKEN: ${{ secrets.PRIVATE_GITHUB_TOKEN }} |
このWorkflowが実行されるとreleasesが作成され、tapリポジトリにPRが作成されます。
一部変更していますが、以下のようなファイルが生成されます。
GoReleaserを使わなくてもこのようなファイルがあれば配布すること自体は可能です。
onelogin.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# typed: false # frozen_string_literal: true # This file was generated by GoReleaser. DO NOT EDIT. require_relative "lib/private_strategy" class Onelogin < Formula desc "" homepage "" version "1.0.2" on_macos do on_intel do url "https://github.com/niftycorporation/onelogin-go-aws-assume-role/releases/download/v1.0.2/onelogin-go-aws-assume-role_Darwin_x86_64.tar.gz", using: GitHubPrivateRepositoryReleaseDownloadStrategy sha256 "hash" def install bin.install "onelogin" end end on_arm do url "https://github.com/niftycorporation/onelogin-go-aws-assume-role/releases/download/v1.0.2/onelogin-go-aws-assume-role_Darwin_arm64.tar.gz", using: GitHubPrivateRepositoryReleaseDownloadStrategy sha256 "hash" def install bin.install "onelogin" end end end on_linux do on_intel do if Hardware::CPU.is_64_bit? url "https://github.com/niftycorporation/onelogin-go-aws-assume-role/releases/download/v1.0.2/onelogin-go-aws-assume-role_Linux_x86_64.tar.gz", using: GitHubPrivateRepositoryReleaseDownloadStrategy sha256 "hash" def install bin.install "onelogin" end end end on_arm do if Hardware::CPU.is_64_bit? url "https://github.com/niftycorporation/onelogin-go-aws-assume-role/releases/download/v1.0.2/onelogin-go-aws-assume-role_Linux_arm64.tar.gz", using: GitHubPrivateRepositoryReleaseDownloadStrategy sha256 "hash" def install bin.install "onelogin" end end end end end |
brew installする
まずローカルからプライベートリポジトリにアクセスするためにPrivateAccessTokenを作成し、 HOMEBREW_GITHUB_API_TOKEN
という環境変数に指定します。
tapリポジトリを指定し、インストールします。
このとき、リポジトリ名の homebrew-
部分は省略することができます。
1 2 |
brew tap niftycorporation/tap brew install niftycorporation/tap/onelogin |
Brewfileには以下のように記載します。
1 2 |
tap "niftycorporation/tap" brew "niftycorporation/tap/onelogin" |
これでプライベートのtapリポジトリでバイナリを配布することができました。
まとめ
ここまでプライベートのtapリポジトリを作成し、配布する方法を紹介してきました。
企業内で独自のソフトウェアを配布したいことはそれなりに多いんじゃないかと思っています。
特に以下はかなりハマりポイントでした。
- tapリポジトリの命名規則
- PATを使ったダウンロード戦略の作成
- PATを使ったダウンロード戦略の指定
今ハマっている方や今後やろうと思っている方はぜひこれらに気をつけていただければと思います。
ここからはタイトルに関係のない今後の展望についてですが、このリポジトリは現在インナーソースとして社内公開していて利用者も比較的多いプロジェクトになっていると考えています。
しかしコントリビュータがなかなか増えず、敷居の高さや関心を引けていないことが問題かと思っています。
ツール自体メイン機能はほぼ完成していますが、爆速で作ったためリファクタリングや処理の効率化、ドキュメントの整備などやりたい事自体はまだまだある状況です。
また、普段使わない言語や領域に触れるなどエンジニアとしての成長も望めるため、コントリビュータを増やしインナーソースやOSSに興味を持ってもらえるよう活動していく予定です。
tapリポジトリについても現在配布されているのがこのツールのみということもあり寂しいので、こちらも敷居を下げより簡単に追加できるようになればいいなと想像しています。
最後に、この記事がどなたかのお役に立てば幸いです。
明日は、@hayabusa01 さんの記事です。 お楽しみに!