GCP: 一つのリポジトリからCloud Functionsへフォルダ別でデプロイする

# 概要

一つのリポジトリに、フォルダ別でFunctionを作成しています。
Cloud Buildを使ってCloud Functionsへデプロイするのですが、Functionごとにデプロイするフォルダを分けたいです。
これをgcloudignoreを使って対応しました。

# 環境
- 構成
    - Google Cloud Build: GitHubへのpushをトリガーにビルド＆デプロイする
    - Google Cloud Functions
- 言語
    - Java

## フォルダ構成
> src/
├ main/
│　└ java/
│　　├ common/
│　　│　└ 共通で使うクラス
│　　├ function1/
│　　│　└ Function1でだけ使うクラス
│　　└ function2/
│　　　　└ Function2でだけ使うクラス
└ test/
.gcloudignore
.gcloudignore_function1
.gcloudignore_function2
.gitignore
cloudbuild.yaml

※function1、function2のパッケージについては、entry-point以外はパッケージプライベートにして、他パッケージから参照されないようにしています。

# 一部のフォルダだけをデプロイ対象にする

ポイントは`--ignore-file`で指定したignoreファイルです。
指定がない場合は、デフォルトの`.gcloudignore`を参照し、記載されたファイルをignore(無視)します。
ファイル名を指定した場合は、ビルドのステップごとに違うファイルを参照できるので、ここで対象フォルダ以外を無視するように指定します。

特定のファイルやフォルダを無視リストから除外する(無視しない)には、先頭に`!`をつけます。
> To explicitly include any file named foo (useful if foo was excluded earlier in the file) and ignore a file named !bar:
>
```
!foo
\!bar
```
https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore#SYNTAX

ただし、今回は深い階層のフォルダを無視したいため、工夫が必要です。
gcloudignoreはgitignoreと基本的に同じ文法のため、そちらを参考にしました。
>Example to exclude everything except a specific directory foo/bar (note the /* - without the slash, the wildcard would also exclude everything within foo/bar):
>
```
    $ cat .gitignore
    # exclude everything except directory foo/bar
    /*
    !/foo
    /foo/*
    !/foo/bar
```
https://git-scm.com/docs/gitignore

想定通りに無視されているか確認する方法はこちらの記事を参考にさせていただきました。
[Gitでignoreされてるか確認する - Qiita](https://qiita.com/blue0513/items/1525a7f06d708e901690)

## 例

`/src/main/java/*`全体を無視リストへ入れてから、一部を除外する(無視しない)という書き方です。

```..gcloudignore_function1
src/test
/src/main/java/*
!/src/main/java/common
!/src/main/java/function1
```

```cloudbuild.yaml
steps:
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - functions
      - deploy
      - function1
      - --entry-point=function1.XxxxFunction
      - --ignore-file=.gcloudignore_function1
      - --trigger-http
      - --source=.
      - --runtime=java11
  - name: 'gcr.io/cloud-builders/gcloud'
    args:
      - functions
      - deploy
      - function2
      - --entry-point=function2.XxxxFunction
      - --ignore-file=.gcloudignore_function2
      - --trigger-http
      - --source=.
      - --runtime=java11
```

- Cloud BuildからCloud Functionsへのデプロイ
    - https://cloud.google.com/cloud-build/docs/deploying-builds/deploy-functions?hl=ja
- gcloud functions deployの設定一覧
    - https://cloud.google.com/sdk/gcloud/reference/functions/deploy?hl=ja

# gcloudignoreファイルをまとめる

今回、複数のgcloudignoreファイルを用意することになりました。
.gitフォルダなどいつも無視したいフォルダもあるため、そちらはまとめて記載できると便利です。

gcloudignoreでは、別のignoreファイルを取り込む記法が定義されています。
多段階での取り込みもできるため、gitignore > gcloudignore > 個別のgcloudignore のように段階的に無視リストを増やすことができます。
>
```
#!include:.gitignore
```

>This will include the contents of a .gitignore-style file at that path at that point in the file. It does not recurse (that is, the included file cannot #!include another file) and cannot be anywhere but the top-level directory to be uploaded.
https://cloud.google.com/sdk/gcloud/reference/topic/gcloudignore#ADVANCED-TOPICS

## 例

```..gcloudignore_function1
#!include:.gcloudignore
.gcloudignore*
/src/main/java/*
!/src/main/java/common
!/src/main/java/function1
```

```..gcloudignore
#!include:.gitignore
.git
.github
src/test
.gitignore
gradlew.bat
README.md
settings.gradle
```

```..gitignore
.gradle
build
```

# 感想

今回はやりたいことに対して、調べ方が分からず設定ドキュメントにたどり着くのが難しかったです。
また、gcloudignoreのドキュメントや解説は数が限られていますが、同じ文法であるgitignoreを調べることで各段に記事の量が増え、解決に至りました。

関連するFunctionsを同じリポジトリ、プロジェクトで管理したい！
デプロイ対象は分けたい！
という希望を実現できました:ok_woman: