Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Golden Path作成編②〜

# はじめに
[前回の記事](https://qiita.com/shin7446/items/ce86d9bbb5121579f9ce)では、`Template`というリソースを作成してGolden Pathの実行まで完了しました。
今回は`template.yaml`に追記を行い、より実践的なGolden Pathの作成を行います。

# 実現する環境
今回は以下の環境を構成します。
![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/e5c69ce7-0a0a-9d3d-5e72-bc99bae59a0a.png)


# 章項目
今回のテーマは6つの記事で構成されています。
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜環境導入編〜](https://qiita.com/shin7446/items/bafb3619caf5c8ba28c1) 
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜認証設定編〜](https://qiita.com/shin7446/items/b54ebda4ee91ea5f4ca2)
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜GitHub Integration編〜](https://qiita.com/shin7446/items/c35010c3ea566beadc5a)
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Golden Path作成編①〜](https://qiita.com/shin7446/items/ce86d9bbb5121579f9ce)
* [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Golden Path作成編②〜](https://qiita.com/shin7446/items/0c181c2f7cc63917bd7c) この記事
* Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Component UI改善編〜

# 前提条件
以下の記事の実行が完了していること
1. [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜環境導入編〜](https://qiita.com/shin7446/items/bafb3619caf5c8ba28c1) 
1. [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜認証設定編〜](https://qiita.com/shin7446/items/b54ebda4ee91ea5f4ca2)
1. [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜GitHub Integration編〜](https://qiita.com/shin7446/items/c35010c3ea566beadc5a)
1. [Red Hat Developer Hub (Backstage) でGolden Pathを作ろう〜Golden Path作成編①〜](https://qiita.com/shin7446/items/ce86d9bbb5121579f9ce)

# Sample Skeletonの取得
今回実行するGolden PathでデプロイするためのアプリケーションとK8s ManifestのサンプルコードをGitHubから取得します。
サンプルコードは以下のGitリポジトリにありますので、こちらをcloneしてきましょう。
https://github.com/rhdh-skitamura-org/sample-skeleton-origin
```
git clone https://github.com/rhdh-skitamura-org/sample-skeleton-origin.git
```

そして`app-skeleton`ディレクトリと`manifest-skeleton`を自分の`sample-skeleton`ディレクトリにコピーしてきましょう。
※`app-skeleton`はすでに存在しますが、上書きしてしまってOKです。
```
cp -R sample-skeleton-origin/app-skeleton sample-skeleton/
cp -R sample-skeleton-origin/manifest-skeleton sample-skeleton/
```

少しディレクトリの中身を確認します。
`app-skeleton`は前回の記事で記載した通り、アプリケーションコードのサンプルを格納してあります。
```
$ tree -L 1 app-skeleton
app-skeleton
├── Dockerfile
├── LICENSE
├── README.md
├── catalog-info.yaml
├── design
├── images
├── site
└── tests
```

`manifest-skeleton`にはその名の通り、様々な用途のK8s Manifestが格納されています。
```
$ tree -L 3 manifest-skeleton
manifest-skeleton
├── README.md
├── argocd
│   ├── argocd-app-build.yaml
│   └── argocd-app-dev.yaml
└── kustomize
    ├── app
    │   ├── base
    │   └── overlays
    └── build
        ├── base
        └── overlays
```
* `manifest-skeleton`: こちらは主に以下の種類のmanifestを格納するSkeletonになります。
    * `argocd`: RHDHが作成するArgoCDの`Application`リソースを格納するディレクトリです。
    * `kustomize/app`: アプリケーションのデプロイに必要なK8s Manifestを格納します。
    *  `kustomize/build`: CIの実行に必要なK8s Manifestを格納します。

# Vault Secretの作成
`manifest-skeleton`の中を確認すると、いくつかのSecretを`ExternalSecret`として設定していることがわかります。
```
$ tree manifest-skeleton/kustomize/build/base
manifest-skeleton/kustomize/build/base
├── el-route.yaml
├── external-secret-basic-auth.yaml
├── external-secret-sonar-settings.yaml
├── external-secret-webhook.yaml
├── external-secret-webhooksecret.yaml
├── git-cli.yaml
├── git-clone.yaml
├── job-create-webhook.yaml
├── kustomization.yaml
├── kustomize.yaml
├── pipeline.yaml
├── sonarqube.yaml
├── tekton-pvc.yaml
├── trigger-sa.yaml
├── triggertemplate.yaml
└── trivy.yaml
```
```
$ cat manifest-skeleton/kustomize/build/base/external-secret-basic-auth.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: external-${{ values.git }}-basic-auth
spec:
  secretStoreRef:
    name: vault-secretstore
    kind: ClusterSecretStore
  target:
    name: ${{ values.git }}-basic-auth
  data:
  - secretKey: .git-credentials
    remoteRef:
      key: secret/${{ values.git }}-basic-auth
      property: .git-credentials
  - secretKey: .gitconfig
    remoteRef:
      key: secret/${{ values.git }}-gitconfig
      property: .gitconfig
```
そのため、あらかじめVaultでSecret情報を登録しておきましょう。
今回必要なSecret情報は以下の4つになります。
* `git_token` : Golden Pathの実行によって作成されたappリポジトリに対してwebhookを設定するjobを実行します。そのjobにGitHubのPersonal Access Tokenを渡す必要があるため、その値をこの変数に格納します。
* `webhook_secret` : webhookには任意のWebhook Secretを設定する必要があるため、こちらもSeretとして管理します。
* `.git-credentials` : manifestリポジトリ内の`deployment.yaml`はPipeline上で`image`の書き換えを行います。そのためGitHubにPushするために必要なクレデンシャル情報を`.git-credentials`として渡す必要があります。
* `sonar-project.properties` : 今回のGolden Pathで用意されたPipelineでは、SonarqubeでのScanが含まれます。そのSonarqubeとの連携に必要な情報をSecretとして管理します。

## GitHubのAccess Tokenの取得
`git_token`や`.git-credentials`に必要なAccess Tokenを取得します。
* GitHubの右上のプロフィールアイコンから`Settings`を選択します。
* 左側のサイドバーから`Developer settings`を選択します。
* `Personal access tokens`セクションを選択し、`Tokens (classic)`を選択します。
* `Generate new token (Classic)`を選択します。
* 任意の名前を記述し、`Select scopes`で以下のScopeにチェックを入れて`Generate token`を選択します。
    * `public_repo`
    * `admin:repo_hook`

![ScreenShot 200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/718c5f9b-5d3d-99cd-ab11-3933c2db4fe6.png)

するとtokenが発行されるので、こちらをメモしておきましょう。
![ScreenShot 201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/a55845e6-6175-0bdb-d6f3-36a060461894.png)

## SonarqubeのSecretの取得
次にSonarqubeの　　を取得します。
Sonarqubeの画面右上の`Create Project`→`Manuary`を選択します。
![ScreenShot 205.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/7af43b17-9f05-6882-d601-3d932c6b7302.png)

`default`というProject名で作成します。
![ScreenShot 206.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/d07aaff5-cb36-e50e-2b1a-f48c6bc11c0b.png)

Project画面で`Locally`を選択します。
![ScreenShot 208.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/396dd6f1-527f-59da-525d-aace8cee477a.png)

`Provide a token`で`Generate`を選択します。
![ScreenShot 209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/be1228e3-1ab2-13e5-1fb7-1f4114b5819a.png)

払い出されたTokenを環境変数に格納します。
![ScreenShot 210.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/cbce98f2-97fe-39f8-f22e-8fa52e48c560.png)

```
export SONARQUBE_TOKEN="<取得したToken>"
```

## Vaultの操作
では必要なSecretを作成していきます。
まずは環境変数に各値を入れていきます。
```
export GIT_TOKEN="<取得したPersonal Access Token>"
# ROSAのapp配下のドメインを入力
export CLUSTER_URL="<apps.rosa.<rosa cluste名>.xxx.xx.openshiftapps.com>"
export WEBHOOK_SECRET="<任意の値>"
export GITHUB_USER="<自分のGitHub ID>"
```

VaultにSecretを作成していきます。
```
# github-env.yamlの作成
cat <<EOF > github-env.yml
git_token: "$GIT_TOKEN"
cluster_url: "$CLUSTER_URL"
webhook_secret: "$WEBHOOK_SECRET"
EOF

# github-gitconfigの作成
cat <<EOF > github-gitconfig
[credential "https://github.com"]
  helper = store
EOF

# sonar-project.propertiesの作成
cat <<EOF > sonar-project.properties
sonar.projectKey=default
sonar.organization=default
sonar.token=$SONARQUBE_TOKEN
sonar.host.url=sonarqube-sonarqube.sonarqube.svc:9000
EOF

# Secret作成
vault kv put secret/github-webhook env.yml=@github-env.yml
vault kv put secret/github-webhooksecret webhook_secret="$WEBHOOK_SECRET"
vault kv put secret/github-basic-auth .git-credentials="https://$GITHUB_USER:$GIT_TOKEN@github.com"
vault kv put secret/github-gitconfig .gitconfig=@github-gitconfig
vault kv put secret/sonar-settings sonar-project.properties=@sonar-project.properties
```

# Golden Pathによるサンプルアプリのデプロイ方法
RHDH上のGolden Pathからどうやってアプリをデプロイするのかをお伝えします。

基本的にRHDHからGolden Pathを実行してK8s（OpenShift）にリソースをデプロイする際は、ArgoCDによるGitOpsを利用します。
というのも、RHDH(Backstage)でK8sに対してできるactionはArgoCDのApplicationの実行くらいです。もちろん独自のPluginを実装すればK8sへの操作を操ることは可能ですが、RHDHはこれまでの記事で説明した通り、Gitとの連携をかなり重視する思想であるため、K8s Manifestのデプロイも極力GitOpsで実現しましょう、というスタンスは正しいと思います。

RHDHでは、ArgoCDのPluginをインストールすることによって「ArgoCDの`Application`リソースをデプロイする」という`Action`を使用することができるようになります。
まずはArgoCDのPluginをインストールしましょう。

# ArgoCDとの連携設定

RHDHの動的Pluginのインストール機能を使って、helmのupgradeでPluginのインストールを行います。インストールする対象は[こちら](https://access.redhat.com/documentation/ja-jp/red_hat_developer_hub/1.0/html/administration_guide_for_red_hat_developer_hub/rhdh-supported-plugins)の中にある`@roadiehq/scaffolder-backend-argocd`です。

`values.yaml`に以下のように追記します。
```（抜粋）values.yaml
    plugins:
      - package: ./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-org-dynamic
        disabled: false
      # ここから
      - package: ./dynamic-plugins/dist/roadiehq-scaffolder-backend-argocd-dynamic
        disabled: false
      # ここまで
```

次に`app-config-rhdh.yaml`を編集します。
```（抜粋）app-config-rhdh.yaml
    integrations:
    ___omit____
    catalog:
    ___omit____
    # ここから
    argocd:
      appLocatorMethods:
      - instances:
        - name: main
          password: ${ARGOCD_PASSWORD}
          url: ${ARGOCD_INSTANCE_URL}
          username: ${ARGOCD_USERNAME}
        type: config
    # ここまで
```

次にArgoCDとの連携に必要な変数を取得します。
まずはArgoCDのAdminパスワードを取得します。
```
export ARGOCD_USERNAME="admin"
export ARGOCD_PASSWORD=$(oc get secret -n openshift-gitops openshift-gitops-cluster  -o jsonpath="{.data.admin\.password}" | base64 -d)
echo $ARGOCD_PASSWORD
```

ArgoCDのRoute URLを取得します。
```
export ARGOCD_INSTACE_URL="https://$(oc get route -n openshift-gitops openshift-gitops-server -o jsonpath={.status.ingress[0].host})"
```

最後に`create-secret.yaml`を編集します。先ほど取得した変数を追記します。
```（抜粋）create-secret.yaml
# Secret作成
oc -n rhdh create secret generic rhdh-secrets \
  ___omit____
  --from-literal=ARGOCD_INSTANCE_URL="${ARGOCD_INSTANCE_URL}" \
  --from-literal=ARGOCD_PASSWORD="${ARGOCD_PASSWORD}" \
  --from-literal=ARGOCD_USERNAME="${ARGOCD_USERNAME}" \
```

ここまで設定が完了したら、`create-secret.yaml`を実行します。
```
cat create-secret.sh | envsubst | bash
```

これで`Template`からArgoCDの`Application`を作成する`Action`を設定することができました。
`https://<RHDH URL>/create/actions`にアクセスして`Action`が追加されていることを確認しましょう。
![ScreenShot 183.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/272129cc-5d2e-4d9c-ff1c-0532ff0682c1.png)


# Templateの追記
ArgoCDとの連携設定が完了したので、`template.yaml`にいくつか新しいStepを追加します。
まずは`id: publish-app-to-github`の下に以下の2つの`action`を追記しましょう。
```（抜粋）template.yaml
    - id: publish-app-to-github
      ____omit____
    # ここから
    - id: manifest_template
      name: Generating the K8s Manifest Component
      action: fetch:template
      input:
        url: ./manifest-skeleton
        copyWithoutTemplating:
          - .github/workflows/
        values:
          git: ${{ parameters.git }}
          git_host_url: ${{ parameters.git_host_url }}
          git_owner_name: ${{ parameters.git_owner_name }}
          app_name: ${{ parameters.app_name }}
          owner: ${{ parameters.owner }}
          system: ${{ parameters.system }}
          description: ${{ parameters.description }}
        targetPath: ./tenant-manifest
    
    - id: publish-manifest-to-github
      if: ${{ parameters.git == "github" }}
      name: Publish Manifest Repository to GitHub
      action: publish:github
      input:
        repoUrl: ${{ parameters.git_host_url }}?owner=${{ parameters.git_owner_name }}&repo=${{ parameters.app_name }}-manifest
        repoVisibility: public
        sourcePath: ./tenant-manifest
        defaultBranch: develop
        protectDefaultBranch: false
    # ここまで
```
`app-skeleton`に対して実行していた`fatch: template`と`publish:github`を追記した形になります。記述方法はほぼ同様なのでここでは説明を割愛します。


次に、`id: register-to-github`の下に以下の`action`を追記しましょう。
```（抜粋）template.yaml
    - id: register-to-github
      ____omit____
    # ここから
    - id: create-argocd-resources
      name: Create ArgoCD Resources
      action: argocd:create-resources
      input:
        appName: ${{ parameters.app_name }}-bootstrap
        argoInstance: main
        namespace: openshift-gitops
        repoUrl: https://${{ parameters.git_host_url }}/${{ parameters.git_owner_name }}/${{ parameters.app_name }}-manifest.git
        path: 'argocd/'
    # ここまで
```
* `input.appName` : この`action`によってデプロイするArgoCDのApplication名です。
* `input.argoInstance` : これは`app-config`で設定したArgoCD instanceのNameを記述します。今回は`main`となります。
* `input.namespace` : `Application`のデプロイ先のNamespaceです。
* `input.repoUrl` : GitOpsの参照先となるGitのURLです。
* `input.path` : GitのURLにおけるサブディレクトリを指定します。

今回の設定によって、`id: register-to-github`でPushしたリポジトリの`/argocd`配下のK8s Manifest（あるいは`kustomization.yaml`）をGitOpsでデプロイする`Applicationが`デプロイされます。

現時点での`template.yaml`は以下のようになっています。
<details><summary>template.yaml（クリックして展開）</summary><div>


```template.yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
  name: sample-app-template
  title: Create a sample application with a CI pipeline
  description: Provides the sample code and CI pipeline to build and deploy a sample application on OpenShift.
  tags:
    - recommended
spec:
  owner: user:default/<自分のGitHub ID>
  type: service

  parameters:
    - title: Provide information about the new component
      required:
        - app_name
        - owner
        - system
      properties:
        app_name:
          title: Repository Name
          type: string
          default: "sample-app"
        description:
          title: Description
          type: string
          description: Help others understand what this component is for
        owner:
          title: Owner
          type: string
          description: Owner of the component
          ui:field: OwnerPicker
          ui:options:
            catalogFilter:
              kind:
                - Group
        system:
          title: System
          type: string
          ui:field: EntityPicker
          ui:options:
            catalogFilter:
              kind:
                - System
    - title: Provide information about the git to used
      required:
        - git
        - git_host_url
        - git_owner_name
      properties:
        git:
          title: Git of Destination
          type: string
          description: This action will store the application source code on the selected Git server
          enum:
            - github
          enumNames:
            - GitHub
      dependencies:
        git:
          oneOf:
            - properties:
                git:
                  enum:
                    - github
                git_host_url:
                  title: Git Host URL
                  type: string
                  default: github.com
                  description: Specify the GitHub or GitLab host URL(e.g., github.com)
                git_owner_name:
                  title: GitHub Organization Name or User Name
                  type: string
                  description: Specify the GitHub Organization or User to register the repository
  steps:
    - id: app-template
      name: Generating the Application Source Code Component
      action: fetch:template
      input:
        url: ./app-skeleton
        values:
          git: ${{ parameters.git }}
          git_host_url: ${{ parameters.git_host_url }}
          git_owner_name: ${{ parameters.git_owner_name }}
          app_name: ${{ parameters.app_name }}
          owner: ${{ parameters.owner }}
          system: ${{ parameters.system }}
          description: ${{ parameters.description }}
        targetPath: ./tenant-app

    - id: publish-app-to-github
      if: ${{ parameters.git == "github" }}
      name: Publish App Repository to GitHub
      action: publish:github
      input:
        repoUrl: ${{ parameters.git_host_url }}?owner=${{ parameters.git_owner_name }}&repo=${{ parameters.app_name }}-app
        repoVisibility: public
        sourcePath: ./tenant-app
        defaultBranch: develop
        protectDefaultBranch: false

    - id: manifest-template
      name: Generating the K8s Manifest Component
      action: fetch:template
      input:
        url: ./manifest-skeleton
        copyWithoutTemplating:
          - .github/workflows/
        values:
          git: ${{ parameters.git }}
          git_host_url: ${{ parameters.git_host_url }}
          git_owner_name: ${{ parameters.git_owner_name }}
          app_name: ${{ parameters.app_name }}
          owner: ${{ parameters.owner }}
          system: ${{ parameters.system }}
          description: ${{ parameters.description }}
        targetPath: ./tenant-manifest

    - id: publish-manifest-to-github
      if: ${{ parameters.git == "github" }}
      name: Publish Manifest Repository to GitHub
      action: publish:github
      input:
        repoUrl: ${{ parameters.git_host_url }}?owner=${{ parameters.git_owner_name }}&repo=${{ parameters.app_name }}-manifest
        repoVisibility: public
        sourcePath: ./tenant-manifest
        defaultBranch: develop
        protectDefaultBranch: false

    - id: register-to-github
      if: ${{ parameters.git == "github" }}
      name: Registering the Catalog Info Component to GitHub
      action: catalog:register
      input:
        repoContentsUrl: ${{ steps['publish-app-to-github'].output.repoContentsUrl }}
        catalogInfoPath: "/catalog-info.yaml"

    - id: create-argocd-resources
      name: Create ArgoCD Resources
      action: argocd:create-resources
      input:
        appName: ${{ parameters.app_name }}-bootstrap
        argoInstance: main
        namespace: openshift-gitops
        repoUrl: https://${{ parameters.git_host_url }}/${{ parameters.git_owner_name }}/${{ parameters.app_name }}-manifest.git
        path: 'argocd/'

  output:
    links:
      - title: Open the Source Code Repository
        if: ${{ parameters.git == "github" }}
        url: ${{ steps['publish-app-to-github'].output.remoteUrl }}
      - title: Open the Catalog Info Component
        if: ${{ parameters.git == "github" }}
        icon: catalog
        entityRef: ${{ steps['register-to-github'].output.entityRef }}

```

</div></details>


この`template.yaml`をGitHubにPushしておきましょう。

# Golden Pathの更新
まだRHDHは新しくPushした`template.yaml`を認識できていないため、更新をかけます。

`Create...`画面から右上の`REGISTER EXISTING COMPONENT`を選択します。
![ScreenShot 184.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/1f2fa67c-5ca3-96bc-5484-b05bb19dd56b.png)

`Select URL`に`template.yaml`のURLを入力し`ANALYZE`を選択します。
![ScreenShot 185.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/d270a3ca-eb5b-2a27-e504-9302478c61ac.png)

するとCatalogをRefreshするか確認されるので、`REFRESH`を選択します。
![ScreenShot 187.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/a0acdaa3-bc27-6ed5-d27f-6074a7468ecd.png)

これでGolden Pathの更新が完了したので、実行してみましょう。
![ScreenShot 188.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/ee0a5c68-f206-9153-10b6-e4768055e484.png)

# Golden Pathの実行
では更新した`template.yaml`を使ってGolden Pathを実行します。
前回と同様に必要事項を入力して`Create`していきます。`App Name`はGitリポジトリ名に使われれるため、重複するとエラーになります。`sample-app2`など、前回とは別の値にしましょう。

![ScreenShot 189.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/3fcd037e-5083-87a2-7737-501cdaf2c2e2.png)

問題なければ正常に実行が完了します。
![ScreenShot 190.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/5cddd384-a5ed-fbbc-c93f-889832fdff0c.png)

# 環境の確認
まずは今回変更を加えたArgoCDをみていきましょう。
ブラウザからArgoCDにアクセスすると、以下のように３つの`Application`がデプロイされています。
![ScreenShot 211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/9ae98938-7c3b-22a1-f7cb-7d0a92a8c45f.png)
この中で`sample-app-2-bootstrap`を選択して見てみると、このApplicationは他の2つの`sample-app2-dev`と`sample-app2-build`のApplicationをデプロイしていることがわかります。
要は`App of Apps`の構成になっているということです。
このApplicationは、Golden Pathの実行で新たに作成された`sample-app2-manifest`リポジトリの`/argocd`ディレクトリ配下を参照しています。
![ScreenShot 212.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/869c1b7b-2761-82bf-7b21-76950123edd9.png)

次に`sample-app2-build`を確認すると、Tektonの`Task`や`Pipeline`、`EventListener`など、主にパイプラインの実行に必要なリソースがデプロイされています。
こちらは`sample-app2-manifest`リポジトリの`/kustomize/build`配下のリソースを参照しています。
真ん中でJobが実行されていますが、こちらは`sample-app2-app`リポジトリに対してwebhookの設定を行うコマンドを実行しています。
![ScreenShot 213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/8b426744-84b0-fce1-2caa-a5f02abc8624.png)

最後に`sample-app2-dev`を確認します。こちらはSync状況が`Degraded`になっていますが、現時点では問題ありません。まだイメージがビルドされていないため、PodのPullエラーが発生しています。
![ScreenShot 214.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/9abdcd2f-0bb6-ad76-c208-769c42afed8e.png)

次にOpenShift側を見てみましょう。
こちらではArgoCDの設定により自動的に`sample-app2-develop`Namespaceが作成されており、TektonのPipelineが準備されていることがわかります。
![ScreenShot 216.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/a4e751e9-c326-edf0-983a-35f07c10232c.png)

ではこの状態でアプリケーションのコード修正を行ってみましょう。
`sample-app2-app/site/public/index.html`を開き、`Edit this file`を選択します。
![ScreenShot 217.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/77d8b94a-5fdd-4aa7-c049-8d0ac37cede2.png)

適当に改行などを入れ、`Commit changes...`を選択します。
![ScreenShot 218.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/fed5b211-4abc-9aef-cb0b-c6f7d53a0cda.png)

するとソースコードの変更を検知し、WebhookによってOpenShift Pipelinerunが実行されます。
![ScreenShot 220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/259d0667-67cf-e66e-19ef-07fa48f34414.png)

設定がうまくいっていれば、無事にPipelineも成功します。
![ScreenShot 222.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/8ee31d80-8cb7-3200-088f-2c05200c72fc.png)

最後にArgoCDで、`sample-app2-dev`のリフレッシュを行うとアプリケーションのデプロイが完了します。
![ScreenShot 223.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/58e168b5-ae7d-58d7-7a84-1006cbf7160e.png)

アプリのRoute URLにアクセスしてみます。httpでのアクセスになります。
![ScreenShot 224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/30c05fc0-4020-67f9-86bd-3d1b658a1c49.png)

admin/adminでログインします。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/9a73c115-a48c-c86a-3370-beab8a87e450.png"  width=50%>

**おめでとうございます！アプリがデプロイできました！**
![ScreenShot 226.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/78856a9c-d466-6ac0-d066-b7488b653a39.png)

もちろん、RHDH上でも管理されています。
![ScreenShot 227.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419286/a83ecb97-a8d8-d330-0f5a-96d94655528e.png)

# おわりに
とても長い道のりでしたが、これで一連の流れを実現することができました。
今回は基本的なGolden Pathの実行でしたが、GitHub上のSkeletonテンプレートからリポジトリを作成し、その情報をもとにArgoCDで環境のデプロイまで行い、プリセットのCICDをいきなり使い始めることができるという、まさしく"ゴールデンパス"を開発者に提供することができました。

一方で、今回の取り組みによって、いかにRHDH上でGolden Pathの提供を整備することが難しいかもご理解いただけたかと思います。
* GitOpsだからSecretの管理は別途考えないといけない
* Pipelineに含めるテストやセキュリティスキャンはどうする？
* RHDH上から埋め込む値をK8s Manifestに反映できるようSkeletonリポジトリを構築しないといけない
* 連携設定やプラグインなど、RHDH上だけでも考えることが多い

とはいえこれを構築できれば、開発者は初めての開発でも"強くてニューゲーム"状態でスタートできるので、効果は絶大です。
まだまだBackstageも発展途上で、その成長に伴いRHDHもどんどん新しい機能が追加されていきますので、ぜひ定期的にチェックしてみていただければと思います。


今回テーマの記事はのこり1つです。最後の記事では、RHDH上で管理されている`Component`、こちらの画面をブラッシュアップし、より開発者によって有益な情報を表示する"ポータル"として機能させるための手順をお伝えします。