helmfileで管理されているArgoCDをArgoCDでデプロイする

Config Management Pluginでも実現できるが今回は使わない。
https://github.com/travisghansen/argo-cd-helmfile

## 永井産業

- helmfile templateでマニフェスト出力
- CIでリモートリポジトリにマニフェスト生成
- ArgoCDにはCIで作ったマニフェストを読ませることでhelmfileでもGitOps達成

## ArgoCDとは

ArgoCDは、KubernetesリソースをGitOpsでCDするためのツールである。
https://argo-cd.readthedocs.io/en/stable/

GitHubのリポジトリとrevision、pathを指定することでArgoCDが勝手にリポジトリの中のマニフェストを読んでクラスタに適用してくれる。うれしい。

## helmfileとは

helmfileは、helm chartを宣言的に管理するためのツールである。
https://github.com/helmfile/helmfile

HelmはKubernetesクラスタ向けのパッケージマネージャーである。
https://helm.sh/

ArgoCDもhelm chartが用意されている。
https://github.com/argoproj/argo-helm/tree/main/charts/argo-cd

## 課題

ArgoCDによってKubernetesリソースをGitOpsで継続的デプロイできるようになったが、helmfileで管理しているパッケージのリソースは手動で適用する必要がある。

```
$ helmfile apply
```

デプロイのために本番でコマンド打つのはダサい。
masterブランチにマージされたら全部勝手にデプロイされてほしい。

## 解決方法

GitHub Actionsで`helmfile template`をダンプしてリモートリポジトリに書き込むようにする。

`helmfile template`コマンドによって、helmfileで適用されるKubernetesマニフェストがすべて出力される。

つまり、`helmfile template`の出力結果をそのままファイルに書き込んでArgoCDにはそれを読ませればOKということである。

## 例

ArgoCDをhelmfileでインストールしてArgoCDでデプロイする。
ArgoCDはreleaseブランチを参照するようにする。
masterにpushされたら`dumped_helmfile_template.yaml`が生成されてreleaseブランチにpushされる。

```manifests/argocd-config/kustomization.yaml
resources:
  - ./argocd-config.yaml
  - ./helmfiles.yaml
```

```manifests/argocd-config/argocd-config.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: argocd-config
  namespace: argocd
spec:
  destination:
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://github.com/me/my-project
    targetRevision: release
    path: manifests/argocd-config
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - Validate=false
      - CreateNamespace=true
```

```manifests/argocd-config/helmfiles.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: helmfiles
  namespace: argocd
spec:
  destination:
    server: https://kubernetes.default.svc
  project: default
  source:
    repoURL: https://github.com/me/my-project
    targetRevision: release
    path: manifests/helmfiles
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - Validate=false
      - CreateNamespace=true
```

```helmfiles/helmfile.yaml
repositories:
  - name: argo-cd
    url: https://argoproj.github.io/argo-helm

helmDefaults:
  timeout: 300
  atomic: true
  wait: true

releases:
  - name: argocd
    namespace: argocd
    chart: argo-cd/argo-cd
    version: 5.29.1
```

```helmfiles/kustomizaiton.yaml
resources:
  - dumped_helmfile_template.yaml
```

```.github/workflows/release.yaml
name: release

on:
  push:
    branches:
    - master

jobs:
  generate-helmfile-template:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v2
      with:
        token: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
        # repo権限をつけたPATを用意する

    - name: Set up Helm
      uses: azure/setup-helm@v3
      with:
        version: "latest"

    - name: Set up Helmfile
      run: |
        VERSION=$(curl --silent https://api.github.com/repos/roboll/helmfile/releases/latest | jq '.tag_name' | sed 's/v//; s/"//g')
        wget https://github.com/roboll/helmfile/releases/download/v${VERSION}/helmfile_linux_amd64
        sudo mv helmfile_linux_amd64 /usr/local/bin/helmfile
        sudo chmod +x /usr/local/bin/helmfile

    - name: Generate Helmfile template
      run: |
        cd manifests/helmfiles
        helmfile template > dumped_helmfile_template.yaml

    - name: Commit helmfile template manifest
      run: |
        git config --local user.email "github-actions[bot]@users.noreply.github.com"
        git config --local user.name "GitHub Actions Bot"
        git switch -c release
        git add manifests/helmfiles/dumped_helmfile_template.yaml
        git diff --quiet && git diff --staged --quiet || git commit -m "Update dumped_helmfile_template.yaml [skip ci]"
        git push origin release
```