feat(traQ): inject config during deployment#1315
Conversation
Diff@@ (root level) @@
# v1/ConfigMap/preview-traq/preview-traq-config
! + one document added:
+ ---
+ apiVersion: v1
+ data:
+ config.json: |
+ {
+ "$schema": "https://raw.githubusercontent.com/traPtitech/traQ_S-UI/refs/heads/master/config.schema.json",
+ "firebase": {
+ "apiKey": "AIzaSyDee_VkrRtByJCrCZAX3nTSDPl8AaHlWfY",
+ "appId": "1:993645413001:web:b253ea3776d6cf85163c58",
+ "projectId": "traq-r",
+ "messagingSenderId": "993645413001",
+ "vapidKey": "BPHegiDotHG7TlKhoW1qvwUYjOQj1C7RgKjvw3etUJZ_4x3LWUtFVXtRANWwckJX4G2w3CVj4zwi5QNThg7DZH4"
+ },
+ "enableQall": true,
+ "enableSearch": true,
+ "services": [
+ {
+ "label": "Portal",
+ "iconPath": "portal.svg",
+ "appLink": "https://portal.trap.jp/"
+ },
+ {
+ "label": "Official Website",
+ "iconPath": "traP.svg",
+ "appLink": "https://trap.jp/"
+ },
+ {
+ "label": "Wiki",
+ "iconPath": "crowi.svg",
+ "appLink": "https://wiki.trap.jp/"
+ },
+ {
+ "label": "Blog Admin",
+ "iconPath": "ghost.svg",
+ "appLink": "https://blog-admin.trap.jp/"
+ },
+ {
+ "label": "Drive",
+ "iconPath": "nextcloud.svg",
+ "appLink": "https://drive.trap.jp/"
+ },
+ {
+ "label": "Gitea",
+ "iconPath": "gitea.svg",
+ "appLink": "https://git.trap.jp/"
+ },
+ {
+ "label": "NeoShowcase",
+ "iconPath": "neoshowcase.svg",
+ "appLink": "https://ns.trap.jp/"
+ },
+ {
+ "label": "HackMD",
+ "iconPath": "hackmd.svg",
+ "appLink": "https://md.trap.jp/"
+ },
+ {
+ "label": "anke-to",
+ "iconPath": "anke-to.svg",
+ "appLink": "https://anke-to.trap.jp/"
+ },
+ {
+ "label": "booQ",
+ "iconPath": "booq.svg",
+ "appLink": "https://booq.trap.jp/"
+ },
+ {
+ "label": "knoQ",
+ "iconPath": "knoq.svg",
+ "appLink": "https://knoq.trap.jp/"
+ },
+ {
+ "label": "BOT Console",
+ "iconPath": "bot-console.svg",
+ "appLink": "https://bot-console.trap.jp/"
+ },
+ {
+ "label": "Jomon",
+ "iconPath": "jomon.svg",
+ "appLink": "https://jomon.trap.jp/"
+ },
+ {
+ "label": "traPortfolio",
+ "iconPath": "traPortfolio.svg",
+ "appLink": "https://portfolio.trap.jp/"
+ },
+ {
+ "label": "tpf-admin",
+ "iconPath": "traPortfolio-admin.svg",
+ "appLink": "https://portfolio-admin.trap.jp/"
+ },
+ {
+ "label": "rucQ",
+ "iconPath": "rucq.svg",
+ "appLink": "https://rucq.trap.jp/"
+ },
+ {
+ "label": "traP Collection",
+ "iconPath": "traPCollection.svg",
+ "appLink": "https://collection.trap.jp/"
+ }
+ ],
+ "ogpIgnoreHostNames": [
+ "wiki.trap.jp",
+ "git.trap.jp",
+ "md.trap.jp",
+ "drive.trap.jp",
+ "anke-to.trap.jp",
+ "booq.trap.jp",
+ "knoq.trap.jp",
+ "wiki.trapti.tech",
+ "git.trapti.tech",
+ "md.trapti.tech",
+ "drive.trapti.tech",
+ "jomon.trap.jp",
+ "ns.trap.jp",
+ "portfolio-admin.trap.jp",
+ "rucq.trap.jp"
+ ],
+ "wikiPageOrigin": "https://wiki.trap.jp",
+ "blogPagePrefix": "https://trap.jp/author/",
+ "auth": {
+ "resetLink": "https://portal.trap.jp/reset-password",
+ "changeLink": "https://portal.trap.jp/me/change-password",
+ "changeName": "traPortal"
+ },
+ "isRootChannelSelectableAsParentChannel": false,
+ "tooLargeFileMessage": "大きい%sの共有にはDriveを使用してください",
+ "showWidgetCopyButton": true,
+ "inlineReplyDisableChannels": [
+ "#general",
+ "#general/schedule",
+ "#general/meeting",
+ "#random",
+ "#random/wasure",
+ "#services"
+ ],
+ "iosPwaInfoLink": "https://wiki.trap.jp/SysAd/docs/traQ-S/PWA"
+ }
+
+ kind: ConfigMap
+ metadata:
+ name: preview-traq-config
+ namespace: preview-traq
@@ spec.template.spec @@
# apps/v1/Deployment/traq-dev/traq-frontend
! + two map entries added:
+ initContainers:
+ - name: convert-config
+ image: "busybox:1.36.1"
+ args:
+ - |
+ echo ";(() => { self.traQConfig = $(cat /config-in/config.json) })()" > /app/override/config.js
+
+ command:
+ - sh
+ - "-c"
+ volumeMounts:
+ - name: config-json
+ mountPath: /config-in
+ - name: config-js
+ mountPath: /app/override
+ volumes:
+ - name: config-json
+ configMap:
+ name: traq-frontend-config-6m99b9hg6f
+ - name: config-js
+ emptyDir: {}
@@ spec.template.spec.containers.traq-frontend @@
# apps/v1/Deployment/traq-dev/traq-frontend
! + one map entry added:
+ volumeMounts:
+ - name: config-js
+ mountPath: /app/override/config.js
+ subPath: config.js
@@ (root level) @@
# v1/ConfigMap/traq-dev/traq-frontend-config-6m99b9hg6f
! + one document added:
+ ---
+ apiVersion: v1
+ data:
+ config.json: |
+ {
+ "$schema": "https://raw.githubusercontent.com/traPtitech/traQ_S-UI/refs/heads/master/config.schema.json",
+ "firebase": {
+ "apiKey": "AIzaSyDee_VkrRtByJCrCZAX3nTSDPl8AaHlWfY",
+ "appId": "1:993645413001:web:b253ea3776d6cf85163c58",
+ "projectId": "traq-r",
+ "messagingSenderId": "993645413001",
+ "vapidKey": "BPHegiDotHG7TlKhoW1qvwUYjOQj1C7RgKjvw3etUJZ_4x3LWUtFVXtRANWwckJX4G2w3CVj4zwi5QNThg7DZH4"
+ },
+ "enableQall": true,
+ "enableSearch": true,
+ "services": [
+ {
+ "label": "Portal",
+ "iconPath": "portal.svg",
+ "appLink": "https://portal.trap.jp/"
+ },
+ {
+ "label": "Official Website",
+ "iconPath": "traP.svg",
+ "appLink": "https://trap.jp/"
+ },
+ {
+ "label": "Wiki",
+ "iconPath": "crowi.svg",
+ "appLink": "https://wiki.trap.jp/"
+ },
+ {
+ "label": "Blog Admin",
+ "iconPath": "ghost.svg",
+ "appLink": "https://blog-admin.trap.jp/"
+ },
+ {
+ "label": "Drive",
+ "iconPath": "nextcloud.svg",
+ "appLink": "https://drive.trap.jp/"
+ },
+ {
+ "label": "Gitea",
+ "iconPath": "gitea.svg",
+ "appLink": "https://git.trap.jp/"
+ },
+ {
+ "label": "NeoShowcase",
+ "iconPath": "neoshowcase.svg",
+ "appLink": "https://ns.trap.jp/"
+ },
+ {
+ "label": "HackMD",
+ "iconPath": "hackmd.svg",
+ "appLink": "https://md.trap.jp/"
+ },
+ {
+ "label": "anke-to",
+ "iconPath": "anke-to.svg",
+ "appLink": "https://anke-to.trap.jp/"
+ },
+ {
+ "label": "booQ",
+ "iconPath": "booq.svg",
+ "appLink": "https://booq.trap.jp/"
+ },
+ {
+ "label": "knoQ",
+ "iconPath": "knoq.svg",
+ "appLink": "https://knoq.trap.jp/"
+ },
+ {
+ "label": "BOT Console",
+ "iconPath": "bot-console.svg",
+ "appLink": "https://bot-console.trap.jp/"
+ },
+ {
+ "label": "Jomon",
+ "iconPath": "jomon.svg",
+ "appLink": "https://jomon.trap.jp/"
+ },
+ {
+ "label": "traPortfolio",
+ "iconPath": "traPortfolio.svg",
+ "appLink": "https://portfolio.trap.jp/"
+ },
+ {
+ "label": "tpf-admin",
+ "iconPath": "traPortfolio-admin.svg",
+ "appLink": "https://portfolio-admin.trap.jp/"
+ },
+ {
+ "label": "rucQ",
+ "iconPath": "rucq.svg",
+ "appLink": "https://rucq.trap.jp/"
+ },
+ {
+ "label": "traP Collection",
+ "iconPath": "traPCollection.svg",
+ "appLink": "https://collection.trap.jp/"
+ }
+ ],
+ "ogpIgnoreHostNames": [
+ "wiki.trap.jp",
+ "git.trap.jp",
+ "md.trap.jp",
+ "drive.trap.jp",
+ "anke-to.trap.jp",
+ "booq.trap.jp",
+ "knoq.trap.jp",
+ "wiki.trapti.tech",
+ "git.trapti.tech",
+ "md.trapti.tech",
+ "drive.trapti.tech",
+ "jomon.trap.jp",
+ "ns.trap.jp",
+ "portfolio-admin.trap.jp",
+ "rucq.trap.jp"
+ ],
+ "wikiPageOrigin": "https://wiki.trap.jp",
+ "blogPagePrefix": "https://trap.jp/author/",
+ "auth": {
+ "resetLink": "https://portal.trap.jp/reset-password",
+ "changeLink": "https://portal.trap.jp/me/change-password",
+ "changeName": "traPortal"
+ },
+ "isRootChannelSelectableAsParentChannel": false,
+ "tooLargeFileMessage": "大きい%sの共有にはDriveを使用してください",
+ "showWidgetCopyButton": true,
+ "inlineReplyDisableChannels": [
+ "#general",
+ "#general/schedule",
+ "#general/meeting",
+ "#random",
+ "#random/wasure",
+ "#services"
+ ],
+ "iosPwaInfoLink": "https://wiki.trap.jp/SysAd/docs/traQ-S/PWA"
+ }
+
+ kind: ConfigMap
+ metadata:
+ name: traq-frontend-config-6m99b9hg6f
+ namespace: traq-dev
@@ spec.template.spec @@
# apps/v1/Deployment/traq/traq-frontend
! + two map entries added:
+ initContainers:
+ - name: convert-config
+ image: "busybox:1.36.1"
+ args:
+ - |
+ echo ";(() => { self.traQConfig = $(cat /config-in/config.json) })()" > /app/override/config.js
+
+ command:
+ - sh
+ - "-c"
+ volumeMounts:
+ - name: config-json
+ mountPath: /config-in
+ - name: config-js
+ mountPath: /app/override
+ volumes:
+ - name: config-json
+ configMap:
+ name: traq-frontend-config-6m99b9hg6f
+ - name: config-js
+ emptyDir: {}
@@ spec.template.spec.containers.traq-frontend @@
# apps/v1/Deployment/traq/traq-frontend
! + one map entry added:
+ volumeMounts:
+ - name: config-js
+ mountPath: /app/override/config.js
+ subPath: config.js
@@ (root level) @@
# v1/ConfigMap/traq/traq-frontend-config-6m99b9hg6f
! + one document added:
+ ---
+ apiVersion: v1
+ data:
+ config.json: |
+ {
+ "$schema": "https://raw.githubusercontent.com/traPtitech/traQ_S-UI/refs/heads/master/config.schema.json",
+ "firebase": {
+ "apiKey": "AIzaSyDee_VkrRtByJCrCZAX3nTSDPl8AaHlWfY",
+ "appId": "1:993645413001:web:b253ea3776d6cf85163c58",
+ "projectId": "traq-r",
+ "messagingSenderId": "993645413001",
+ "vapidKey": "BPHegiDotHG7TlKhoW1qvwUYjOQj1C7RgKjvw3etUJZ_4x3LWUtFVXtRANWwckJX4G2w3CVj4zwi5QNThg7DZH4"
+ },
+ "enableQall": true,
+ "enableSearch": true,
+ "services": [
+ {
+ "label": "Portal",
+ "iconPath": "portal.svg",
+ "appLink": "https://portal.trap.jp/"
+ },
+ {
+ "label": "Official Website",
+ "iconPath": "traP.svg",
+ "appLink": "https://trap.jp/"
+ },
+ {
+ "label": "Wiki",
+ "iconPath": "crowi.svg",
+ "appLink": "https://wiki.trap.jp/"
+ },
+ {
+ "label": "Blog Admin",
+ "iconPath": "ghost.svg",
+ "appLink": "https://blog-admin.trap.jp/"
+ },
+ {
+ "label": "Drive",
+ "iconPath": "nextcloud.svg",
+ "appLink": "https://drive.trap.jp/"
+ },
+ {
+ "label": "Gitea",
+ "iconPath": "gitea.svg",
+ "appLink": "https://git.trap.jp/"
+ },
+ {
+ "label": "NeoShowcase",
+ "iconPath": "neoshowcase.svg",
+ "appLink": "https://ns.trap.jp/"
+ },
+ {
+ "label": "HackMD",
+ "iconPath": "hackmd.svg",
+ "appLink": "https://md.trap.jp/"
+ },
+ {
+ "label": "anke-to",
+ "iconPath": "anke-to.svg",
+ "appLink": "https://anke-to.trap.jp/"
+ },
+ {
+ "label": "booQ",
+ "iconPath": "booq.svg",
+ "appLink": "https://booq.trap.jp/"
+ },
+ {
+ "label": "knoQ",
+ "iconPath": "knoq.svg",
+ "appLink": "https://knoq.trap.jp/"
+ },
+ {
+ "label": "BOT Console",
+ "iconPath": "bot-console.svg",
+ "appLink": "https://bot-console.trap.jp/"
+ },
+ {
+ "label": "Jomon",
+ "iconPath": "jomon.svg",
+ "appLink": "https://jomon.trap.jp/"
+ },
+ {
+ "label": "traPortfolio",
+ "iconPath": "traPortfolio.svg",
+ "appLink": "https://portfolio.trap.jp/"
+ },
+ {
+ "label": "tpf-admin",
+ "iconPath": "traPortfolio-admin.svg",
+ "appLink": "https://portfolio-admin.trap.jp/"
+ },
+ {
+ "label": "rucQ",
+ "iconPath": "rucq.svg",
+ "appLink": "https://rucq.trap.jp/"
+ },
+ {
+ "label": "traP Collection",
+ "iconPath": "traPCollection.svg",
+ "appLink": "https://collection.trap.jp/"
+ }
+ ],
+ "ogpIgnoreHostNames": [
+ "wiki.trap.jp",
+ "git.trap.jp",
+ "md.trap.jp",
+ "drive.trap.jp",
+ "anke-to.trap.jp",
+ "booq.trap.jp",
+ "knoq.trap.jp",
+ "wiki.trapti.tech",
+ "git.trapti.tech",
+ "md.trapti.tech",
+ "drive.trapti.tech",
+ "jomon.trap.jp",
+ "ns.trap.jp",
+ "portfolio-admin.trap.jp",
+ "rucq.trap.jp"
+ ],
+ "wikiPageOrigin": "https://wiki.trap.jp",
+ "blogPagePrefix": "https://trap.jp/author/",
+ "auth": {
+ "resetLink": "https://portal.trap.jp/reset-password",
+ "changeLink": "https://portal.trap.jp/me/change-password",
+ "changeName": "traPortal"
+ },
+ "isRootChannelSelectableAsParentChannel": false,
+ "tooLargeFileMessage": "大きい%sの共有にはDriveを使用してください",
+ "showWidgetCopyButton": true,
+ "inlineReplyDisableChannels": [
+ "#general",
+ "#general/schedule",
+ "#general/meeting",
+ "#random",
+ "#random/wasure",
+ "#services"
+ ],
+ "iosPwaInfoLink": "https://wiki.trap.jp/SysAd/docs/traQ-S/PWA"
+ }
+
+ kind: ConfigMap
+ metadata:
+ name: traq-frontend-config-6m99b9hg6f
+ namespace: traq
|
d36066b to
b5af0ff
Compare
There was a problem hiding this comment.
Pull request overview
This pull request implements config injection during deployment for the traQ frontend, enabling runtime configuration through Kubernetes ConfigMaps instead of build-time configuration. This follows the referenced issues about improving the deployment configuration pattern.
Key Changes:
- Introduces an initContainer that converts JSON config to JavaScript at deployment time
- Adds ConfigMap generation for both production (traq) and preview environments
- Implements volume mounting strategy to inject the converted config into the frontend container
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| traq/frontend/kustomization.yaml | Adds ConfigMap generator for traq-frontend-config from config.json |
| traq/frontend/deployment.yaml | Adds initContainer to convert JSON config to JS and volume mounts to inject it into the frontend |
| traq/frontend/config.json | New configuration file containing Firebase credentials, services list, and UI settings |
| preview-traq/kustomization.yaml | Adds ConfigMap generator for preview environment using the same config.json and deployment patch |
| preview-traq/deployment-patch.yaml | Patch to add the same config conversion initContainer and volume mounts for preview deployments |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b5af0ff to
d67e826
Compare
d67e826 to
a2d98a7
Compare
| patches: | ||
| - path: deployment-patch.yaml | ||
| target: | ||
| kind: Deployment | ||
| name: preview-traq-.* | ||
| namespace: preview-traq |
There was a problem hiding this comment.
このpatchはkustomize build実行時に行われるため、preview-uiが生成するArgoCD Applicationにおいては行われないと思います。
これをやる場合、.common/preview-ui-templateでDeploymentのinitContainersをHelm Valueで指定できるようにするとできそうです。
| configMapGenerator: | ||
| - name: traq-frontend-config | ||
| files: | ||
| - config.json |
There was a problem hiding this comment.
良さそうですが、先にtraq-devでテストして欲しいです🙏
config.jsonからconfig.jsを生成してapp/overried/config.jsに差し込みたいref:
config.jsをビルドから除外する traQ_S-UI#5005