Skip to content

Commit 53ad1bf

Browse files
committed
feat(release): complete one-click desktop distribution
1 parent 77b7521 commit 53ad1bf

49 files changed

Lines changed: 2424 additions & 249 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/CONTRIBUTING.en.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ For injection, CSS, launch, or restore changes, also run `macos/scripts/verify-d
5050
Run the Windows regression suite:
5151

5252
```powershell
53-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\windows\tests\run-tests.ps1
53+
powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File .\windows\tests\run-tests.ps1
5454
```
5555

5656
For install, launch, injection, or restore changes, exercise the affected scripts and `windows/scripts/verify-dream-skin.ps1`. Include the Windows version and Codex source in the pull request.

.github/CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ macos/scripts/doctor-macos.sh
5050
运行 Windows 回归测试:
5151

5252
```powershell
53-
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\windows\tests\run-tests.ps1
53+
powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File .\windows\tests\run-tests.ps1
5454
```
5555

5656
改动安装、启动、注入或恢复流程时,请运行对应脚本和 `windows/scripts/verify-dream-skin.ps1`,并在 PR 中注明 Windows 版本与 Codex 来源。

.github/workflows/ci.yml

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ jobs:
1818
name: Static checks
1919
runs-on: ubuntu-latest
2020
steps:
21-
- uses: actions/checkout@v4
22-
- uses: actions/setup-node@v4
21+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
22+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
2323
with:
2424
node-version: "22"
2525

@@ -79,6 +79,11 @@ jobs:
7979
printf 'A runtime script appears to mutate app.asar.\n' >&2
8080
exit 1
8181
fi
82+
if grep -R -n --include='*.ps1' --include='*.iss' \
83+
-F -- '-ExecutionPolicy Bypass' windows/scripts windows/installer >/dev/null; then
84+
printf 'Windows runtime or installer code bypasses the PowerShell execution policy.\n' >&2
85+
exit 1
86+
fi
8287
if grep -n -E '/usr/bin/python3|(^|[[:space:]])eval([[:space:]]|$)' \
8388
macos/scripts/common-macos.sh >/dev/null; then
8489
printf 'The macOS runtime must parse state without python3 or eval.\n' >&2
@@ -89,10 +94,14 @@ jobs:
8994
shell: bash
9095
run: |
9196
expected="$(tr -d '\r\n' < macos/VERSION)"
97+
windows_version="$(tr -d '\r\n' < windows/VERSION)"
98+
package_version="$(node -p "JSON.parse(require('fs').readFileSync('macos/package.json','utf8')).version")"
9299
common="$(sed -n 's/^SKIN_VERSION="\([^"]*\)"$/\1/p' macos/scripts/common-macos.sh)"
93100
macos_injector="$(sed -n 's/^const SKIN_VERSION = "\([^"]*\)";$/\1/p' macos/scripts/injector.mjs)"
94101
windows_injector="$(sed -n 's/^const SKIN_VERSION = "\([^"]*\)";$/\1/p' windows/scripts/injector.mjs)"
95102
test -n "$expected"
103+
test "$windows_version" = "$expected"
104+
test "$package_version" = "$expected"
96105
test "$common" = "$expected"
97106
test "$macos_injector" = "$expected"
98107
test "$windows_injector" = "$expected"
@@ -117,21 +126,56 @@ jobs:
117126
- name: PowerShell 7
118127
executable: pwsh.exe
119128
steps:
120-
- uses: actions/checkout@v4
121-
- uses: actions/setup-node@v4
129+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
130+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
122131
with:
123132
node-version: "22"
124133

125134
- name: Run Windows regression suite
126135
shell: cmd
127-
run: ${{ matrix.executable }} -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\windows\tests\run-tests.ps1
136+
run: ${{ matrix.executable }} -NoLogo -NoProfile -ExecutionPolicy RemoteSigned -File .\windows\tests\run-tests.ps1
137+
138+
- name: Run Windows installer static checks
139+
shell: cmd
140+
run: ${{ matrix.executable }} -NoLogo -NoProfile -ExecutionPolicy RemoteSigned -File .\windows\tests\installer-static.tests.ps1
141+
142+
- name: Install pinned Inno Setup
143+
if: matrix.executable == 'powershell.exe'
144+
shell: pwsh
145+
run: |
146+
$requiredVersion = '6.7.1'
147+
choco upgrade innosetup --version=$requiredVersion --allow-downgrade --no-progress --yes
148+
if ($LASTEXITCODE -ne 0) { throw "Could not install Inno Setup $requiredVersion." }
149+
$iscc = Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 6\ISCC.exe'
150+
if (-not (Test-Path -LiteralPath $iscc -PathType Leaf)) { throw 'ISCC.exe is missing.' }
151+
$actual = "$((Get-Item -LiteralPath $iscc).VersionInfo.ProductVersion)"
152+
if (-not $actual.StartsWith($requiredVersion, [System.StringComparison]::Ordinal)) {
153+
throw "Expected Inno Setup $requiredVersion, found $actual."
154+
}
155+
"ISCC_PATH=$iscc" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
156+
157+
- name: Compile Windows Setup.exe
158+
if: matrix.executable == 'powershell.exe'
159+
shell: pwsh
160+
run: |
161+
$output = Join-Path $env:RUNNER_TEMP 'codex-dream-skin-ci-installer'
162+
& powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
163+
-File .\windows\installer\build-release.ps1 `
164+
-OutputDirectory $output -IsccPath $env:ISCC_PATH
165+
if ($LASTEXITCODE -ne 0) { throw "Windows release builder failed with exit code $LASTEXITCODE." }
166+
$version = [System.IO.File]::ReadAllText((Resolve-Path .\windows\VERSION)).Trim()
167+
$artifact = Join-Path $output "CodexDreamSkin-Setup-v$version.exe"
168+
if (-not (Test-Path -LiteralPath $artifact -PathType Leaf) -or
169+
(Get-Item -LiteralPath $artifact).Length -le 0) {
170+
throw 'Windows installer artifact is missing or empty.'
171+
}
128172
129173
macos-tests:
130174
name: macOS repository regressions
131175
runs-on: macos-latest
132176
steps:
133-
- uses: actions/checkout@v4
134-
- uses: actions/setup-node@v4
177+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
178+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
135179
with:
136180
node-version: "22"
137181

@@ -147,3 +191,9 @@ jobs:
147191
CODEX_DREAM_SKIN_SKIP_SIGNED_RUNTIME_TESTS: "1"
148192
CODEX_DREAM_SKIN_SKIP_DOCTOR: "1"
149193
run: ./macos/tests/run-tests.sh
194+
195+
- name: Build and test the native menu bar app
196+
run: swift test --package-path macos/menubar-app
197+
198+
- name: Compile and verify the universal DMG
199+
run: ./macos/scripts/build-dmg.sh --skip-tests

.github/workflows/release.yml

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ jobs:
2020
version: ${{ steps.version.outputs.version }}
2121
steps:
2222
- name: Check out source
23-
uses: actions/checkout@v4
23+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
24+
with:
25+
fetch-depth: 0
2426

2527
- name: Set up Node.js for manifest checks
26-
uses: actions/setup-node@v4
28+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
2729
with:
2830
node-version: '22'
2931

@@ -39,6 +41,12 @@ jobs:
3941
echo "Release tags must look like v1.2.3: $tag" >&2
4042
exit 1
4143
fi
44+
main_sha="$(git rev-parse origin/main)"
45+
tag_sha="$(git rev-parse HEAD)"
46+
if [[ "$tag_sha" != "$main_sha" ]]; then
47+
echo "Release tag must point at the current origin/main commit: tag=$tag_sha main=$main_sha" >&2
48+
exit 1
49+
fi
4250
version="$(tr -d '[:space:]' < macos/VERSION)"
4351
windows_version="$(tr -d '[:space:]' < windows/VERSION)"
4452
package_version="$(node -p "JSON.parse(require('fs').readFileSync('macos/package.json', 'utf8')).version")"
@@ -60,7 +68,12 @@ jobs:
6068
runs-on: macos-latest
6169
steps:
6270
- name: Check out source
63-
uses: actions/checkout@v4
71+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
72+
73+
- name: Set up Node.js for macOS regressions
74+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
75+
with:
76+
node-version: '22'
6477

6578
- name: Build unsigned DMG
6679
shell: bash
@@ -82,7 +95,7 @@ jobs:
8295
hdiutil imageinfo "$artifact" >/dev/null
8396
8497
- name: Upload macOS artifact
85-
uses: actions/upload-artifact@v4
98+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
8699
with:
87100
name: release-macos
88101
if-no-files-found: error
@@ -95,32 +108,45 @@ jobs:
95108
runs-on: windows-latest
96109
steps:
97110
- name: Check out source
98-
uses: actions/checkout@v4
111+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
112+
113+
- name: Set up Node.js for Windows regressions
114+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
115+
with:
116+
node-version: '22'
99117

100118
- name: Install Inno Setup 6
101119
shell: pwsh
102120
run: |
121+
$requiredVersion = '6.7.1'
103122
$iscc = Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 6\ISCC.exe'
104-
if (-not (Test-Path -LiteralPath $iscc -PathType Leaf)) {
105-
choco install innosetup --no-progress --yes
123+
$installedVersion = if (Test-Path -LiteralPath $iscc -PathType Leaf) {
124+
"$((Get-Item -LiteralPath $iscc).VersionInfo.ProductVersion)"
125+
} else { '' }
126+
if (-not $installedVersion.StartsWith($requiredVersion, [System.StringComparison]::Ordinal)) {
127+
choco upgrade innosetup --version=$requiredVersion --allow-downgrade --no-progress --yes
128+
if ($LASTEXITCODE -ne 0) { throw "Could not install Inno Setup $requiredVersion." }
106129
}
107-
$resolved = Get-Command ISCC.exe -ErrorAction SilentlyContinue
108-
if ($null -eq $resolved) {
109-
$known = @(
110-
(Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 6\ISCC.exe'),
111-
(Join-Path $env:ProgramFiles 'Inno Setup 6\ISCC.exe')
112-
) | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf }
113-
if ($known.Count -eq 0) { throw 'Inno Setup 6 (ISCC.exe) is not available on the runner.' }
114-
"ISCC_PATH=$($known[0])" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
115-
} else {
116-
"ISCC_PATH=$($resolved.Source)" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
130+
$resolved = @(
131+
(Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 6\ISCC.exe'),
132+
(Join-Path $env:ProgramFiles 'Inno Setup 6\ISCC.exe'),
133+
(Get-Command ISCC.exe -ErrorAction SilentlyContinue).Source
134+
) | Where-Object { $_ -and (Test-Path -LiteralPath $_ -PathType Leaf) } | Select-Object -First 1
135+
if (-not $resolved) { throw 'Inno Setup 6 (ISCC.exe) is not available on the runner.' }
136+
$resolvedVersion = "$((Get-Item -LiteralPath $resolved).VersionInfo.ProductVersion)"
137+
if (-not $resolvedVersion.StartsWith($requiredVersion, [System.StringComparison]::Ordinal)) {
138+
throw "Expected Inno Setup $requiredVersion, found $resolvedVersion at $resolved."
117139
}
140+
"ISCC_PATH=$resolved" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
118141
119142
- name: Build Setup.exe with pinned Node runtime
120143
shell: pwsh
121144
env:
122145
VERSION: ${{ needs.guard.outputs.version }}
123146
run: |
147+
& powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
148+
-File .\windows\tests\run-tests.ps1
149+
if ($LASTEXITCODE -ne 0) { throw "Windows regressions failed with exit code $LASTEXITCODE." }
124150
& powershell.exe -NoLogo -NoProfile -ExecutionPolicy RemoteSigned `
125151
-File .\windows\tests\installer-static.tests.ps1
126152
if ($LASTEXITCODE -ne 0) { throw "Installer static checks failed with exit code $LASTEXITCODE." }
@@ -137,7 +163,7 @@ jobs:
137163
if ((Get-Item -LiteralPath $artifact).Length -le 0) { throw 'Windows artifact is empty.' }
138164
139165
- name: Upload Windows artifact
140-
uses: actions/upload-artifact@v4
166+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
141167
with:
142168
name: release-windows
143169
if-no-files-found: error
@@ -152,10 +178,10 @@ jobs:
152178
contents: write
153179
steps:
154180
- name: Check out source
155-
uses: actions/checkout@v4
181+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
156182

157183
- name: Download release artifacts
158-
uses: actions/download-artifact@v4
184+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
159185
with:
160186
pattern: release-*
161187
path: dist
@@ -171,8 +197,8 @@ jobs:
171197
test -s "dist/CodexDreamSkin-Setup-v${VERSION}.exe"
172198
(
173199
cd dist
174-
sha256sum "CodexDreamSkin-v${VERSION}.dmg" "CodexDreamSkin-Setup-v${VERSION}.exe" \
175-
| sed 's# # #' > SHA256SUMS.txt
200+
sha256sum "CodexDreamSkin-v${VERSION}.dmg" \
201+
"CodexDreamSkin-Setup-v${VERSION}.exe" > SHA256SUMS.txt
176202
)
177203
cat > release-notes.md <<EOF
178204
## Codex Dream Skin v${VERSION}
@@ -184,8 +210,8 @@ jobs:
184210
- [SHA256SUMS.txt](https://github.com/Fei-Away/Codex-Dream-Skin/releases/download/v${VERSION}/SHA256SUMS.txt)
185211
186212
The packages are currently unsigned. Follow the graphical first-run steps in
187-
[macOS installation](https://github.com/Fei-Away/Codex-Dream-Skin/blob/main/docs/install-macos.md)
188-
or [Windows installation](https://github.com/Fei-Away/Codex-Dream-Skin/blob/main/docs/install-windows.md).
213+
[macOS installation](https://github.com/Fei-Away/Codex-Dream-Skin/blob/v${VERSION}/docs/install-macos.md)
214+
or [Windows installation](https://github.com/Fei-Away/Codex-Dream-Skin/blob/v${VERSION}/docs/install-windows.md).
189215
No terminal trust command is required for ordinary users.
190216
191217
This release is created as a draft for a maintainer to review before publishing.
@@ -196,10 +222,25 @@ jobs:
196222
GH_TOKEN: ${{ github.token }}
197223
VERSION: ${{ needs.guard.outputs.version }}
198224
run: |
199-
gh release create "v${VERSION}" \
200-
--draft \
201-
--title "Codex Dream Skin v${VERSION}" \
202-
--notes-file release-notes.md \
203-
dist/CodexDreamSkin-v${VERSION}.dmg \
204-
dist/CodexDreamSkin-Setup-v${VERSION}.exe \
205-
dist/SHA256SUMS.txt
225+
if gh release view "v${VERSION}" >/dev/null 2>&1; then
226+
is_draft="$(gh release view "v${VERSION}" --json isDraft --jq .isDraft)"
227+
test "$is_draft" = true || {
228+
echo "Refusing to replace an already published v${VERSION} release." >&2
229+
exit 1
230+
}
231+
gh release upload "v${VERSION}" --clobber \
232+
dist/CodexDreamSkin-v${VERSION}.dmg \
233+
dist/CodexDreamSkin-Setup-v${VERSION}.exe \
234+
dist/SHA256SUMS.txt
235+
gh release edit "v${VERSION}" --draft \
236+
--title "Codex Dream Skin v${VERSION}" \
237+
--notes-file release-notes.md
238+
else
239+
gh release create "v${VERSION}" \
240+
--draft \
241+
--title "Codex Dream Skin v${VERSION}" \
242+
--notes-file release-notes.md \
243+
dist/CodexDreamSkin-v${VERSION}.dmg \
244+
dist/CodexDreamSkin-Setup-v${VERSION}.exe \
245+
dist/SHA256SUMS.txt
246+
fi

README.en.md

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@
1717
Unofficial. Does not modify <code>.app</code> / <code>app.asar</code> / WindowsApps.
1818
</p>
1919

20+
## Install directly
21+
22+
Ordinary users first install and quit the official Codex / ChatGPT app once,
23+
then download from [GitHub Releases](https://github.com/Fei-Away/Codex-Dream-Skin/releases):
24+
25+
- macOS: open `CodexDreamSkin-vX.Y.Z.dmg` and drag the app to Applications.
26+
- Windows: run `CodexDreamSkin-Setup-vX.Y.Z.exe` and follow the wizard.
27+
28+
No source checkout, Node.js install, `.sh`, or `.ps1` command is required. See
29+
the [macOS guide](./docs/install-macos.md) or
30+
[Windows guide](./docs/install-windows.md) for unsigned first-run approval,
31+
updates, and uninstall steps.
32+
2033
## Sponsors
2134

2235
<p align="center">
@@ -53,12 +66,7 @@
5366
<sub>Real injected Codex home screen (preview only)</sub>
5467
</p>
5568

56-
After installing on macOS, switch from **已保存主题** or run:
57-
58-
```bash
59-
~/.codex/codex-dream-skin-studio/scripts/switch-theme-macos.sh \
60-
--id preset-gothic-void-crusade
61-
```
69+
After installing on macOS, switch directly from **Saved Themes** in the menu bar.
6270

6371
### Arina Hashimoto / 桥本有菜
6472

@@ -79,28 +87,13 @@ shown below are native Codex controls.
7987
<sub>Dark · real injected screenshot; unsent input hidden during capture (preview only)</sub>
8088
</p>
8189

82-
Install from the repo and switch in one command on macOS:
83-
84-
```bash
85-
cd macos
86-
./scripts/install-dream-skin-macos.sh --no-launch
87-
~/.codex/codex-dream-skin-studio/scripts/switch-theme-macos.sh \
88-
--id preset-arina-hashimoto
89-
```
90-
91-
Windows has a persistent local theme store and system-tray controls, and seeds
92-
the same Arina Hashimoto preset. For the first repo-based setup:
93-
94-
```powershell
95-
powershell -ExecutionPolicy Bypass -File .\windows\scripts\install-dream-skin.ps1
96-
powershell -ExecutionPolicy Bypass -File .\windows\scripts\start-dream-skin.ps1
97-
```
98-
99-
After launch, switch directly through **已保存主题 → 桥本有菜**; no cross-folder
100-
manual import is required. **更换背景图** still imports your own UI-free
101-
wallpaper, which can then be saved for one-click switching.
90+
This portrait material remains in the source repository for reference and
91+
rights review; it is excluded from public DMG and Setup.exe assets. Public
92+
installers seed only the redistributable Gothic Void Crusade preset. Users can
93+
still choose **Change Background** to import UI-free artwork they are entitled
94+
to use and save it for one-click switching.
10295

103-
> The downloadable user source is [`docs/images/presets/arina-hashimoto-source.png`](./docs/images/presets/arina-hashimoto-source.png) (`1672 × 941`); the macOS one-click preset uses the normalized derived [`background.jpg`](./macos/presets/preset-arina-hashimoto/background.jpg) (`2560 × 1440`). Do not import either screenshot above: they contain real UI and are previews only. The background is a user-provided AI-generated example, not an official OpenAI/Codex visual or endorsement; confirm likeness and asset rights before redistributing it.
96+
> The downloadable user source is [`docs/images/presets/arina-hashimoto-source.png`](./docs/images/presets/arina-hashimoto-source.png) (`1672 × 941`); the source-only reference preset uses the normalized derived [`background.jpg`](./macos/presets/preset-arina-hashimoto/background.jpg) (`2560 × 1440`). Do not import either screenshot above: they contain real UI and are previews only. The background is a user-provided AI-generated example, not an official OpenAI/Codex visual or endorsement; do not put it in a public installer without confirmed likeness and asset rights.
10497
10598
## Concept gallery (not importable backgrounds)
10699

0 commit comments

Comments
 (0)