desktop 다운로드 수정
This commit is contained in:
@@ -45,6 +45,9 @@ public class DesktopAppBuildService {
|
||||
@Value("${goldenchart.desktop-app.jenkins.token:}")
|
||||
private String jenkinsToken;
|
||||
|
||||
@Value("${goldenchart.desktop-app.jenkins.trigger-token:}")
|
||||
private String jenkinsTriggerToken;
|
||||
|
||||
@Value("${goldenchart.desktop-app.git-bare-dir:}")
|
||||
private String gitBareDir;
|
||||
|
||||
@@ -53,11 +56,22 @@ public class DesktopAppBuildService {
|
||||
|
||||
public DesktopAppBuildStatusDto getStatus() {
|
||||
if (!jenkinsEnabled) {
|
||||
return disabledStatus("Jenkins 연동이 비활성화되어 있습니다.");
|
||||
}
|
||||
if (!hasBasicAuth()) {
|
||||
if (hasTriggerToken()) {
|
||||
return DesktopAppBuildStatusDto.builder()
|
||||
.jenkinsEnabled(true)
|
||||
.building(false)
|
||||
.status("ready")
|
||||
.message("빌드 트리거 준비됨 (원격 토큰). 상태 조회는 Jenkins API 토큰 설정 시 가능합니다.")
|
||||
.build();
|
||||
}
|
||||
return DesktopAppBuildStatusDto.builder()
|
||||
.jenkinsEnabled(false)
|
||||
.jenkinsEnabled(true)
|
||||
.building(false)
|
||||
.status("disabled")
|
||||
.message("Jenkins 연동이 비활성화되어 있습니다.")
|
||||
.status("error")
|
||||
.message("Jenkins 인증 미설정 — GC_DESKTOP_JENKINS_TRIGGER_TOKEN 또는 USER/TOKEN을 backend에 설정하세요.")
|
||||
.build();
|
||||
}
|
||||
try {
|
||||
@@ -68,7 +82,7 @@ public class DesktopAppBuildService {
|
||||
.jenkinsEnabled(true)
|
||||
.building(false)
|
||||
.status("error")
|
||||
.message("Jenkins 상태 조회 실패: " + e.getMessage())
|
||||
.message("Jenkins 상태 조회 실패: " + rootMessage(e))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -78,23 +92,40 @@ public class DesktopAppBuildService {
|
||||
if (!jenkinsEnabled) {
|
||||
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE, "Jenkins 연동이 비활성화되어 있습니다.");
|
||||
}
|
||||
if (!hasBasicAuth() && !hasTriggerToken()) {
|
||||
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,
|
||||
"Jenkins 연동 설정 필요 — GC_DESKTOP_JENKINS_TRIGGER_TOKEN 또는 GC_DESKTOP_JENKINS_USER·TOKEN을 backend 환경변수에 설정하세요.");
|
||||
}
|
||||
try {
|
||||
syncGitLatest();
|
||||
|
||||
DesktopAppBuildStatusDto current = fetchLastBuildStatus();
|
||||
if (current.isBuilding()) {
|
||||
return DesktopAppBuildTriggerDto.builder()
|
||||
.accepted(false)
|
||||
.buildNumber(current.getBuildNumber())
|
||||
.message("이미 빌드가 진행 중입니다 (#" + current.getBuildNumber() + ").")
|
||||
.build();
|
||||
if (hasBasicAuth()) {
|
||||
try {
|
||||
DesktopAppBuildStatusDto current = fetchLastBuildStatus();
|
||||
if (current.isBuilding()) {
|
||||
return DesktopAppBuildTriggerDto.builder()
|
||||
.accepted(false)
|
||||
.buildNumber(current.getBuildNumber())
|
||||
.message("이미 빌드가 진행 중입니다 (#" + current.getBuildNumber() + ").")
|
||||
.build();
|
||||
}
|
||||
} catch (WebClientResponseException e) {
|
||||
log.warn("[desktop-build] status skip before trigger: HTTP {}", e.getStatusCode().value());
|
||||
}
|
||||
}
|
||||
|
||||
triggerJenkinsBuild();
|
||||
DesktopAppBuildStatusDto after = fetchLastBuildStatus();
|
||||
|
||||
Integer buildNumber = null;
|
||||
if (hasBasicAuth()) {
|
||||
try {
|
||||
buildNumber = fetchLastBuildStatus().getBuildNumber();
|
||||
} catch (Exception ignored) { /* optional */ }
|
||||
}
|
||||
|
||||
return DesktopAppBuildTriggerDto.builder()
|
||||
.accepted(true)
|
||||
.buildNumber(after.getBuildNumber())
|
||||
.buildNumber(buildNumber)
|
||||
.message("Jenkins에서 macOS·Windows 데스크톱 앱 빌드를 시작했습니다. 완료 후 설치 파일이 자동으로 반영됩니다.")
|
||||
.build();
|
||||
} catch (ResponseStatusException e) {
|
||||
@@ -165,7 +196,7 @@ public class DesktopAppBuildService {
|
||||
|
||||
private void triggerJenkinsBuild() {
|
||||
WebClient client = jenkinsClient();
|
||||
String buildUrl = jobApiPath() + "/build";
|
||||
String buildUrl = buildTriggerUrl();
|
||||
Map<String, String> crumb = fetchCrumbOptional(client);
|
||||
try {
|
||||
postBuild(client, buildUrl, crumb);
|
||||
@@ -175,11 +206,19 @@ public class DesktopAppBuildService {
|
||||
}
|
||||
}
|
||||
|
||||
private String buildTriggerUrl() {
|
||||
String url = jobApiPath() + "/build";
|
||||
if (hasTriggerToken()) {
|
||||
url += "?token=" + UriUtils.encodeQueryParam(jenkinsTriggerToken.trim(), StandardCharsets.UTF_8);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
private Map<String, String> fetchCrumbOptional(WebClient client) {
|
||||
try {
|
||||
return fetchCrumb(client);
|
||||
} catch (Exception e) {
|
||||
log.debug("[desktop-build] crumb optional skip: {}", e.getMessage());
|
||||
log.debug("[desktop-build] crumb skip: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -215,17 +254,34 @@ public class DesktopAppBuildService {
|
||||
WebClient.Builder builder = webClientBuilder
|
||||
.baseUrl(normalizeBase(jenkinsUrl))
|
||||
.defaultHeader("Accept", MediaType.APPLICATION_JSON_VALUE);
|
||||
if (StringUtils.hasText(jenkinsUser) && StringUtils.hasText(jenkinsToken)) {
|
||||
if (hasBasicAuth()) {
|
||||
builder.defaultHeaders(h -> h.setBasicAuth(jenkinsUser.trim(), jenkinsToken.trim()));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private boolean hasBasicAuth() {
|
||||
return StringUtils.hasText(jenkinsUser) && StringUtils.hasText(jenkinsToken);
|
||||
}
|
||||
|
||||
private boolean hasTriggerToken() {
|
||||
return StringUtils.hasText(jenkinsTriggerToken);
|
||||
}
|
||||
|
||||
private String jobApiPath() {
|
||||
String encoded = UriUtils.encodePathSegment(jenkinsJob.trim(), StandardCharsets.UTF_8);
|
||||
return "/job/" + encoded;
|
||||
}
|
||||
|
||||
private static DesktopAppBuildStatusDto disabledStatus(String message) {
|
||||
return DesktopAppBuildStatusDto.builder()
|
||||
.jenkinsEnabled(false)
|
||||
.building(false)
|
||||
.status("disabled")
|
||||
.message(message)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static String normalizeBase(String url) {
|
||||
if (!StringUtils.hasText(url)) return "http://127.0.0.1:8090";
|
||||
return url.trim().replaceAll("/+$", "");
|
||||
@@ -240,10 +296,10 @@ public class DesktopAppBuildService {
|
||||
private static String jenkinsHttpError(WebClientResponseException e) {
|
||||
int code = e.getStatusCode().value();
|
||||
if (code == 401 || code == 403) {
|
||||
return "Jenkins 인증 실패 — GC_DESKTOP_JENKINS_USER·TOKEN을 확인하세요.";
|
||||
return "Jenkins 인증 실패 — GC_DESKTOP_JENKINS_TRIGGER_TOKEN 또는 USER/TOKEN·Job 원격 트리거 토큰을 확인하세요.";
|
||||
}
|
||||
if (code == 404) {
|
||||
return "Jenkins Job을 찾을 수 없습니다 — goldenChart-Desktop-Pipeline Job을 등록하세요.";
|
||||
return "Jenkins Job을 찾을 수 없습니다 — ./scripts/server-install-desktop-jenkins.sh 로 Job을 등록하세요.";
|
||||
}
|
||||
return "Jenkins HTTP " + code + ": " + e.getStatusText();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user