desktop 다운로드 기능 수정

This commit is contained in:
Macbook
2026-06-14 10:38:45 +09:00
parent 407e746822
commit eb9e6ec4e9
3 changed files with 82 additions and 18 deletions
@@ -78,25 +78,35 @@ public class DesktopAppBuildService {
if (!jenkinsEnabled) {
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "Jenkins 연동이 비활성화되어 있습니다.");
}
try {
syncGitLatest();
syncGitLatest();
DesktopAppBuildStatusDto current = fetchLastBuildStatus();
if (current.isBuilding()) {
return DesktopAppBuildTriggerDto.builder()
.accepted(false)
.buildNumber(current.getBuildNumber())
.message("이미 빌드가 진행 중입니다 (#" + current.getBuildNumber() + ").")
.build();
}
DesktopAppBuildStatusDto current = fetchLastBuildStatus();
if (current.isBuilding()) {
triggerJenkinsBuild();
DesktopAppBuildStatusDto after = fetchLastBuildStatus();
return DesktopAppBuildTriggerDto.builder()
.accepted(false)
.buildNumber(current.getBuildNumber())
.message("이미 빌드가 진행 중입니다 (#" + current.getBuildNumber() + ").")
.accepted(true)
.buildNumber(after.getBuildNumber())
.message("Jenkins에서 macOS·Windows 데스크톱 앱 빌드를 시작했습니다. 완료 후 설치 파일이 자동으로 반영됩니다.")
.build();
} catch (ResponseStatusException e) {
throw e;
} catch (WebClientResponseException e) {
log.warn("[desktop-build] Jenkins HTTP {}: {}", e.getStatusCode(), e.getResponseBodyAsString());
throw new ResponseStatusException(HttpStatus.BAD_GATEWAY, jenkinsHttpError(e));
} catch (Exception e) {
log.warn("[desktop-build] trigger failed: {}", e.getMessage());
throw new ResponseStatusException(HttpStatus.BAD_GATEWAY,
"Jenkins 빌드 요청 실패: " + rootMessage(e));
}
triggerJenkinsBuild();
DesktopAppBuildStatusDto after = fetchLastBuildStatus();
return DesktopAppBuildTriggerDto.builder()
.accepted(true)
.buildNumber(after.getBuildNumber())
.message("Jenkins에서 macOS·Windows 데스크톱 앱 빌드를 시작했습니다. 완료 후 설치 파일이 자동으로 반영됩니다.")
.build();
}
private DesktopAppBuildStatusDto fetchLastBuildStatus() {
@@ -156,16 +166,28 @@ public class DesktopAppBuildService {
private void triggerJenkinsBuild() {
WebClient client = jenkinsClient();
String buildUrl = jobApiPath() + "/build";
Map<String, String> crumb = fetchCrumbOptional(client);
try {
postBuild(client, buildUrl, null);
} catch (WebClientResponseException.Forbidden e) {
Map<String, String> crumb = fetchCrumb(client);
postBuild(client, buildUrl, crumb);
} catch (WebClientResponseException.Forbidden e) {
if (crumb != null) throw e;
postBuild(client, buildUrl, fetchCrumb(client));
}
}
private Map<String, String> fetchCrumbOptional(WebClient client) {
try {
return fetchCrumb(client);
} catch (Exception e) {
log.debug("[desktop-build] crumb optional skip: {}", e.getMessage());
return null;
}
}
private void postBuild(WebClient client, String buildUrl, Map<String, String> crumb) {
var spec = client.post().uri(buildUrl);
var spec = client.post()
.uri(buildUrl)
.contentType(MediaType.APPLICATION_FORM_URLENCODED);
if (crumb != null) {
spec = spec.header(crumb.get("field"), crumb.get("value"));
}
@@ -215,6 +237,27 @@ public class DesktopAppBuildService {
return t == null || t.isBlank() ? null : t;
}
private static String jenkinsHttpError(WebClientResponseException e) {
int code = e.getStatusCode().value();
if (code == 401 || code == 403) {
return "Jenkins 인증 실패 — GC_DESKTOP_JENKINS_USER·TOKEN을 확인하세요.";
}
if (code == 404) {
return "Jenkins Job을 찾을 수 없습니다 — goldenChart-Desktop-Pipeline Job을 등록하세요.";
}
return "Jenkins HTTP " + code + ": " + e.getStatusText();
}
private static String rootMessage(Throwable e) {
Throwable t = e;
while (t.getCause() != null) t = t.getCause();
String msg = t.getMessage();
if (msg != null && msg.contains("Connection refused")) {
return "Jenkins에 연결할 수 없습니다. Docker 환경이면 GC_DESKTOP_JENKINS_URL=http://host.docker.internal:8090 를 설정하세요.";
}
return msg != null ? msg : e.toString();
}
private void syncGitLatest() {
if (!StringUtils.hasText(gitBareDir)) {
log.debug("[desktop-build] git-bare-dir 미설정 — Jenkins SCM checkout에 위임");
@@ -22,6 +22,16 @@ goldenchart:
cors:
allowed-origins:
- "*"
desktop-app:
release-dir: ${GC_DESKTOP_APP_RELEASE_DIR:/app/data/desktop-releases}
public-base-url: ${GC_DESKTOP_APP_PUBLIC_BASE_URL:http://exdev.co.kr}
jenkins:
enabled: ${GC_DESKTOP_JENKINS_ENABLED:true}
# Docker 컨테이너 → 호스트 Jenkins (127.0.0.1:8090 은 컨테이너 자신을 가리킴)
url: ${GC_DESKTOP_JENKINS_URL:http://host.docker.internal:8090}
job: ${GC_DESKTOP_JENKINS_JOB:goldenChart-Desktop-Pipeline}
user: ${GC_DESKTOP_JENKINS_USER:}
token: ${GC_DESKTOP_JENKINS_TOKEN:}
# FCM — exdev: FIREBASE_ENABLED=true + 서비스 계정 JSON 마운트
firebase: