-
Notifications
You must be signed in to change notification settings - Fork 0
CI: launch the built .app to prove it opens; rewrite the install guide #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,92 +1,162 @@ | ||
| name: Build | ||
|
|
||
| on: | ||
| push: | ||
| branches: ["main"] | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| # No job here creates releases, publishes packages, or writes via the API. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| # The engine has no UI imports, so it tests without a display. | ||
| - run: pip install Pillow piexif | ||
| - run: python tests/test_engine.py | ||
|
|
||
| smoke: | ||
| needs: test | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| os: [macos-14, windows-latest] | ||
| runs-on: ${{ matrix.os }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| - run: pip install -r requirements.txt | ||
| # Proves the GUI actually constructs on this OS — imports, fonts, theme | ||
| # tokens, widget options — rather than only that the engine passes. | ||
| - run: python main.py --check | ||
| - run: python tests/test_gui_boot.py | ||
|
|
||
| macos-app: | ||
| needs: smoke | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| # py2app bundles the running interpreter, so a single runner produces | ||
| # a single-arch app that will not launch on the other kind of Mac. | ||
| # macos-15-intel is the current Intel label; macos-13 was retired and | ||
| # a job targeting it queues forever instead of failing. | ||
| - runner: macos-15-intel | ||
| arch: intel | ||
| - runner: macos-14 | ||
| arch: apple-silicon | ||
| runs-on: ${{ matrix.runner }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| - run: | | ||
| pip install -r requirements.txt | ||
| pip install py2app | ||
| # v1's workflow cd'd into a folder that was never in the repo, so this | ||
| # job had never once produced a bundle. | ||
| - run: python setup.py py2app | ||
| - name: Verify the bundle launches | ||
| run: | | ||
| APP="dist/WebP Studio.app" | ||
| test -d "$APP" || { echo "no bundle produced"; exit 1; } | ||
| file "$APP/Contents/MacOS/WebP Studio" | ||
| # Headless runners have no window server, so a full launch can't be | ||
| # tested here — confirm the embedded interpreter starts and imports. | ||
| "$APP/Contents/MacOS/WebP Studio" --check | ||
| - run: ditto -c -k --keepParent "dist/WebP Studio.app" "WebP-Studio-macOS-${{ matrix.arch }}.zip" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: WebP-Studio-macOS-${{ matrix.arch }} | ||
| path: WebP-Studio-macOS-${{ matrix.arch }}.zip | ||
| retention-days: 14 | ||
|
|
||
| name: Build | ||
|
|
||
| on: | ||
| push: | ||
| branches: ["main"] | ||
| pull_request: | ||
| workflow_dispatch: | ||
|
|
||
| # No job here creates releases, publishes packages, or writes via the API. | ||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| # The engine has no UI imports, so it tests without a display. | ||
| - run: pip install Pillow piexif | ||
| - run: python tests/test_engine.py | ||
|
|
||
| smoke: | ||
| needs: test | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| os: [macos-14, windows-latest] | ||
| runs-on: ${{ matrix.os }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| - run: pip install -r requirements.txt | ||
| # Proves the GUI actually constructs on this OS — imports, fonts, theme | ||
| # tokens, widget options — rather than only that the engine passes. | ||
| - run: python main.py --check | ||
| - run: python tests/test_gui_boot.py | ||
|
|
||
| macos-app: | ||
| needs: smoke | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| include: | ||
| # py2app bundles the running interpreter, so a single runner produces | ||
| # a single-arch app that will not launch on the other kind of Mac. | ||
| # macos-15-intel is the current Intel label; macos-13 was retired and | ||
| # a job targeting it queues forever instead of failing. | ||
| - runner: macos-15-intel | ||
| arch: intel | ||
| expect_arch: x86_64 | ||
| - runner: macos-14 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: printf '%s\n' '--- build.yml ---'
sed -n '1,75p' .github/workflows/build.yml
printf '%s\n' '--- release.yml ---'
sed -n '1,35p' .github/workflows/release.ymlRepository: DhakadG/ConvertImagesToWebP-MacApp Length of output: 3630 🌐 Web query:
💡 Result: The macOS 14 runner images (both x64 and arm64) in GitHub Actions are currently in the process of deprecation [1][2]. The deprecation period began on July 6, 2026, and these images will reach their end-of-support date on November 2, 2026 [1][3]. After November 2, 2026, these images will no longer be supported by GitHub Actions or Azure DevOps [1][2]. Users are encouraged to migrate their workflows to newer, supported macOS runner images. Newer versions, such as macOS 15 and macOS 26, are available and include support for arm64 architectures [3][4][5]. You can update your workflow configuration by changing the Citations:
Replace the retiring Apple Silicon runner.
📍 Affects 2 files
🤖 Prompt for AI Agents |
||
| arch: apple-silicon | ||
| expect_arch: arm64 | ||
| runs-on: ${{ matrix.runner }} | ||
| steps: | ||
| - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 | ||
| with: | ||
| persist-credentials: false | ||
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | ||
| with: | ||
| python-version: "3.12" | ||
| cache: pip | ||
| - run: | | ||
| pip install -r requirements.txt | ||
| pip install py2app | ||
| # v1's workflow cd'd into a folder that was never in the repo, so this | ||
| # job had never once produced a bundle. | ||
| - run: python setup.py py2app | ||
| - name: Inspect the bundle | ||
| run: | | ||
| set -euo pipefail | ||
| APP="dist/WebP Studio.app" | ||
| BIN="$APP/Contents/MacOS/WebP Studio" | ||
| test -d "$APP" || { echo "::error::py2app produced no bundle"; exit 1; } | ||
|
|
||
| # Checking the launcher stub proves nothing: setup-python ships a | ||
| # universal2 CPython, so the stub, the framework and _tkinter.so all | ||
| # report "x86_64 arm64" on every runner. The binaries that decide | ||
| # portability are the pip-installed wheels, which are single-arch. | ||
| PILC=$(find "$APP/Contents/Resources" -name '_imaging.cpython-*-darwin.so' -print -quit) | ||
| test -n "$PILC" || { echo "::error::Pillow's _imaging module is not in the bundle"; exit 1; } | ||
| archs=$(lipo -archs "$PILC") | ||
| echo "Pillow _imaging architectures: $archs" | ||
| case "$archs" in | ||
| *${{ matrix.expect_arch }}*) ;; | ||
| *) echo "::error::expected ${{ matrix.expect_arch }}, got $archs"; exit 1 ;; | ||
| esac | ||
|
|
||
| # tkinterdnd2 ships one tkdnd build per platform. py2app copying only | ||
| # the .tcl files and leaving the macOS .dylib behind would disable | ||
| # drag & drop in the bundle — and the app catches that failure and | ||
| # carries on, so it would never surface as an error. | ||
| if [ -z "$(find "$APP/Contents/Resources" -path '*tkdnd/osx-*' -name '*.dylib' -print -quit)" ]; then | ||
| echo "::error::macOS tkdnd library missing — drag & drop would be dead in the bundle" | ||
| exit 1 | ||
| fi | ||
|
|
||
| # CustomTkinter reads its theme JSON from inside its own package the | ||
| # first time a widget is built. If py2app leaves those out, the app | ||
| # imports cleanly and then dies the instant a window opens — which is | ||
| # exactly the failure `--check` alone cannot see. | ||
| if [ -z "$(find "$APP/Contents/Resources" -path '*customtkinter*' -name '*.json' -print -quit)" ]; then | ||
| echo "::error::CustomTkinter theme assets missing from the bundle" | ||
| exit 1 | ||
| fi | ||
|
|
||
| "$BIN" --check | ||
|
|
||
| - name: Launch it and prove a window actually opens | ||
| run: | | ||
| APP="dist/WebP Studio.app" | ||
| BIN="$APP/Contents/MacOS/WebP Studio" | ||
|
|
||
| # `--check` only proves the interpreter imports. This is the step that | ||
| # would have caught a bundle that builds green and dies on double-click. | ||
| "$BIN" > launch.log 2>&1 & | ||
| PID=$! | ||
| sleep 25 | ||
|
|
||
| if ! kill -0 "$PID" 2>/dev/null; then | ||
| echo "::error::the app exited on its own — it crashed during startup" | ||
| echo "--- output ---"; cat launch.log | ||
| exit 1 | ||
| fi | ||
|
Comment on lines
+130
to
+135
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The gate accepts any process that remains alive, including an application whose event loop runs with a blank, unmapped, off-screen, or unusable window. The screenshot is best-effort and unvalidated, so such a bundle passes CI and the equivalent release check allows it to be published. Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time! |
||
|
|
||
| echo "still running after 25s" | ||
| screencapture -x window.png 2>/dev/null || echo "(no screencapture on this runner)" | ||
| kill "$PID" 2>/dev/null || true | ||
| wait "$PID" 2>/dev/null || true | ||
| echo "--- output ---"; cat launch.log | ||
|
|
||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| if: always() | ||
| with: | ||
| name: launch-proof-${{ matrix.arch }} | ||
| path: | | ||
| window.png | ||
| launch.log | ||
| retention-days: 14 | ||
| if-no-files-found: ignore | ||
|
|
||
| - run: ditto -c -k --keepParent "dist/WebP Studio.app" "WebP-Studio-macOS-${{ matrix.arch }}.zip" | ||
| - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | ||
| with: | ||
| name: WebP-Studio-macOS-${{ matrix.arch }} | ||
| path: WebP-Studio-macOS-${{ matrix.arch }}.zip | ||
| # 14 days meant every build quietly disappeared and the download | ||
| # links in the README led to nothing. Tagged releases are the | ||
| # permanent copy; this is the ceiling GitHub allows for artifacts. | ||
| retention-days: 90 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Normalize workflow line endings to LF.
YAMLlint reports
wrong new line character: expected \nfor both workflow files. Convert the files to LF line endings so the YAML lint check does not report an error..github/workflows/build.yml#L1-L1: convert the file to LF line endings..github/workflows/release.yml#L1-L1: convert the file to LF line endings.🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 1-1: wrong new line character: expected \n
(new-lines)
📍 Affects 2 files
.github/workflows/build.yml#L1-L1(this comment).github/workflows/release.yml#L1-L1🤖 Prompt for AI Agents
Source: Linters/SAST tools