add build env and path ingress controls

This commit is contained in:
2026-07-02 15:43:29 +09:00
parent 25dd90076f
commit 2b7f504007
4 changed files with 225 additions and 6 deletions
+16 -2
View File
@@ -92,6 +92,7 @@ export function RuntimeConfigPage() {
const [ingressHost, setIngressHost] = useState('');
const [ingressPath, setIngressPath] = useState('/');
const [ingressPort, setIngressPort] = useState('');
const [ingressStripPrefix, setIngressStripPrefix] = useState(false);
const selectedApp = apps.find((app) => app.id === appId);
const selectedProfile = profiles.find((profile) => profile.id === profileId);
@@ -237,11 +238,13 @@ export function RuntimeConfigPage() {
host: ingressHost.trim(),
path: ingressPath.trim() || '/',
servicePort: Number(ingressPort),
stripPrefix: ingressStripPrefix,
tlsEnabled: false
})
.then(() => {
setIngressHost('');
setIngressPath('/');
setIngressStripPrefix(false);
refreshProfiles(appId, selectedProfile.id);
})
.catch((createError: Error) => setError(createError.message));
@@ -529,19 +532,20 @@ export function RuntimeConfigPage() {
<span className="text-xs text-muted-foreground">총 {ingressRules.length}개</span>
</div>
<div className="max-h-[320px] overflow-x-auto overflow-y-auto">
<table className="w-full min-w-[820px] text-left text-sm">
<table className="w-full min-w-[940px] text-left text-sm">
<thead className="sticky top-0 z-10 border-b border-border bg-card text-xs text-muted-foreground">
<tr>
<th className="px-5 py-3 font-medium">구성요소</th>
<th className="px-5 py-3 font-medium">도메인</th>
<th className="px-5 py-3 font-medium">Path</th>
<th className="px-5 py-3 font-medium">포트</th>
<th className="px-5 py-3 font-medium">Prefix</th>
<th className="w-16 px-5 py-3 text-right font-medium">관리</th>
</tr>
</thead>
<tbody className="divide-y divide-border">
{ingressRules.length === 0 ? (
<tr><td colSpan={5} className="px-5 py-14 text-center text-muted-foreground">등록된 접속 설정이 없습니다.</td></tr>
<tr><td colSpan={6} className="px-5 py-14 text-center text-muted-foreground">등록된 접속 설정이 없습니다.</td></tr>
) : null}
{ingressRules.map((rule) => (
<tr key={rule.id} className="hover:bg-muted/20">
@@ -554,6 +558,7 @@ export function RuntimeConfigPage() {
<td className="px-5 py-3 text-foreground">{rule.host}</td>
<td className="px-5 py-3 text-muted-foreground">{rule.path}</td>
<td className="px-5 py-3 text-muted-foreground">{rule.servicePort}</td>
<td className="px-5 py-3 text-muted-foreground">{rule.stripPrefix ? '제거' : '유지'}</td>
<td className="px-5 py-3 text-right">
<Button variant="ghost" className="h-8 w-8 p-0 text-rose-300 hover:text-rose-200" title="삭제" aria-label={`${rule.host} 삭제`} onClick={() => removeIngressRule(rule.id)}>
<Trash2 className="size-4" />
@@ -600,6 +605,15 @@ export function RuntimeConfigPage() {
<input type="number" min="1" className="mt-2 h-9 w-full rounded-md border border-input bg-background px-3 text-sm text-foreground outline-none focus:ring-2 focus:ring-ring" value={ingressPort} onChange={(event) => setIngressPort(event.target.value)} placeholder="80" />
</label>
</div>
<label className="flex items-center gap-2 rounded-md border border-border bg-muted/10 px-3 py-2 text-xs font-medium text-muted-foreground">
<input
type="checkbox"
className="size-4 accent-primary"
checked={ingressStripPrefix}
onChange={(event) => setIngressStripPrefix(event.target.checked)}
/>
Path prefix 제거
</label>
<Button className="h-9 w-full text-[13px]" onClick={addIngressRule} disabled={!selectedProfile || !ingressComponentId || !ingressHost.trim() || !ingressPort.trim()}>
<Plus className="size-4" />
추가
+1 -1
View File
@@ -30,7 +30,7 @@ export function createRuntimeVariable(
export function createRuntimeIngressRule(
profileId: string,
input: { componentId: string; host: string; path?: string; servicePort: number; tlsEnabled?: boolean; tlsSecretName?: string }
input: { componentId: string; host: string; path?: string; servicePort: number; stripPrefix?: boolean; tlsEnabled?: boolean; tlsSecretName?: string }
) {
return apiRequest(`/apps/runtime-profiles/${profileId}/ingress-rules`, {
method: 'POST',