desktop download 수정

This commit is contained in:
Macbook
2026-06-14 10:41:05 +09:00
parent eb9e6ec4e9
commit 7654ec99dc
10 changed files with 168 additions and 11 deletions
+1 -1
View File
@@ -50,7 +50,7 @@
"plugins": {
"updater": {
"endpoints": [
"https://exdev.co.kr/desktop/updates/latest.json"
"http://exdev.co.kr/desktop/updates/latest.json"
],
"pubkey": "REPLACE_WITH_TAURI_SIGNER_PUBKEY"
}
+3
View File
@@ -112,5 +112,8 @@ services:
condition: service_healthy
ports:
- "${FRONTEND_PORT:-80}:80"
volumes:
# Desktop updater latest.json·설치 파일 — Jenkins publish + nginx reload
- ./frontend/public/desktop/updates:/usr/share/nginx/html/desktop/updates:ro
networks:
- goldenchart-net
+15 -1
View File
@@ -32,10 +32,24 @@ $HOME/.cargo/bin
| 항목 | 값 |
|------|-----|
| SCM | `file:///Volumes/ADATA/git/goldenChart.git` main |
| 스케줄 | 30분마다 SCM poll (또는 수동) |
| **트리거** | **`git push main` 성공 시 post-receive → 자동 Jenkins 빌드** |
| 빌드 | `scripts/jenkins-desktop-pipeline.sh` |
| Artifact | `dist-desktop/**` |
`main` push 흐름:
```
git push exdev main
→ post-receive → deploy.sh (웹·백엔드 Docker)
→ trigger-desktop-jenkins-build.sh (Jenkins 큐)
→ macOS dmg + Windows exe + updater 번들
→ publish-desktop-update.sh → latest.json
→ nginx reload (frontend 볼륨 마운트)
→ Desktop 앱 「업데이트」 버튼으로 자동 업데이트
```
CI 빌드 시 `latest.json` 버전 기준 **patch 자동 bump** (예: 0.1.3 → 0.1.4).
환경 변수 (선택):
| 변수 | 설명 |
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# published latest.json 기준 patch 버전 bump → tauri.conf.json (CI 자동 업데이트용)
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
WORK_TREE="${WORK_TREE:-$ROOT}"
CONF="${WORK_TREE}/desktop/src-tauri/tauri.conf.json"
LATEST="${WORK_TREE}/frontend/public/desktop/updates/latest.json"
node -e "
const fs = require('fs');
const confPath = process.argv[1];
const latestPath = process.argv[2];
const conf = JSON.parse(fs.readFileSync(confPath, 'utf8'));
let base = conf.version || '0.1.0';
if (fs.existsSync(latestPath)) {
try {
const pub = JSON.parse(fs.readFileSync(latestPath, 'utf8'));
if (pub.version) base = pub.version;
} catch { /* ignore */ }
}
const parts = base.split('.').map(n => parseInt(n, 10) || 0);
while (parts.length < 3) parts.push(0);
parts[2] += 1;
const nv = parts.join('.');
conf.version = nv;
fs.writeFileSync(confPath, JSON.stringify(conf, null, 2) + '\n');
console.log(nv);
" "$CONF" "$LATEST"
+13 -1
View File
@@ -42,7 +42,14 @@ fi
BUILD_ARGS=(--all)
if [[ -n "${DESKTOP_BUILD_MAC_ONLY:-}" ]]; then BUILD_ARGS=(--mac); fi
if [[ -n "${DESKTOP_BUILD_WIN_ONLY:-}" ]]; then BUILD_ARGS=(--win); fi
if [[ -n "${BUMP_VERSION:-}" ]]; then BUILD_ARGS+=(--bump-version "$BUMP_VERSION"); fi
if [[ -n "${BUMP_VERSION:-}" ]]; then
BUILD_ARGS+=(--bump-version "$BUMP_VERSION")
elif [[ -n "${BUILD_NUMBER:-}" && "${DESKTOP_BUMP_ON_CI:-1}" == "1" ]]; then
log "CI patch bump (latest.json 기준)..."
chmod +x "$ROOT/scripts/bump-desktop-version-from-release.sh"
NEW_VER="$("$ROOT/scripts/bump-desktop-version-from-release.sh")"
log "Desktop version → $NEW_VER"
fi
"$ROOT/scripts/build-desktop.sh" "${BUILD_ARGS[@]}"
@@ -53,6 +60,11 @@ TAURI_SIGNER_KEY="${TAURI_SIGNER_KEY:-$HOME/.tauri/goldenchart.key}" \
DESKTOP_RELEASE_NOTES="${DESKTOP_RELEASE_NOTES:-Build ${BUILD_NUMBER:-local}}" \
"$ROOT/scripts/publish-desktop-update.sh"
# latest.json·설치 파일 nginx 즉시 반영 (볼륨 마운트)
if [[ -x "$ROOT/scripts/reload-frontend-desktop-static.sh" ]]; then
WORK_TREE="$WORK_TREE" "$ROOT/scripts/reload-frontend-desktop-static.sh" || true
fi
# Jenkins artifact archive 경로
if [[ -d "$ROOT/dist-desktop" ]]; then
log "Artifacts ready: $ROOT/dist-desktop"
+15
View File
@@ -4,6 +4,7 @@
set -euo pipefail
GIT_DIR="/Volumes/ADATA/git/goldenChart.git"
WORK_TREE="${WORK_TREE:-/Users/aidev/apps/goldenChart}"
DEPLOY_SCRIPT="/Volumes/ADATA/git/deploy.sh"
SUMMARY_SCRIPT="/Volumes/ADATA/git/git-push-summary.sh"
DEPLOY_LOG="/Volumes/ADATA/logs/deploy/deploy.log"
@@ -41,6 +42,20 @@ while read -r OLDREV NEWREV REFNAME; do
exit "$EXIT_CODE"
fi
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG 배포 완료"
# Desktop(macOS·Windows) Jenkins 빌드 — git push 성공 후 자동 (웹 배포와 독립)
WORK_TREE="${WORK_TREE:-/Users/aidev/apps/goldenChart}"
TRIGGER="${WORK_TREE}/scripts/trigger-desktop-jenkins-build.sh"
if [ -x "$TRIGGER" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG Desktop Jenkins 빌드 트리거"
if "$TRIGGER" >> "$DEPLOY_LOG" 2>&1; then
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG Desktop 빌드 큐 등록 완료"
else
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG [WARN] Desktop Jenkins 트리거 실패 (웹 배포는 성공)"
fi
else
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG [WARN] trigger-desktop-jenkins-build.sh 없음: $TRIGGER"
fi
else
echo "$(date '+%Y-%m-%d %H:%M:%S') $HOOK_TAG '$BRANCH_NAME' — 배포 스킵 (main만)"
fi
+1 -1
View File
@@ -25,7 +25,7 @@ conf.bundle.createUpdaterArtifacts = enable;
conf.plugins = conf.plugins || {};
conf.plugins.updater = conf.plugins.updater || {};
if (!conf.plugins.updater.endpoints?.length) {
conf.plugins.updater.endpoints = ['https://exdev.co.kr/desktop/updates/latest.json'];
conf.plugins.updater.endpoints = ['http://exdev.co.kr/desktop/updates/latest.json'];
}
if (!conf.plugins.updater.pubkey) {
conf.plugins.updater.pubkey = 'REPLACE_WITH_TAURI_SIGNER_PUBKEY';
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# desktop/updates static 반영 — nginx reload (볼륨 마운트 시 재빌드 불필요)
set -euo pipefail
WORK_TREE="${WORK_TREE:-/Users/aidev/apps/goldenChart}"
COMPOSE="${DOCKER_COMPOSE_FILE:-$WORK_TREE/docker-compose.yml}"
CONTAINER="${FRONTEND_CONTAINER:-gc-frontend}"
if [[ ! -f "$COMPOSE" ]]; then
echo "[reload-desktop-static] skip — no compose: $COMPOSE"
exit 0
fi
if docker ps --format '{{.Names}}' | grep -qx "$CONTAINER"; then
docker exec "$CONTAINER" nginx -s reload 2>/dev/null \
&& echo "[reload-desktop-static] nginx reload OK ($CONTAINER)" \
&& exit 0
fi
if docker compose -f "$COMPOSE" ps frontend 2>/dev/null | grep -q Up; then
docker compose -f "$COMPOSE" exec -T frontend nginx -s reload \
&& echo "[reload-desktop-static] nginx reload OK (compose)" \
&& exit 0
fi
echo "[reload-desktop-static] frontend container not running — skip"
+5 -7
View File
@@ -42,11 +42,7 @@ cat > "${JENKINS_HOME}/jobs/${JENKINS_JOB}/config.xml" << JENKINS_XML
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers>
<hudson.triggers.SCMTrigger>
<spec>H/30 * * * *</spec>
</hudson.triggers.SCMTrigger>
</triggers>
<triggers/>
<concurrentBuild>false</concurrentBuild>
<builders>
<hudson.tasks.Shell>
@@ -57,8 +53,10 @@ export WORK_TREE="${WORK_TREE}"
export GIT_DIR="${GIT_DIR}"
export BUILD_NUMBER="\${BUILD_NUMBER}"
export TAURI_SIGNER_KEY="\${TAURI_SIGNER_KEY:-\$HOME/.tauri/goldenchart.key}"
export DESKTOP_DEPLOY_WEB="\${DESKTOP_DEPLOY_WEB:-1}"
"${REPO_ROOT}/scripts/jenkins-desktop-pipeline.sh"
export DESKTOP_BUMP_ON_CI=1
export DESKTOP_DEPLOY_WEB=0
export DESKTOP_UPDATE_BASE_URL="${DESKTOP_UPDATE_BASE_URL:-http://exdev.co.kr/desktop/updates}"
"${WORK_TREE}/scripts/jenkins-desktop-pipeline.sh"
</command>
</hudson.tasks.Shell>
</builders>
+60
View File
@@ -0,0 +1,60 @@
#!/usr/bin/env bash
# Git push(main) 후 Jenkins goldenChart-Desktop-Pipeline 트리거
set -euo pipefail
JENKINS_URL="${JENKINS_URL:-${GC_DESKTOP_JENKINS_URL:-http://127.0.0.1:8090}}"
JENKINS_JOB="${JENKINS_JOB:-${GC_DESKTOP_JENKINS_JOB:-goldenChart-Desktop-Pipeline}}"
JENKINS_USER="${JENKINS_USER:-${GC_DESKTOP_JENKINS_USER:-}}"
JENKINS_TOKEN="${JENKINS_TOKEN:-${GC_DESKTOP_JENKINS_TOKEN:-}}"
LOG_TAG="[trigger-desktop]"
log() { echo "$(date '+%Y-%m-%d %H:%M:%S') $LOG_TAG $*"; }
JENKINS_URL="${JENKINS_URL%/}"
JOB_API="${JENKINS_URL}/job/${JENKINS_JOB// /%20}"
curl_get() {
if [[ -n "$JENKINS_USER" && -n "$JENKINS_TOKEN" ]]; then
curl -sf -u "${JENKINS_USER}:${JENKINS_TOKEN}" "$@"
else
curl -sf "$@"
fi
}
curl_post() {
if [[ -n "$JENKINS_USER" && -n "$JENKINS_TOKEN" ]]; then
curl -sf -X POST -u "${JENKINS_USER}:${JENKINS_TOKEN}" "$@"
else
curl -sf -X POST "$@"
fi
}
log "Jenkins desktop build — $JENKINS_JOB @ $JENKINS_URL"
if ! curl -sf -o /dev/null "${JENKINS_URL}/login" 2>/dev/null; then
log "[ERROR] Jenkins unreachable: $JENKINS_URL"
exit 1
fi
if curl_get "${JOB_API}/lastBuild/api/json?tree=building" 2>/dev/null | grep -q '"building":true'; then
log "[SKIP] 이미 빌드 진행 중"
exit 0
fi
CRUMB_HDR=()
CRUMB_JSON="$(curl_get "${JENKINS_URL}/crumbIssuer/api/json" 2>/dev/null || true)"
if [[ -n "$CRUMB_JSON" ]]; then
FIELD="$(node -e "try{console.log(JSON.parse(process.argv[1]).crumbRequestField||'')}catch{}" "$CRUMB_JSON" 2>/dev/null || true)"
VAL="$(node -e "try{console.log(JSON.parse(process.argv[1]).crumb||'')}catch{}" "$CRUMB_JSON" 2>/dev/null || true)"
if [[ -n "$FIELD" && -n "$VAL" ]]; then
CRUMB_HDR=(-H "${FIELD}: ${VAL}")
fi
fi
if curl_post "${CRUMB_HDR[@]}" -H "Content-Type: application/x-www-form-urlencoded" "${JOB_API}/build"; then
log "빌드 큐 등록 완료"
exit 0
fi
log "[ERROR] Jenkins build trigger failed"
exit 1