ftpサーバーにupload/download-artifactsするGitHub Actionを作った

はじめに

株式会社Synamonのエンジニアの岡村です。自分はGitHub Actionsを使ったCIをよく弄っているのですが、先日、とある事情からCIで作成された成果物をNASサーバーにアップロードする必要が出てきたので、それに対応するために、ftpプロトコルで成果物をアップロードするGitHub Actionを作成してみました。既存のActionのフォークとはいえ、きちんと体裁の整ったActionを作るのは初めてだったのと、思っていたより簡単に作れたので、せっかくだから記事にしてみる事にしました。

GitHub ActionsとNASへのアップロード

GitHub Actionsでは、作成された成果物は、基本的に公式の用意しているupload-artifactアクションでアップロードされます。 アップロードしたものはGitHubが用意したオンラインストレージ上に保存され、保存された成果物は実行の要約ページ上にある成果物一覧に表示されて、ダウンロードする事が出来るようになります。

ただし、GitHubが用意したオンラインストレージには

  • 容量に応じて課金される(S3の10倍くらい)*1
  • 最大でも90日(プライベートリポジトリの場合は最大400日)で削除される*2
  • 一覧性が悪い(APIを捏ねる事で解決自体は可能)
  • ダウンロードの帯域が比較的細い

といった制約があります。

諸事情により、今回のケースでは以前作成したAWS環境や、s3を含むクラウドストレージの使用が出来なかった為、代替手段として(オンプレでRunnerを走らせていたのもあり、)同じLAN内にあるNASサーバーへのアップロードを実施することにしました。

アップロード方法の検討

NASサーバーはSynology製で、アップロード手段は色々用意されていました。最初はネットワークストレージのマウントや公式の提供しているAPIでのアップロードを検討したのですが、

  • ビルドしているマシン側にストレージのマウント設定が必要
  • 公式のWebAPIのドキュメントが難解で対応が困難

であったため、枯れて安定した技術であるFTPを使ったアップロードを試してみる事にしました。

公式upload-artifactアクションのカスタマイズ

最初は直接curlコマンドでアップロードを行っていたのですが、すぐにそれでは機能が足りないことに気づきました。

  • 複数の成果物をアップロードしたい
  • アップロードした成果物をダウンロードして再利用したい
  • パターンで複数ファイルを指定したい

curlやzipを駆使して出来ないこともないのですが、ステップ数が多くなってしまいyamlファイルの可読性が下がり、メンテナンスもし辛くなってしまいます。

そこで、以前s3へのアップロード周りでMarketplace製のActionを使っていた経験から、ftpを使って成果物をアップロードできるActionも転がっているのではないかと探してみました。ところが、ftpによるデプロイActionは幾つか見つかったのですが、純粋にupload-artifactのftp版となるようなActionはまだ存在していないようでした。

そのため、GitHubが公式で提供しているActionであるupload-artifact及びdownload-artifactをフォークし、アップロード処理のみをftpで実装したカスタムActionの作成を試してみることにしました。

フォークしたupload-artifactアクションの実装

作成したものがこちらです。

github.com

github.com

upload版とdownload版を両方作りました。作り自体は単純で、それぞれのオリジナルのActionの内部で使われているArtifactClientインターフェースを実現するftp-artifact-clientを実装しただけです。公式の実装できちんとインターフェースが区切られていたので、その中でもそれぞれのaction内で使用されているメソッドを実装し、テストも作成しています。

あとは、ftpサーバーに接続するためのアドレスやID, パスワード等のパラメータを露出させて実装は完了です。

自作したActionの感想

入力がupload-artifact及びdownload-artifactの仕様に沿っているので学習コストが滅茶苦茶少ないです。エンドポイントやユーザー情報が一致していればuploadした成果物を別のjobでdownloadして再利用する事も可能です。nodejs製でプラットフォーム間の互換も(多分)あります*3。既存のツールと同じように扱えるのは正義ですね。

今後の課題としては、多少効率が悪い箇所があるのでその最適化と、元のupload/download-artifactが更新された時にどの程度追従できるか/するべきかという所でしょうか。なるべく安定していてほしい……

GitHub Marketplaceへの公開

せっかくなのMarketplaceに公開してみました。GitHub公式のドキュメントを読めば簡単に公開することが出来ます。

github.com

github.com

npmのパッケージ詳細ページと異なり、GitHub Marketplaceの詳細ページ上ではこのActionがどの程度利用されているのか確認できないのがちょっとさみしいですね。

まとめ

GitHub ActionsでローカルのRunnerからNASにアップロードする為にupload-artifactをフォークしたftp-upload-artifactアクションを作りました。GitHub Actionsは他のCIツールに比べるとまだ若く、ニッチなニーズを満たすようなActionは見つからないこともありますが、簡単にActionを作成できるし利用できるので、「なければ作ればいいじゃない」がとてもやりやすい仕組みになっているように感じました。ftp以外のプロトコルでupload-artifactするActionもその気になれば簡単に作れそうです。

*1:GitHubは$0.25/GB、s3はap-northeast-1のstandardクラスで0.025$/GB。2023年4月9日時点

*2:https://docs.github.com/ja/actions/learn-github-actions/usage-limits-billing-and-administration#artifact-and-log-retention-policy

*3:windowsとmac上で動作を確認済