Skip to content

Commit e52f831

Browse files
committed
fix(release): harden installer rollback and rights boundaries
1 parent 53ad1bf commit e52f831

22 files changed

Lines changed: 279 additions & 44 deletions

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ jobs:
8585
CODEX_DREAM_SKIN_SKIP_SIGNED_RUNTIME_TESTS=1 \
8686
CODEX_DREAM_SKIN_SKIP_DOCTOR=1 \
8787
./macos/tests/run-tests.sh
88+
swift test --package-path macos/menubar-app
8889
test -x macos/scripts/build-dmg.sh || chmod +x macos/scripts/build-dmg.sh
8990
# The builder owns app assembly, engine staging, and ad-hoc signing.
9091
# Release signing/notarization remains optional and is intentionally

docs/background-generation-prompts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
| 你要做的事 | 应看的文件 | 说明 |
1414
|---|---|---|
15-
| 直接切换当前置顶主题 | `macos/presets/preset-arina-hashimoto/theme.json` + `background.jpg`;Windows 对应 `windows/assets/theme.json` + `dream-reference.jpg` | 两端都播种「桥本有菜」;不是 `docs/images/presets/*-light/dark` 截图 |
15+
| 在获权的源码 checkout 中切换参考主题 | `macos/presets/preset-arina-hashimoto/theme.json` + `background.jpg`源码 Windows 对应 `windows/assets/theme.json` + `dream-reference.jpg` | 仅限本地权利核验后的源码使用;公开 DMG/Setup.exe 只播种 Gothic Void Crusade,不是 `docs/images/presets/*-light/dark` 截图 |
1616
| 重新生成一张纯背景 | 本文件的通用模板或 [`reference-background-prompt-guide.md`](./reference-background-prompt-guide.md) | 输出应是独立的 `2560 × 1440`、16:9 图片,不是截图 |
1717
| 只看效果或找风格 | `docs/images/gallery/skin-01.jpg``skin-08.jpg` | 带 UI 的概念效果图,不能改名为 `background.jpg` 后导入 |
1818
| 查看当前主题在浅/暗色下的实机结果 | `docs/images/presets/arina-hashimoto-light.jpg``arina-hashimoto-dark.jpg` | 仅预览,包含真实控件,不能作为背景素材 |

docs/reference-background-prompt-guide.en.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ Chinese guide: [`reference-background-prompt-guide.md`](./reference-background-p
66

77
> Public prompts default to an original fictional adult. They do not name or imitate a celebrity, private individual, copyrighted character, or living artist's signature style. Use an authorized identity reference only when you hold the necessary likeness and asset rights. Generated artwork is not an official OpenAI/Codex visual or endorsement.
88
9-
## Current Tested Feature: Arina Hashimoto
9+
## Source-Only Reference: Arina Hashimoto (Excluded From Public Packages)
1010

11-
- **Switchable theme:** `macos/presets/preset-arina-hashimoto/`; Windows seeds from `windows/assets/theme.json` plus the byte-identical `windows/assets/dream-reference.jpg`. Both installers seed Arina Hashimoto.
11+
- **Source-only switchable reference:** `macos/presets/preset-arina-hashimoto/`; source Windows runs can use `windows/assets/theme.json` plus the byte-identical `windows/assets/dream-reference.jpg`. Public DMG and Setup.exe exclude these files and seed only the rights-reviewed Gothic Void Crusade.
1212
- **User-supplied pure source:** `docs/images/presets/arina-hashimoto-source.png` (`1672 × 941`). The preset's `2560 × 1440` JPEG is a standardized release derivative and does not create additional source detail.
1313
- **Real runtime results:** `arina-hashimoto-light.jpg` and `arina-hashimoto-dark.jpg` are light/dark screenshots for preview only. They are not importable wallpapers.
1414
- **Relationship to earlier examples:** this is the current tested preset, not `docs/images/gallery/skin-01.jpg` and not one of the skin-01–08 concept mockups. skin-01 contributes only a related pink-rose direction and UI-copy reference.
@@ -21,15 +21,15 @@ The “effect” shown in a README is not automatically an importable wallpaper.
2121

2222
| Type | Repository path | What it is | A complete theme? |
2323
|---|---|---|---|
24-
| **Current featured preset** | `macos/presets/preset-arina-hashimoto/`; Windows seeds from `windows/assets/theme.json` plus the byte-identical `dream-reference.jpg` | A cross-platform theme pack containing a UI-free wallpaper; both installers seed Arina Hashimoto | **Yes** |
24+
| **Source-only reference preset** | `macos/presets/preset-arina-hashimoto/`; source Windows runs use `windows/assets/theme.json` plus the byte-identical `dream-reference.jpg` | Use locally only after an independent rights review; public DMG/Setup.exe use Gothic Void Crusade instead | **Only in an authorized local source checkout** |
2525
| **Pure source art** | `docs/images/presets/arina-hashimoto-source.png` | User-supplied source wallpaper around `1672 × 941`; no `theme.json` | **No**; it can be selected as an image, but is not a complete pack |
2626
| **Real injected previews** | `docs/images/presets/arina-hashimoto-light.jpg`, `arina-hashimoto-dark.jpg` | Light/dark Codex screenshots containing real controls | **No** |
2727
| **Concept gallery** | `docs/images/gallery/skin-01.jpg``skin-08.jpg` | UI effect mockups used only to communicate visual directions | **No** |
2828
| **Experimental/history images** | `docs/images/banner-*.png`, `docs/images/generated-*.png` | Unapproved local experiments or references | **No**; do not ship without rights/provenance review |
2929

3030
`docs/images/hero-banner-red-white.png` and `macos/assets/portal-hero.png` are legacy 3:1 banner assets, not the current 16:9 universal-theme master. Do not substitute either for `preset-*/background.jpg` unless the output is intentionally homepage-banner-only.
3131

32-
Rule of thumb: **switch themes from `macos/presets/preset-*`; generate from this guide; study directions in `docs/images/gallery/`; inspect runtime results in `docs/images/presets/*-light.jpg` / `*-dark.jpg`.** A `theme.json` and a `background.jpg` in the same `preset-*` directory form a seedable theme; `docs/images/` is documentation/archive space, not a mirror of the theme library.
32+
Rule of thumb: **public installers default to Gothic Void Crusade; use the source-only reference preset locally only after a rights review.** Generate from this guide; study directions in `docs/images/gallery/`; inspect runtime results in `docs/images/presets/*-light.jpg` / `*-dark.jpg`. A `theme.json` and a `background.jpg` in the same `preset-*` directory form a seedable theme; `docs/images/` is documentation/archive space, not a mirror of the theme library.
3333

3434
Path classification is not a likeness or redistribution license. The current `preset-arina-hashimoto` contains user-provided human/AI portrait material included at the maintainer's direction. Public repository inclusion neither grants nor proves likeness, generation, commercial-use, or further-redistribution rights; see `macos/NOTICE.md` for the file-level boundary.
3535

docs/reference-background-prompt-guide.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
77
English guide: [`reference-background-prompt-guide.en.md`](./reference-background-prompt-guide.en.md)
88

9-
## 当前实测精选置顶:桥本有菜
9+
## 当前源码参考:桥本有菜(不随公开安装包提供)
1010

11-
- **实际可切换主题**`macos/presets/preset-arina-hashimoto/`;Windows 使用 `windows/assets/theme.json` 与 byte-identical 的 `windows/assets/dream-reference.jpg` 组成播种源,两端首装都会播种「桥本有菜」
11+
- **源码中的可切换参考主题**`macos/presets/preset-arina-hashimoto/`源码 Windows 运行时使用 `windows/assets/theme.json` 与 byte-identical 的 `windows/assets/dream-reference.jpg`。公开 DMG 和 Setup.exe 不包含这套素材,公开包只播种已确认可分发的 Gothic Void Crusade
1212
- **用户提供的纯背景源图**`docs/images/presets/arina-hashimoto-source.png``1672 × 941`);preset 中的 `2560 × 1440` JPEG 是标准化发行副本,不会凭空增加源图细节。
1313
- **真实运行效果**`arina-hashimoto-light.jpg``arina-hashimoto-dark.jpg` 是浅色/暗色实机截图,只用于预览,不能导入为背景。
1414
- **与历史示例的关系**:它是当前实际预设,不是 `docs/images/gallery/skin-01.jpg`,也不是 skin-01~08 的概念效果图。skin-01 只提供相近的粉色玫瑰视觉方向和 UI 文案参考。
@@ -21,15 +21,15 @@ README 里的“效果图”不等于可以导入的背景。下面这些文件
2121

2222
| 类型 | 仓库路径 | 作用 | 能否直接作为完整主题导入 |
2323
|---|---|---|---|
24-
| **实际可切换预设(当前置顶** | `macos/presets/preset-arina-hashimoto/`;Windows 的播种源为 `windows/assets/theme.json` + byte-identical 的 `dream-reference.jpg` | 两端都会播种「桥本有菜」;macOS 用脚本/菜单栏切换,Windows 用系统托盘切换 | **可以** |
24+
| **源码参考预设(非公开包** | `macos/presets/preset-arina-hashimoto/`源码 Windows 播种源为 `windows/assets/theme.json` + byte-identical 的 `dream-reference.jpg` | 仅在本地源码且完成权利核验后使用;公开 DMG/Setup.exe 改用 Gothic Void Crusade | **仅限获权的本地源码场景** |
2525
| **纯背景源图** | `docs/images/presets/arina-hashimoto-source.png` | 用户提供的原始纯背景,约 `1672 × 941`;只有图片,没有 `theme.json` | **不能作为完整主题**;可手动换图,但应先检查比例和裁切 |
2626
| **真实实机效果预览** | `docs/images/presets/arina-hashimoto-light.jpg``arina-hashimoto-dark.jpg` | 浅色/暗色 Codex 注入截图,包含真实侧栏、卡片和输入框 | **不可以** |
2727
| **概念效果图** | `docs/images/gallery/skin-01.jpg``skin-08.jpg` | 只表达八种视觉方向的带 UI 示例;配套的 `background-generation-prompts.md` 按这些方向拆解 | **不可以** |
2828
| **实验/历史图片** | `docs/images/banner-*.png``docs/images/generated-*.png` | 尚未批准的本地实验图或参考图;不属于任何 preset pack | **不可以**,也不要未经权利核验放进发行包 |
2929

3030
`docs/images/hero-banner-red-white.png``macos/assets/portal-hero.png` 是旧的 3:1 横幅资源,不是当前 16:9 通用主题母版;除非明确只做首页横幅,否则不要拿它们替代 `preset-*/background.jpg`
3131

32-
一句话判断:**要切换主题看 `macos/presets/preset-*`要生成新图看本指南;要看视觉方向看 `docs/images/gallery/`;要看真实运行结果看 `docs/images/presets/*-light.jpg` / `*-dark.jpg`** `theme.json``background.jpg` 同在一个 `preset-*` 目录时才是一套可播种的主题;`docs/images/` 是文档/归档目录,不是主题库的镜像。
32+
一句话判断:**公开安装包的默认主题是 Gothic Void Crusade;源码中的参考主题仅在完成权利核验后本地切换。** 要生成新图看本指南;要看视觉方向看 `docs/images/gallery/`;要看真实运行结果看 `docs/images/presets/*-light.jpg` / `*-dark.jpg``theme.json``background.jpg` 同在一个 `preset-*` 目录时才是一套可播种的主题;`docs/images/` 是文档/归档目录,不是主题库的镜像。
3333

3434
路径分类不代表肖像或再分发许可。当前 `preset-arina-hashimoto` 含维护者指示收录的用户提供真人/AI 肖像素材;仓库公开包含这些文件并不授予或证明肖像、生成、商业使用或再次分发权利,具体边界以 `macos/NOTICE.md` 为准。
3535

macos/README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ This project injects through **local loopback CDP**. It does **not** modify the
1010
1111
## Requirements
1212

13-
- macOS
13+
- macOS 13 Ventura or newer (the native DMG app declares macOS 13 as its minimum)
1414
- Official Codex Desktop installed and launched at least once (`~/.codex/config.toml` exists)
1515
- No global Node.js install required (uses Codex’s signed bundled Node after validation)
1616

@@ -56,7 +56,7 @@ Install location after step 2:
5656
| State / logs / user images | `~/Library/Application Support/CodexDreamSkinStudio` |
5757
| Theme backup | under Application Support (`theme-backup.json`) |
5858

59-
## Legacy customer ZIP (optional packaging)
59+
## Legacy standalone ZIP (maintainer/offline packaging only)
6060

6161
To build the “double-click install” folder layout for non-git users:
6262

@@ -65,8 +65,11 @@ To build the “double-click install” folder layout for non-git users:
6565
```
6666

6767
That ZIP contains a visible installer plus a hidden `.codex-dream-skin-studio`
68-
engine. Prefer the DMG for new deliveries; keep this ZIP only for existing
69-
offline workflows. Do not ship only CSS/images.
68+
engine and is staged as a rights-clean package with only the redistributable
69+
Gothic Void Crusade preset. It is retained for existing offline workflows;
70+
prefer the DMG for ordinary users, and do not share a source checkout or an
71+
archive containing the excluded Arina reference files. Do not ship only
72+
CSS/images.
7073

7174
## How it works (security boundary)
7275

macos/menubar-app/Sources/CodexDreamSkinMenuBar/AppDelegate.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,18 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
150150
addDisabledItem("版本:v\(appVersion)")
151151

152152
menu.addItem(.separator())
153+
let busy = operationInFlight || engineInstallInFlight || snapshot.busy
153154
let needsEngineInstall = engineNeedsInstall()
154155
if engineInstallInFlight {
155156
addDisabledItem("正在安装引擎…")
156157
} else {
157158
addActionItem(
158159
needsEngineInstall ? "安装 / 升级引擎…" : "修复 / 重新安装引擎…",
159-
action: #selector(reinstallEngine)
160+
action: #selector(reinstallEngine),
161+
enabled: !busy
160162
)
161163
}
162164

163-
let busy = operationInFlight || engineInstallInFlight || snapshot.busy
164165
let applyTitle: String
165166
switch snapshot.session {
166167
case "active": applyTitle = "重新应用皮肤"
@@ -311,6 +312,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
311312
}
312313

313314
@objc private func reinstallEngine() {
315+
guard !operationInFlight, !snapshot.busy else { return }
314316
installBundledEngineIfNeeded(force: true)
315317
}
316318

@@ -524,7 +526,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
524526
}
525527

526528
private func installBundledEngineIfNeeded(force: Bool) {
527-
guard !engineInstallInFlight else { return }
529+
guard !engineInstallInFlight, !operationInFlight, !snapshot.busy else { return }
528530
if !force && !engineNeedsInstall() { return }
529531
guard let bundledVersion = version(at: bundledEngineURL?.appendingPathComponent("VERSION")) else {
530532
showError(title: "安装资源损坏", message: "App 内的版本信息无效,请重新下载。")

macos/scripts/build-client-release.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/bin/bash
22

33
set -euo pipefail
4+
export LC_ALL=C
5+
export LANG=C
6+
export LC_CTYPE=C
47
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
58
VERSION="$(/usr/bin/tr -d '[:space:]' < "$ROOT/VERSION")"
69
OUTPUT="${1:-$HOME/Desktop/Codex 主题编辑器.zip}"
@@ -16,6 +19,7 @@ trap '/bin/rm -rf "$TMP"' EXIT
1619
--exclude '.DS_Store' \
1720
--exclude 'release/' \
1821
--exclude 'runtime/' \
22+
--exclude 'presets/preset-arina-hashimoto/' \
1923
"$ROOT/" "$ENGINE/"
2024

2125
# Keep the customer ZIP self-contained: bundle prompt docs and referenced
@@ -57,8 +61,13 @@ fi
5761
/bin/cp "$ROOT/CLIENT_DEPLOY_PROMPT.md" "$CLIENT_ROOT/给 Codex 的部署提示词.md"
5862
/bin/chmod 755 "$CLIENT_ROOT/安装 Codex 主题编辑器.command"
5963
/bin/chmod 755 "$ENGINE"/*.command "$ENGINE"/scripts/*.sh "$ENGINE"/tests/*.sh
60-
/usr/bin/xattr -cr "$CLIENT_ROOT"
6164
/usr/bin/find "$CLIENT_ROOT" -type f \( -name '.DS_Store' -o -name '._*' \) -delete
65+
[ ! -e "$ENGINE/presets/preset-arina-hashimoto" ] \
66+
|| { printf 'Restricted Arina preset entered the standalone ZIP.\n' >&2; exit 1; }
67+
if /usr/bin/find "$CLIENT_ROOT" -type f -name 'arina-hashimoto-*' -print -quit | /usr/bin/grep -q .; then
68+
printf 'Restricted Arina documentation asset entered the standalone ZIP.\n' >&2
69+
exit 1
70+
fi
6271
/bin/mkdir -p "$(dirname "$OUTPUT")"
6372
/bin/rm -f "$OUTPUT"
6473
COPYFILE_DISABLE=1 /usr/bin/ditto -c -k --keepParent --norsrc --noextattr "$CLIENT_ROOT" "$OUTPUT"

macos/scripts/build-menubar-app.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,17 @@ done
112112
/usr/bin/rsync -a "$ROOT/assets/" "$ENGINE/assets/"
113113
PUBLIC_PRESET="preset-gothic-void-crusade"
114114
PUBLIC_PRESET_SHA256="b76a7cbe2ff9d923846e931984d243a7ba1f25de8d190b5c6412c809c41aee42"
115+
PUBLIC_PRESET_THEME_SHA256="fd250dc6c0ec1eea724f59a86c7c126a6bd9b90798289483a00948d57e23e52e"
115116
[ -d "$ROOT/presets/$PUBLIC_PRESET" ] \
116117
|| { printf 'Public release preset missing: %s\n' "$PUBLIC_PRESET" >&2; exit 1; }
117118
actual_public_preset_sha256="$(LC_ALL=C /usr/bin/shasum -a 256 \
118119
"$ROOT/presets/$PUBLIC_PRESET/background.jpg" | /usr/bin/awk '{print $1}')"
119120
[ "$actual_public_preset_sha256" = "$PUBLIC_PRESET_SHA256" ] \
120121
|| { printf 'Reviewed public preset hash changed: %s\n' "$actual_public_preset_sha256" >&2; exit 1; }
122+
actual_public_preset_theme_sha256="$(LC_ALL=C /usr/bin/shasum -a 256 \
123+
"$ROOT/presets/$PUBLIC_PRESET/theme.json" | /usr/bin/awk '{print $1}')"
124+
[ "$actual_public_preset_theme_sha256" = "$PUBLIC_PRESET_THEME_SHA256" ] \
125+
|| { printf 'Reviewed public preset metadata hash changed: %s\n' "$actual_public_preset_theme_sha256" >&2; exit 1; }
121126
/bin/mkdir -p "$ENGINE/presets/$PUBLIC_PRESET"
122127
/usr/bin/rsync -a "$ROOT/presets/$PUBLIC_PRESET/" "$ENGINE/presets/$PUBLIC_PRESET/"
123128
/bin/cp "$ROOT/VERSION" "$ENGINE/VERSION"

macos/scripts/build-release.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#!/bin/bash
22

33
set -euo pipefail
4+
export LC_ALL=C
5+
export LANG=C
6+
export LC_CTYPE=C
47
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
58
VERSION="$(/usr/bin/tr -d '[:space:]' < "$ROOT/VERSION")"
69
RELEASE_DIR="$ROOT/release"
@@ -15,6 +18,7 @@ if [ "${1:-}" != "--skip-tests" ]; then "$ROOT/tests/run-tests.sh"; fi
1518
--exclude '.git/' \
1619
--exclude '.DS_Store' \
1720
--exclude 'release/' \
21+
--exclude 'presets/preset-arina-hashimoto/' \
1822
"$ROOT/" "$TMP/codex-dream-skin-studio/"
1923

2024
# The macOS tree is also published as a standalone ZIP. Bundle prompt guides
@@ -37,6 +41,12 @@ if [ -f "$PRESET_README" ]; then
3741
/bin/mv "$temporary" "$PRESET_README"
3842
fi
3943
/usr/bin/find "$TMP/codex-dream-skin-studio" -type f \( -name '.DS_Store' -o -name '._*' \) -delete
44+
[ ! -e "$TMP/codex-dream-skin-studio/presets/preset-arina-hashimoto" ] \
45+
|| { printf 'Restricted Arina preset entered the standalone ZIP.\n' >&2; exit 1; }
46+
if /usr/bin/find "$TMP/codex-dream-skin-studio" -type f -name 'arina-hashimoto-*' -print -quit | /usr/bin/grep -q .; then
47+
printf 'Restricted Arina documentation asset entered the standalone ZIP.\n' >&2
48+
exit 1
49+
fi
4050
/bin/chmod 755 "$TMP/codex-dream-skin-studio"/*.command
4151
/bin/chmod 755 "$TMP/codex-dream-skin-studio"/scripts/*.sh "$TMP/codex-dream-skin-studio"/tests/*.sh
4252
/bin/rm -f "$ARCHIVE"

macos/scripts/install-dream-skin-macos.sh

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,48 @@ deploy_project() {
3131
--exclude 'runtime/' \
3232
"$PROJECT_ROOT/" "$temporary/"
3333
/bin/chmod 700 "$temporary"/*.command "$temporary"/scripts/*.sh 2>/dev/null || true
34+
/bin/rm -rf "$previous"
3435
if [ -e "$INSTALL_ROOT" ]; then /bin/mv "$INSTALL_ROOT" "$previous"; fi
3536
if ! /bin/mv "$temporary" "$INSTALL_ROOT"; then
3637
[ -e "$previous" ] && /bin/mv "$previous" "$INSTALL_ROOT"
3738
fail "Could not install the project at $INSTALL_ROOT"
3839
fi
39-
/bin/rm -rf "$previous"
40+
DEPLOY_PREVIOUS="$previous"
4041
}
4142

43+
commit_deployed_project() {
44+
[ -n "${DEPLOY_PREVIOUS:-}" ] || return 0
45+
/bin/rm -rf "$DEPLOY_PREVIOUS" || true
46+
DEPLOY_PREVIOUS=""
47+
}
48+
49+
rollback_deployed_project() {
50+
local status="$1"
51+
/bin/rm -rf "$INSTALL_ROOT"
52+
if [ -n "${DEPLOY_PREVIOUS:-}" ] && [ -e "$DEPLOY_PREVIOUS" ]; then
53+
/bin/mv "$DEPLOY_PREVIOUS" "$INSTALL_ROOT" \
54+
|| fail "Installation failed and the previous engine could not be restored."
55+
fi
56+
DEPLOY_PREVIOUS=""
57+
return "$status"
58+
}
59+
60+
DEPLOY_PREVIOUS=""
61+
4262
if [ "$IN_PLACE" = "false" ] && [ "$PROJECT_ROOT" != "$INSTALL_ROOT" ]; then
4363
/bin/mkdir -p "$(dirname "$INSTALL_ROOT")"
4464
deploy_project
4565
install_args=(--in-place --port "$PORT")
4666
[ "$CREATE_LAUNCHERS" = "true" ] || install_args+=(--no-launchers)
4767
[ "$LAUNCH_AFTER_INSTALL" = "true" ] || install_args+=(--no-launch)
48-
exec "$INSTALL_ROOT/scripts/install-dream-skin-macos.sh" "${install_args[@]}"
68+
if "$INSTALL_ROOT/scripts/install-dream-skin-macos.sh" "${install_args[@]}"; then
69+
commit_deployed_project
70+
exit 0
71+
else
72+
status=$?
73+
rollback_deployed_project "$status"
74+
exit "$status"
75+
fi
4976
fi
5077

5178
discover_codex_app

0 commit comments

Comments
 (0)