fix: Windows desktop updater — sign setup.exe, preserve latest.json on deploy
Sign *-setup.exe for updater manifest, pick newest bundle per platform, reconcile after git checkout, and stop overwriting latest.json with empty placeholder. Bump desktop to 0.1.3. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@goldenchart/desktop",
|
"name": "@goldenchart/desktop",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "GoldenChart",
|
"productName": "GoldenChart",
|
||||||
"version": "0.1.2",
|
"version": "0.1.3",
|
||||||
"identifier": "com.goldenchart.desktop",
|
"identifier": "com.goldenchart.desktop",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|||||||
@@ -73,6 +73,13 @@ fi
|
|||||||
[ ! -f "$DOCKER_COMPOSE_FILE" ] && err "docker-compose.yml 없음: $DOCKER_COMPOSE_FILE"
|
[ ! -f "$DOCKER_COMPOSE_FILE" ] && err "docker-compose.yml 없음: $DOCKER_COMPOSE_FILE"
|
||||||
cd "$WORK_TREE"
|
cd "$WORK_TREE"
|
||||||
|
|
||||||
|
# Phase 1b — git checkout이 placeholder latest.json 을 되돌리므로 signed bundle 기준 복구
|
||||||
|
RECONCILE="$WORK_TREE/scripts/reconcile-desktop-latest-json.sh"
|
||||||
|
if [[ -x "$RECONCILE" ]]; then
|
||||||
|
info "[Phase 1b] desktop latest.json reconcile"
|
||||||
|
WORK_TREE="$WORK_TREE" "$RECONCILE" || warn "reconcile-desktop-latest-json 실패"
|
||||||
|
fi
|
||||||
|
|
||||||
# Phase 2 — Docker 이미지 빌드 (호스트 npm 사용 안 함 → postcss 홈 디렉터리 간섭 방지)
|
# Phase 2 — Docker 이미지 빌드 (호스트 npm 사용 안 함 → postcss 홈 디렉터리 간섭 방지)
|
||||||
info "[Phase 2] Docker 이미지 빌드 ($SERVICE_NAME)"
|
info "[Phase 2] Docker 이미지 빌드 ($SERVICE_NAME)"
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,22 @@ if (!fs.existsSync(dir)) {
|
|||||||
|
|
||||||
const files = fs.readdirSync(dir);
|
const files = fs.readdirSync(dir);
|
||||||
|
|
||||||
/** @type {Record<string, { url: string; signature: string }>} */
|
function versionFromName(name) {
|
||||||
|
const m = name.match(/(\d+\.\d+\.\d+)/);
|
||||||
|
return m ? m[1] : '0.0.0';
|
||||||
|
}
|
||||||
|
|
||||||
|
function cmpSemver(a, b) {
|
||||||
|
const pa = a.split('.').map(Number);
|
||||||
|
const pb = b.split('.').map(Number);
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
const d = (pa[i] || 0) - (pb[i] || 0);
|
||||||
|
if (d !== 0) return d;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {Record<string, { url: string; signature: string; bundleVersion: string }>} */
|
||||||
const platforms = {};
|
const platforms = {};
|
||||||
|
|
||||||
function addPlatform(platformKey, bundleName) {
|
function addPlatform(platformKey, bundleName) {
|
||||||
@@ -43,9 +58,13 @@ function addPlatform(platformKey, bundleName) {
|
|||||||
console.warn(`[warn] missing signature: ${sigPath}`);
|
console.warn(`[warn] missing signature: ${sigPath}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const bundleVersion = versionFromName(bundleName);
|
||||||
|
const existing = platforms[platformKey];
|
||||||
|
if (existing && cmpSemver(bundleVersion, existing.bundleVersion) <= 0) return;
|
||||||
platforms[platformKey] = {
|
platforms[platformKey] = {
|
||||||
url: `${baseUrl}/${encodeURIComponent(bundleName)}`,
|
url: `${baseUrl}/${encodeURIComponent(bundleName)}`,
|
||||||
signature,
|
signature,
|
||||||
|
bundleVersion,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,7 +91,9 @@ const manifest = {
|
|||||||
version,
|
version,
|
||||||
notes,
|
notes,
|
||||||
pub_date: new Date().toISOString(),
|
pub_date: new Date().toISOString(),
|
||||||
platforms,
|
platforms: Object.fromEntries(
|
||||||
|
Object.entries(platforms).map(([k, v]) => [k, { url: v.url, signature: v.signature }]),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
const outPath = path.join(dir, 'latest.json');
|
const outPath = path.join(dir, 'latest.json');
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ fi
|
|||||||
# updater 번들 서명
|
# updater 번들 서명
|
||||||
if [[ -f "$KEY_PATH" ]]; then
|
if [[ -f "$KEY_PATH" ]]; then
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for bundle in "$PUBLISH_UPDATES"/*.tar.gz "$PUBLISH_UPDATES"/*.nsis.zip "$PUBLISH_UPDATES"/*.zip; do
|
for bundle in "$PUBLISH_UPDATES"/*.tar.gz "$PUBLISH_UPDATES"/*-setup.exe "$PUBLISH_UPDATES"/*.nsis.zip "$PUBLISH_UPDATES"/*.zip; do
|
||||||
[[ -f "$bundle" ]] || continue
|
[[ -f "$bundle" ]] || continue
|
||||||
[[ "$bundle" == *.sig ]] && continue
|
[[ "$bundle" == *.sig ]] && continue
|
||||||
log "Signing $(basename "$bundle")"
|
log "Signing $(basename "$bundle")"
|
||||||
@@ -77,15 +77,7 @@ GEN_RC=$?
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
if [[ "$GEN_RC" -eq 2 ]]; then
|
if [[ "$GEN_RC" -eq 2 ]]; then
|
||||||
log "[WARN] signed updater bundle 없음 — placeholder latest.json 작성"
|
log "[WARN] signed updater bundle 없음 — latest.json 유지 (placeholder 덮어쓰기 안 함)"
|
||||||
cat > "$PUBLISH_UPDATES/latest.json" <<EOF
|
|
||||||
{
|
|
||||||
"version": "$VERSION",
|
|
||||||
"notes": "$NOTES",
|
|
||||||
"pub_date": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
||||||
"platforms": {}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
elif [[ "$GEN_RC" -ne 0 ]]; then
|
elif [[ "$GEN_RC" -ne 0 ]]; then
|
||||||
exit "$GEN_RC"
|
exit "$GEN_RC"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -15,12 +15,33 @@ fi
|
|||||||
|
|
||||||
VERSION="$(node -p "require('$CONF').version" 2>/dev/null || echo '0.1.0')"
|
VERSION="$(node -p "require('$CONF').version" 2>/dev/null || echo '0.1.0')"
|
||||||
LATEST_JSON="$UPDATES_DIR/latest.json"
|
LATEST_JSON="$UPDATES_DIR/latest.json"
|
||||||
|
BUILD_INFO="$UPDATES_DIR/build-info.json"
|
||||||
|
if [[ -f "$BUILD_INFO" ]]; then
|
||||||
|
BI_VER="$(node -p "require('$BUILD_INFO').version || ''" 2>/dev/null || true)"
|
||||||
|
if [[ -n "$BI_VER" ]]; then
|
||||||
|
VERSION="$(node <<NODE
|
||||||
|
const cmp = (a, b) => {
|
||||||
|
const pa = a.split('.').map(Number), pb = b.split('.').map(Number);
|
||||||
|
for (let i = 0; i < 3; i++) { const d = (pa[i]||0)-(pb[i]||0); if (d) return d; }
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
console.log(cmp('$BI_VER', '$VERSION') > 0 ? '$BI_VER' : '$VERSION');
|
||||||
|
NODE
|
||||||
|
)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [[ -f "$LATEST_JSON" ]]; then
|
if [[ -f "$LATEST_JSON" ]]; then
|
||||||
EXISTING="$(node <<NODE
|
EXISTING="$(node <<NODE
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const confV = '$VERSION';
|
const confV = '$VERSION';
|
||||||
let existing = '0.0.0';
|
let existing = '0.0.0';
|
||||||
try { existing = JSON.parse(fs.readFileSync('$LATEST_JSON', 'utf8')).version || '0.0.0'; } catch {}
|
let hasPlatforms = false;
|
||||||
|
try {
|
||||||
|
const j = JSON.parse(fs.readFileSync('$LATEST_JSON', 'utf8'));
|
||||||
|
existing = j.version || '0.0.0';
|
||||||
|
hasPlatforms = j.platforms && Object.keys(j.platforms).length > 0;
|
||||||
|
} catch {}
|
||||||
|
if (!hasPlatforms) { console.log(confV); process.exit(0); }
|
||||||
const cmp = (a, b) => {
|
const cmp = (a, b) => {
|
||||||
const pa = a.split('.').map(Number), pb = b.split('.').map(Number);
|
const pa = a.split('.').map(Number), pb = b.split('.').map(Number);
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user