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",
+ "defaultChannelId": [
+ "04ad2c18-fdcb-4c43-beef-82e8ba26ac98", // #general of q.trap.jp
+ "83afc6cc-737d-4868-9a2f-aeb7c199260e" // #general of q-dev.trapti.tech
+ ],
+ "fallbackChannelPath": "general"
+ }
+
+ kind: ConfigMap
+ metadata:
+ name: preview-traq-config
+ namespace: preview-traq
@@ spec.template.spec @@
# apps/v1/Deployment/traq-dev/traq-frontend
! + one map entry added:
+ volumes:
+ - name: config-json
+ configMap:
+ name: traq-frontend-config-dt8g76ft5c
@@ spec.template.spec.containers.traq-frontend @@
# apps/v1/Deployment/traq-dev/traq-frontend
! + one map entry added:
+ volumeMounts:
+ - name: config-json
+ mountPath: /app/override/config.json
+ subPath: config.jsonc
@@ (root level) @@
# v1/ConfigMap/traq-dev/traq-frontend-config-dt8g76ft5c
! + one document added:
+ ---
+ apiVersion: v1
+ data:
+ config.jsonc: |
+ {
+ "$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",
+ "defaultChannelId": [
+ "04ad2c18-fdcb-4c43-beef-82e8ba26ac98", // #general of q.trap.jp
+ "83afc6cc-737d-4868-9a2f-aeb7c199260e" // #general of q-dev.trapti.tech
+ ],
+ "fallbackChannelPath": "general"
+ }
+
+ kind: ConfigMap
+ metadata:
+ name: traq-frontend-config-dt8g76ft5c
+ namespace: traq-dev
@@ spec.template.spec @@
# apps/v1/Deployment/traq/traq-frontend
! + one map entry added:
+ volumes:
+ - name: config-json
+ configMap:
+ name: traq-frontend-config
@@ spec.template.spec.containers.traq-frontend @@
# apps/v1/Deployment/traq/traq-frontend
! + one map entry added:
+ volumeMounts:
+ - name: config-json
+ mountPath: /app/override/config.json
+ subPath: config.jsonc
|
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でテストして欲しいです🙏
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughConfigMapベースのフロントエンド設定導入と、それをマウントするためのKustomize生成・Helmテンプレート条件付きvolumeMount/volumes追加。新規設定ファイル Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
.common/preview-ui-template/templates/dashboard-deployment.yaml (1)
30-37:⚠️ Potential issue | 🟠 Majorpreview 経路では PR 目的の
config.js注入がまだ実現できていません。ここで追加しているのは ConfigMap の mount だけで、
traq/frontend/deployment.yamlに入ったconvert-config+emptyDirによるconfig.jsonc -> config.js変換が preview 側にはありません。これだと preview だけ runtime config の適用経路が別になるので、Helm Values からinitContainersも渡せるようにして同じ変換フローを通す必要があります。🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.common/preview-ui-template/templates/dashboard-deployment.yaml around lines 30 - 37, The preview deployment only mounts the ConfigMap but omits the init-container conversion flow (convert-config + emptyDir) used in traq/frontend/deployment.yaml, so add support to pass initContainers from Helm Values into the preview template and wire the same conversion flow: update the template to include .Values.containers.initContainers (or a dedicated .Values.initContainers) so the initContainer named convert-config and its emptyDir volume are rendered into the preview pod spec, ensure the emptyDir volume name used by convert-config matches the volumeMount in the main container (same volume name as in volumes/volumeMounts), and keep existing volumeMounts/volumes logic but include the initContainers block before containers so preview follows the identical config.jsonc -> config.js conversion path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@preview-traq/kustomization.yaml`:
- Around line 7-8: kustomization.yaml currently references a non-existent file
via the files entry (“config.json=../traq/frontend/config.json”); update that
reference to point to the actual file added in this PR (e.g. replace
../traq/frontend/config.json with ../traq/frontend/config.jsonc or the correct
existing path) so kustomize build can find the file; verify the files: entry in
kustomization.yaml matches the real filename and commit the change.
In `@traq/frontend/deployment.yaml`:
- Around line 24-29: The convert-config input name and file path are
inconsistent with the generator's ConfigMap key: update the converter and
volume/ConfigMap usage so both read the same filename (change the read path in
the config.js generation from /config-in/config.json to /config-in/config.jsonc
or rename the generator output key to config.json); ensure the echo line that
writes to /app/override/config.js, the volumeMount name (config-json) and the
source key produced by traq-dev/frontend/kustomization.yaml (config.jsonc) all
match the same key name so config.js is generated from the correct source.
---
Duplicate comments:
In @.common/preview-ui-template/templates/dashboard-deployment.yaml:
- Around line 30-37: The preview deployment only mounts the ConfigMap but omits
the init-container conversion flow (convert-config + emptyDir) used in
traq/frontend/deployment.yaml, so add support to pass initContainers from Helm
Values into the preview template and wire the same conversion flow: update the
template to include .Values.containers.initContainers (or a dedicated
.Values.initContainers) so the initContainer named convert-config and its
emptyDir volume are rendered into the preview pod spec, ensure the emptyDir
volume name used by convert-config matches the volumeMount in the main container
(same volume name as in volumes/volumeMounts), and keep existing
volumeMounts/volumes logic but include the initContainers block before
containers so preview follows the identical config.jsonc -> config.js conversion
path.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0e389eac-0102-4215-bad9-ee33eac93714
📒 Files selected for processing (7)
.common/preview-ui-template/templates/dashboard-deployment.yamlpreview-traq/kustomization.yamlpreview-traq/values.yamltraq-dev/frontend/deployment-patch.yamltraq-dev/frontend/kustomization.yamltraq/frontend/config.jsonctraq/frontend/deployment.yaml
| - name: preview-traq-config | ||
| namespace: preview-traq | ||
| files: | ||
| - config.json=../traq/frontend/config.jsonc |
There was a problem hiding this comment.
ここファイル名が合ってなさそうです
| - config.json=../traq/frontend/config.jsonc | |
| - config.jsonc=../traq/frontend/config.jsonc |
| configMapGenerator: | ||
| - name: traq-frontend-config | ||
| files: | ||
| - ../../traq/frontend/config.jsonc |
There was a problem hiding this comment.
これpreview-traqと書き方が違うのって理由ありますか?
あと、本番環境の方に無さそうな気がします
config.jsonからconfig.jsを生成してapp/overried/config.jsに差し込みたいref:
Summary by CodeRabbit