@@ -92,6 +92,7 @@ export function BuildManagementPage() {
|
||||
const [branch, setBranch] = useState('develop');
|
||||
const [commitSha, setCommitSha] = useState('');
|
||||
const [selectedJob, setSelectedJob] = useState<BuildJob | null>(null);
|
||||
const [confirmOpen, setConfirmOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [page, setPage] = useState(1);
|
||||
const [range, setRange] = useState<BuildRange>('week');
|
||||
@@ -199,6 +200,7 @@ export function BuildManagementPage() {
|
||||
const startBuild = async () => {
|
||||
if (!selectedComponent) return;
|
||||
try {
|
||||
setConfirmOpen(false);
|
||||
const result = await createBuildJob({ componentId: selectedComponent.id, branch, commitSha });
|
||||
toast({ type: 'success', message: '빌드 작업이 생성되었습니다.' });
|
||||
setSelectedJob(result.buildJob);
|
||||
@@ -300,7 +302,7 @@ export function BuildManagementPage() {
|
||||
<span className="text-muted-foreground">예상 결과물</span>
|
||||
<span className="truncate font-medium">{predicted}</span>
|
||||
</div>
|
||||
<Button className="mt-1 h-8 px-3 text-[13px]" onClick={startBuild} disabled={!selectedComponent || appsLoading || loading}>
|
||||
<Button className="mt-1 h-8 px-3 text-[13px]" onClick={() => setConfirmOpen(true)} disabled={!selectedComponent || appsLoading || loading}>
|
||||
<Play className="size-4" />
|
||||
빌드 실행
|
||||
</Button>
|
||||
@@ -441,6 +443,53 @@ export function BuildManagementPage() {
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
<Modal
|
||||
open={confirmOpen}
|
||||
title="빌드 실행 확인"
|
||||
onClose={() => {
|
||||
if (!loading) setConfirmOpen(false);
|
||||
}}
|
||||
footer={
|
||||
<>
|
||||
<Button variant="outline" disabled={loading} onClick={() => setConfirmOpen(false)}>취소</Button>
|
||||
<Button disabled={!selectedComponent || appsLoading || loading} onClick={startBuild}>
|
||||
<Play className="size-4" />
|
||||
실행
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div className="space-y-3 text-sm">
|
||||
<div className="rounded-md border border-border bg-muted/20 px-4 py-3">
|
||||
<p className="font-medium">{selectedComponent?.name ?? '-'} 구성요소 빌드를 실행합니다.</p>
|
||||
<p className="mt-1 text-xs leading-5 text-muted-foreground">
|
||||
실행 후 빌드 작업이 생성되고, 작업 목록에서 진행 상태와 로그를 확인할 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-2 rounded-md border border-border bg-background p-4">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">앱</span>
|
||||
<span className="truncate font-medium">{selectedApp?.name ?? '-'}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">저장소</span>
|
||||
<span className="truncate font-medium">{selectedComponent?.repository || '-'}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">브랜치</span>
|
||||
<span className="font-medium">{branch}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">커밋</span>
|
||||
<span className="font-mono text-xs font-medium">{commitSha.trim() || '브랜치 최신'}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-muted-foreground">빌드 대상</span>
|
||||
<span className="truncate font-medium">{selectedTarget}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<LoadingModal open={loadingVisible} />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -171,6 +171,7 @@ export function ReleaseManagementPage() {
|
||||
const [totalReleases, setTotalReleases] = useState(0);
|
||||
const [usedBuildIdValues, setUsedBuildIdValues] = useState<string[]>([]);
|
||||
const [usedReleaseValueValues, setUsedReleaseValueValues] = useState<string[]>([]);
|
||||
const hasActiveRelease = releases.some((release) => release.status === 'PENDING' || release.status === 'RUNNING');
|
||||
const loadingVisible = useMinimumLoading(loading);
|
||||
const usedValues = useMemo(() => new Set(usedReleaseValueValues), [usedReleaseValueValues]);
|
||||
const usedBuildIds = useMemo(() => new Set(usedBuildIdValues), [usedBuildIdValues]);
|
||||
@@ -226,6 +227,28 @@ export function ReleaseManagementPage() {
|
||||
void refresh();
|
||||
}, [selectedAppId, page, range, apps]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasActiveRelease) return;
|
||||
const timer = window.setInterval(() => {
|
||||
listReleasesPage({
|
||||
appKey: apps.find((app) => app.id === selectedAppId)?.key,
|
||||
page,
|
||||
limit: releasePageSize,
|
||||
since: releaseRangeSince(range)
|
||||
})
|
||||
.then((nextReleases) => {
|
||||
setReleases(nextReleases.releases);
|
||||
setTotalReleases(nextReleases.total);
|
||||
setUsedBuildIdValues(nextReleases.usedBuildIds ?? []);
|
||||
setUsedReleaseValueValues(nextReleases.usedValues ?? []);
|
||||
})
|
||||
.catch((error: Error) => {
|
||||
toast({ type: 'error', message: `릴리즈 목록 갱신 실패: ${error.message}` });
|
||||
});
|
||||
}, 2000);
|
||||
return () => window.clearInterval(timer);
|
||||
}, [hasActiveRelease, apps, selectedAppId, page, range, toast]);
|
||||
|
||||
useEffect(() => {
|
||||
setPage(1);
|
||||
}, [selectedAppId, range]);
|
||||
|
||||
@@ -97,7 +97,7 @@ export function RepositoryManagementPage() {
|
||||
const [isCreateRepoOpen, setIsCreateRepoOpen] = useState(false);
|
||||
const [repoName, setRepoName] = useState('');
|
||||
const [repoDescription, setRepoDescription] = useState('');
|
||||
const [repoPrivate, setRepoPrivate] = useState(true);
|
||||
const [repoPrivate, setRepoPrivate] = useState(false);
|
||||
const [createDevelopBranch, setCreateDevelopBranch] = useState(true);
|
||||
const [createReleaseBranch, setCreateReleaseBranch] = useState(true);
|
||||
const [repoCreateStatus, setRepoCreateStatus] = useState<'idle' | 'saving' | 'error'>('idle');
|
||||
@@ -165,7 +165,7 @@ export function RepositoryManagementPage() {
|
||||
.then(() => {
|
||||
setRepoName('');
|
||||
setRepoDescription('');
|
||||
setRepoPrivate(true);
|
||||
setRepoPrivate(false);
|
||||
setCreateDevelopBranch(true);
|
||||
setCreateReleaseBranch(true);
|
||||
setRepoCreateStatus('idle');
|
||||
|
||||
@@ -299,7 +299,7 @@ export function SourceManagementPage() {
|
||||
const [sources, setSources] = useState<SourceComponent[]>([]);
|
||||
const [sourcesLoading, setSourcesLoading] = useState(true);
|
||||
const [selectedSourceId, setSelectedSourceId] = useState('');
|
||||
const [selectedBranch, setSelectedBranch] = useState('release');
|
||||
const [selectedBranch, setSelectedBranch] = useState('develop');
|
||||
const [commitRange, setCommitRange] = useState<CommitRange>('week');
|
||||
const [commitPage, setCommitPage] = useState(1);
|
||||
const [commits, setCommits] = useState<GiteaCommit[]>([]);
|
||||
@@ -319,10 +319,10 @@ export function SourceManagementPage() {
|
||||
);
|
||||
const selectedSource = filteredSources.find((source) => source.id === selectedSourceId) ?? filteredSources[0] ?? null;
|
||||
const repository = splitRepository(selectedSource?.repository);
|
||||
const branch = selectedBranch || 'release';
|
||||
const branch = selectedBranch || 'develop';
|
||||
const latestBranchSha = commits.length > 0 ? commits[0]?.sha ?? '' : '';
|
||||
const branchOptions = useMemo(
|
||||
() => [...new Set(['release', 'develop', 'main', selectedSource?.branch].filter((item): item is string => Boolean(item)))],
|
||||
() => [...new Set(['develop', 'release', 'main', selectedSource?.branch].filter((item): item is string => Boolean(item)))],
|
||||
[selectedSource?.branch]
|
||||
);
|
||||
const totalCommitPages = totalCommits === null ? null : Math.max(1, Math.ceil(totalCommits / commitPageSize));
|
||||
@@ -469,7 +469,7 @@ export function SourceManagementPage() {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="min-w-0 md:col-span-2">
|
||||
<p className="text-xs text-muted-foreground">SHA1</p>
|
||||
<div className="mt-2 rounded-md border border-border bg-background px-3 py-2">
|
||||
<p className="truncate font-mono text-sm font-medium" title={latestBranchSha || '-'}>
|
||||
|
||||
Reference in New Issue
Block a user