Repository navigation
Add a proper macOS application icon - #158
Conversation
axisrow
left a comment
There was a problem hiding this comment.
Reviewed 06a67f2..9975b24 (1 commit, 9 files, +112 lines plus two icon binaries). Approving: I am not requesting changes. Rust application code and dependencies are untouched, so the unrun cargo checks carry no risk here and CI covers them.
What I checked
- Asset policy (AGENTS.md §1): the artwork is contributor-original (AI-assisted, made for this contribution, MPL-2.0), recorded in ATTRIBUTION.md with source, licence and use. Nothing from Tekla/Trimble or any third party, no brand-logo licence touched. The diff is +112 text lines plus the two admitted binaries, within the project limits.
- Bundle wiring end to end: Info.plist gains CFBundleIconFile=BeamCraft.icns; package.sh copies the ICNS into Contents/Resources before ad-hoc signing; the release smoke on the macOS runner verifies the plist value, decodes the packaged ICNS with iconutil and requires [email protected], then runs the CLI. The three layers agree.
- ICNS contents (parsed directly): valid container, total length exact, ten PNG elements whose widths are exactly the set the unit test asserts (16, 32, 64, 128, 256, 512, 1024; the 32/256/512 doubles are the @2x roles). The ic10 element is the committed 1024 source PNG byte for byte. I also decoded the committed ICNS with iconutil on macOS: it converts cleanly and [email protected] is present, so the release smoke step will pass. The icp6 element carries a 64 px payload under the 48 px nominal name, which is how iconutil itself labels the 32@2x role; harmless.
- packaging/test_package.py: the container test bounds every element length and guards the loop, the archive test copies exactly the inputs package.sh reads, the codesign stub receives the app path as its last argument, matching the one call site in package.sh, and the archive assertions check version, plist value and byte-identical icon. All files the test copies from the tree exist at the head commit. The extra Linux CI step runs before Package and is independent of the built artifacts.
- generate-icon.sh: bounded loop over the standard sizes, mktemp with a trap, regenerates a set that satisfies the same size assertion; the committed ICNS stays the packaging input so release builds need no image tools.
- Docs match the code (development.md, README wording); no ROADMAP edit in a feature PR.
Notes (no change requested)
- CFBundleIconFile with the .icns extension works; the more modern idiom is the bare name plus CFBundleIconName with an asset catalog, which this project does not use. No action needed.
- The two binaries add about 2.7 MB to the repository; consistent with the already admitted fonts, just worth knowing.
- When the archive test fails because package.sh refuses, the packer stderr is captured into the raised exception only; printing it on failure would make CI logs friendlier. Optional.
Native Finder/Dock appearance stays with the owner, as the PR itself states; nothing in the diff prevents it.
2a80f26 to
9f508d9
Compare
axisrow
left a comment
There was a problem hiding this comment.
Ревью PR #158 (head 2a80f26, база 06a67f2 = upstream/master): иконка macOS-бандла. Вердикт: approved, изменений не требуется.
Проверено:
- Провенанс: SHA-256 файлов в репо —
assets/icons/beamcraft-1024.png(184ec596…) иdocs/brand/beamcraft-logo.svg(4dc69950…) — совпадают с хешами вложений issue #164, записанными в ATTRIBUTION.md;docs/brand/LICENSE-brand.txtсуществует; обе новые строки ATTRIBUTION заполнены по форме соседних. - Механика:
package.shкопирует ICNS в Resources до ad-hoc подписи; стабcodesignв тесте корректен ("$app"действительно последний аргумент вызоваcodesign --force --deep --sign -); stdout-контракт package.sh (только путь архива) соблюдён, поэтомуresult.stdout.strip()как путь tar-архива корректен; префиксbeamcraft-v0.0.1-aarch64-apple-darwin/BeamCraft.app/Contents/совпадает сnameиз package.sh. - Парсер ICNS в
test_package.pyкорректен: magic и длина контейнера, IHDR-размеры PNG-элементов, защита от зацикливания (length >= 8), карта ic-типов покрывает стандартный вывод iconutil (включая сырые ARGB ic04/ic05 и info/toc); ожидаемое множество размеров {16…1024} согласовано со smoke-проверкой[email protected]в release.yml. - Исходный PNG квадратный 1024×1024, так что
sips -zв generate-icon.sh пропорции не искажает; бинарники закоммичены обычными blob 100644, ICNS коммитится чтобы релизной упаковке не нужны были image-инструменты — согласуется с docs/development.md. - release.yml: python-тест гейтится перед Package на Linux, macOS-smoke (PlistBuddy по CFBundleIconFile, iconutil-декод, проверка бинарников) идёт до запуска
--version— битый артефакт не соберётся и не уедет.
Не блокирует (без инлайнов):
python3 packaging/test_package.pyвыполняется только в release-воркфлоу, то есть впервые реально пройдёт на релизном теге (обычная CI-джобаtestего не вызывает). Логика теста дефектов не показала; при желании его можно дергать и в обычном CI.- Описание PR утверждает «one commit and exactly nine icon-related files», фактически 2 коммита и 11 файлов — косметика описания.
- Нативная проверка вида в Finder/Dock/app-switcher остаётся за владельцем, как прямо указано в описании PR (draft до нативной верификации).
axisrow
left a comment
There was a problem hiding this comment.
Ревью PR #158 (head d97f7a0, база 6fbedec = upstream/master): иконка macOS-бандла, теперь с Dock-иконкой на время работы процесса. Вердикт: approved, изменений не требуется. Ветка перебейзена на актуальный master и дополнилась коммитами «Keep the macOS Dock icon from the bundle» и «Show the official logo in the Dock while the app runs».
Новое с прошлого ревью — проверено:
app.rs::load_icon(): читаетContents/Resources/beamcraft-icon.pngотносительно exe, декодируетeframe::icon_data::from_png_bytes, на любой ошибке (нет exe-родителя, нет файла, битый PNG) падает на кодированныйicon()— never-crash соблюдён, unwraps нет, pub-функция документирована. Путь согласован с package.sh: exe лежит вContents/MacOS/, иконка копируется вContents/Resources/beamcraft-icon.png; вне бандла ресурс не существует, fallback закономерен.main.rs: механическая заменаicon()наload_icon()в ViewportBuilder.- Тест
the_icon_loader_falls_back_to_the_coded_icon: хардкод 32×32 валиден — кодированныйicon()именно 32×32 с 4096 байтами rgba; ресурса рядом с тестовым бинарем нет, так что тест проверяет именно ветку fallback. package.shкопирует PNG в бандл;test_package.pyпроверяет его байт-в-байт в архиве; docs/development.md описывает обе иконки (ICNS для Finder/Dock и PNG для рантайм-Dock).- ATTRIBUTION.md против базы добавляет только те же две строки логотипа; строка про патченный eframe — из базы (#151), не из этого PR; Cargo.toml/deny.toml PR не трогает.
Не блокирует (без инлайнов):
- Проверки
test (ubuntu-latest)иtest (windows-latest)на момент ревью ещё pending — рантайм-вызовeframe::icon_data::from_png_bytesвпервые скомпилируется именно там; API для eframe 0.36 стандартный, риск низкий. - Утверждение в доке, что работающий процесс показывает в Dock иконку процесса и игнорирует ICNS бандла, — эмпирика для запуска бинаря напрямую; решение через viewport-иконку корректно в обоих случаях и безвредно при обратном поведении.
- Нативная проверка вида в Finder/Dock/app-switcher, как и раньше, остаётся за владельцем (PR заявлен draft до нативной верификации).
axisrow
left a comment
There was a problem hiding this comment.
Финальное ревью PR #158 (head d97f7a0, база 6fbedec = upstream/master): иконка macOS-бандла. Вердикт: approved, изменений не требуется.
PR выведен из draft, код не менялся с предыдущих проходов ревью, CI полностью зелёный: ubuntu (8m36s, включая rustfmt/clippy и fallback-тест иконки), windows (10m50s), cargo deny, wasm32.
Итог по существу:
- Провенанс официального логотипа подтверждён хешами: SHA-256 committed assets/icons/beamcraft-1024.png (184ec596…) и docs/brand/beamcraft-logo.svg (4dc69950…) совпадают с вложениями issue #164, записанными в ATTRIBUTION.md; docs/brand/LICENSE-brand.txt существует; новые записи ATTRIBUTION против базы — только две строки логотипа (строка про патченный eframe — из базы #151).
- Never-crash соблюдён: app.rs::load_icon() при любом сбое (нет exe-родителя, нет ресурса, битый PNG) падает на кодированную 32x32 иконку; unwraps нет, pub-функция документирована.
- Проводка согласована end-to-end: package.sh кладёт ICNS и beamcraft-icon.png в Contents/Resources до ad-hoc подписи; test_package.py проверяет оба файла байт-в-байт в архиве (стаб codesign корректен, stdout-контракт package.sh соблюдён); release.yml гейтит python-тест перед Package и декодирует ICNS через iconutil в macOS-smoke.
- Рантайм-Dock-иконка через viewport-иконку корректна независимо от того, игнорирует ли Dock ICNS работающего процесса; вне бандла fallback закономерен.
- Парсер ICNS в test_package.py корректен (magic/длина контейнера, IHDR-размеры, защита от зацикливания, полная карта ic-типов), ожидаемое множество размеров согласовано со smoke-проверкой [email protected].
Не блокирует: python-тест исполняется только в release-воркфлоу (впервые реально пройдёт на релизном теге); нативная проверка вида в Finder/Dock/app-switcher — за владельцем, вывод PR из draft принят как сигнал её выполнения.
d97f7a0 to
ccd1de1
Compare
axisrow
left a comment
There was a problem hiding this comment.
Ревью PR #158 (head ccd1de1, база 6fbedec = upstream/master): иконка macOS-бандла. Вердикт: approved, изменений не требуется.
Ветка пересобрана в один squash-коммит «Add the macOS app icon: the official BeamCraft logo (#164)»; дерево байт-в-байт совпадает с ранее проверенным head d97f7a0 (git diff пуст), так что все прежние проверки остаются в силе:
- CI 4/4 зелёный на этом же дереве: ubuntu (rustfmt/clippy + fallback-тест иконки), windows, cargo deny, wasm32.
- Провенанс подтверждён хешами: SHA-256 committed assets/icons/beamcraft-1024.png (184ec596…) и docs/brand/beamcraft-logo.svg (4dc69950…) совпадают с вложениями issue #164 в ATTRIBUTION.md; docs/brand/LICENSE-brand.txt существует; против базы ATTRIBUTION добавляет только две строки логотипа.
- Never-crash: app.rs::load_icon() при любом сбое (нет exe-родителя, нет ресурса, битый PNG) падает на кодированную 32x32 иконку; unwraps нет; путь Contents/MacOS/../Resources/beamcraft-icon.png согласован с package.sh.
- Упаковка сквозная: package.sh копирует ICNS и beamcraft-icon.png до ad-hoc подписи; test_package.py сверяет оба файла байт-в-байт в архиве; release.yml гейтит python-тест перед Package и декодирует ICNS через iconutil в macOS-smoke; парсер ICNS корректен (magic/длина, IHDR, защита от зацикливания, карта ic-типов).
Не блокирует: python-тест исполняется только в release-воркфлоу (впервые пройдёт на релизном теге); нативная проверка вида в Finder/Dock/app-switcher — за владельцем, PR из draft выведен.
The macOS bundle had no CFBundleIconFile or bundled icon, so Finder and the Dock used a generic icon. Ship the official logo posted by the maintainer in issue #164: the unmodified 1024px PNG as the icon source, the official SVG in docs/brand/ shown at the top of the README, and an ICNS resampled from the PNG into the standard/Retina sizes (16-1024, packaging/generate-icon.sh, prebuilt so packaging needs no image tools). The icon carries the BeamCraft brand terms, not MPL-2.0; ATTRIBUTION.md records the issue, author and attachment hashes. While the app runs, the Dock paints the process icon and ignores the bundle's ICNS, so the bundle also ships the official PNG as Resources/beamcraft-icon.png and beamcraft-ui applies it at run time (eframe::icon_data::from_png_bytes), falling back to the coded I-section outside a bundle. packaging/test_package.py validates the icns container by element type (the current iconutil emits raw-ARGB ic04/ic05 plus an info chunk), requires every standard size, and checks both icon files land in the archive.
ccd1de1 to
5b6cecb
Compare
axisrow
left a comment
There was a problem hiding this comment.
Ревью PR #158 (head 5b6cecb, база a42b945 = upstream/master): иконка macOS-бандла. Вердикт: approved, изменений не требуется.
Ветка перебейзена на master после U17 (#165, удаление отдельного USD-воркера): в файлах PR это отразилось только ожидаемым образом — из packaging/package.sh, синтетики test_package.py и release-smoke ушли упоминания beamcraft-usd-worker; содержание самой иконки не изменилось и совпадает с ранее проверенными проходами:
- Провенанс подтверждён хешами: SHA-256 committed assets/icons/beamcraft-1024.png (184ec596…) и docs/brand/beamcraft-logo.svg (4dc69950…) совпадают с вложениями issue #164 в ATTRIBUTION.md; против базы добавляются только две строки логотипа.
- Never-crash: app.rs::load_icon() при любом сбое (нет exe-родителя, нет ресурса, битый PNG) падает на кодированную 32x32 иконку; unwraps нет; путь Contents/MacOS/../Resources/beamcraft-icon.png согласован с package.sh.
- Упаковка сквозная: package.sh копирует ICNS и beamcraft-icon.png в Resources до ad-hoc подписи; test_package.py сверяет оба файла байт-в-байт в архиве (список синтетики теперь без usd-worker — согласован с #165); release.yml гейтит python-тест перед Package и декодирует ICNS через iconutil в macOS-smoke; парсер ICNS корректен.
- На новом head cargo deny и wasm32 уже зелёные; cargo-джобы ubuntu/windows на момент ревью ещё гоняются, но содержание Rust-кода идентично прошлому полностью зелёному прогону (tree-level отличие — только удаление воркера из мастер-базы), риск минимален.
Не блокирует: python-тест исполняется только в release-воркфлоу (впервые пройдёт на релизном теге); нативная проверка вида в Finder/Dock/app-switcher — за владельцем.
Carried from axisrow/BeamCraft PR 50, rebased onto upstream master. Update 2026-10-21/22: rebased onto current master, the generated placeholder artwork is replaced with the official BeamCraft logo from #164, and the Dock shows it while the app runs.
Fixes #164
What this changes
The macOS bundle currently has no CFBundleIconFile or bundled app icon, so Finder and the Dock use a generic icon. Add an icon, a prebuilt ICNS with 16–1024 px standard/Retina representations, and copy it into Contents/Resources before ad-hoc signing. Add a native macOS regeneration script, release smoke decoding with iconutil, packaging regression tests, and documentation.
Update 2026-10-21/22: the maintainer posted the official project logo in #164, so the placeholder artwork is replaced with it:
assets/icons/beamcraft-1024.pngis the official 1024×1024 PNG attachment from Add required project logos #164 (unmodified; SHA-256 inATTRIBUTION.md);packaging/generate-icon.shresamples it into the standard/Retina ICNS sizes, and the committedBeamCraft.icnswas rebuilt with it.docs/brand/beamcraft-logo.svgand shown at the top ofREADME.md.docs/brand/LICENSE-brand.txt) instead of MPL-2.0 — forks must remove it, as the brand policy already requires.ATTRIBUTION.mdrecords the issue, author (Yuri Isachenkov (@Blogbotana)) and date for both attachments.setApplicationIconImage) and the Dock ignores a bundle-only ICNS for a running app, so the coded I-section used to hide the official logo. The bundle now ships the official PNG asContents/Resources/beamcraft-icon.png,beamcraft-uiloads it at run time (eframe::icon_data::from_png_bytes) and falls back to the coded icon outside a bundle (app::load_icon, unit-tested).packaging/test_package.pyvalidates the icns container by element type (the current macOSiconutilemits raw-ARGBic04/ic05plus aninfochunk), checks every standard size 16–1024, and asserts both icon files land in the archive.How you verified it
python3 packaging/test_package.py(2 tests: icns element types/sizes/container and archive icon/Info.plist wiring, now also the runtime PNG).cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings.cargo test --workspaceon macOS after the rebase — only the 6 knownbeamcraft-host output::testsfailures (pre-existing on this host, unrelated; no other suite failed).bash -n packaging/package.sh packaging/generate-icon.sh;git diff --check.packaging/package.shproduced a signedBeamCraft.app; the app was launched from the bundle against a published store, and a screenshot shows the official logo on the running window and in the Dock (attached to the worker report).cargo fmt --all— passcargo clippy --workspace --all-targets -- -D warnings— passcargo test --workspace— pass except the 6 known macOS-host output testsNever-crash
Provenance
ATTRIBUTION.md: the official SVG, PNG and ICNS reference issue Add required project logos #164, its author and the attachment hashes.docs/brand/LICENSE-brand.txt, not MPL-2.0. No third-party artwork used.Anything a reviewer should look at first
assets/icons/*(was MPL-2.0 placeholder art): the app icon is now the official logo, sodocs/brand/LICENSE-brand.txtgoverns it.app::load_iconreads a file from the bundle at run time: check the fallback path and that no icon bytes are compiled into the binary.test_package.pyicns assertions must keep failing when a required size is missing.Roadmap entry
2026-10-22 — Add the macOS app icon and bundle-resource checks; replace the placeholder with the official logo (#164); the Dock shows it while the app runs; native validation done on macOS.
🤖 Generated with Claude Code