Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions image/desktop_payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ def prepare_defaults(root, payload, environment, inventory):
KITTY_INCLUDE = "# BEGIN CYBEXOS MANAGED INCLUDE\ninclude cybexos.conf\n# END CYBEXOS MANAGED INCLUDE\n"


def prepare_app_launchers(root, payload):
"""Package the same desktop launchers that checkout installs deploy."""
applications = payload / 'usr/share/cybexos/user-seed/.local/share/applications'
applications.mkdir(parents=True, exist_ok=True)
for name in ('nvim-kitty', 'brave-origin', 'chatgpt', 'com.onepassword.OnePassword'):
target = applications / (name + '.desktop')
shutil.copyfile(root / 'roles/dotfiles/files' / target.name, target)
target.chmod(0o644)


def prepare_session(root, payload, inventory):
"""Session pieces the workstation installs per user, packaged once.

Expand Down
5 changes: 2 additions & 3 deletions image/package
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import urllib.request
import jinja2
import yaml
from application_payload import relativize_seed_links, include_applications
from desktop_payload import prepare_defaults, prepare_session, split_seed, prepare_managed_defaults
from desktop_payload import prepare_defaults, prepare_session, split_seed, prepare_managed_defaults, prepare_app_launchers
from provision_payload import prepare_provision
from release_metadata import install_update_channel, render_spec

Expand Down Expand Up @@ -112,8 +112,7 @@ def main():
content = (ROOT / "roles/dotfiles/templates" / (name + ".desktop.j2")).read_text()
write(f"{seed}/.local/share/applications/{name}.desktop",
content.replace("{{ primary_home }}/.local/bin/", ""))
for name in ("nvim-kitty", "brave-origin", "chatgpt", "com.onepassword.OnePassword"):
copy(f"roles/dotfiles/files/{name}.desktop", f"{seed}/.local/share/applications/{name}.desktop")
prepare_app_launchers(ROOT, payload)
t3_desktop = (ROOT / "roles/dotfiles/templates/t3code-nightly.desktop.j2").read_text()
write(f"{seed}/.local/share/applications/t3code-nightly.desktop",
t3_desktop.replace("{{ primary_home }}/.local/bin/", ""))
Expand Down
31 changes: 31 additions & 0 deletions image/test_installation_parity.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,37 @@ def test_packaged_policy_is_the_same_source_used_by_checkout(self):
with self.assertRaisesRegex(ValueError, 'both installer schemas'):
defaults(Path('fixture'))

def test_chatgpt_launcher_matches_checkout_and_iso_at_native_display_scale(self):
from desktop_payload import prepare_app_launchers
from test_desktop_payload import INIT

launcher = '.local/share/applications/chatgpt.desktop'
(self.home / launcher).parent.mkdir(parents=True)
task = next(task for task in yaml.safe_load(
(ROOT / 'roles/dotfiles/tasks/main.yml').read_text())
if task.get('name') == 'Install MIME defaults and desktop launchers')
task['become'] = False
task['loop'] = [item for item in task['loop'] if item['name'] == 'chatgpt.desktop']
task['ansible.builtin.copy']['src'] = str(ROOT / 'roles/dotfiles/files') + '/{{ item.name }}'
playbook = self.root / 'chatgpt-launcher.yml'
playbook.write_text(yaml.safe_dump([{
'hosts': 'localhost', 'connection': 'local', 'gather_facts': False,
'vars': {'primary_home': str(self.home), 'primary_user': 'fixture',
'features': {'proprietary_apps': True}},
'tasks': [task],
}]))
result = subprocess.run(['ansible-playbook', '-i', 'localhost,', str(playbook)],
env=os.environ, text=True, capture_output=True, timeout=30)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)

payload = self.root / 'payload'
prepare_app_launchers(ROOT, payload)
iso_home = self.root / 'iso-account'
INIT.seed_applications(payload / 'usr/share/cybexos/user-seed', iso_home)
self.assertEqual((self.home / launcher).read_bytes(), (iso_home / launcher).read_bytes())
self.assertIn('Exec=chatgpt --ozone-platform=wayland %U',
(iso_home / launcher).read_text().splitlines())


if __name__ == '__main__':
unittest.main()
2 changes: 1 addition & 1 deletion roles/dotfiles/files/chatgpt.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Name=ChatGPT
Comment=ChatGPT by OpenAI
GenericName=AI assistant
Exec=chatgpt %U
Exec=chatgpt --ozone-platform=wayland %U
Icon=chatgpt
Type=Application
Terminal=false
Expand Down
4 changes: 2 additions & 2 deletions tests/quickshell/deployment-convergence.test.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ test("ChatGPT launcher follows portable desktop scaling", () => {
assert.match(dotfileTasks,
/Install MIME defaults and desktop launchers[\s\S]{0,1200}?name: chatgpt\.desktop[\s\S]{0,120}?features\.proprietary_apps/,
"the launcher must be deployed as a per-user package override");
assert.match(launcher, /^Exec=chatgpt %U$/m,
"ChatGPT follows the display scale selected by the desktop");
assert.match(launcher, /^Exec=chatgpt --ozone-platform=wayland %U$/m,
"native Wayland follows the display scale even when XWayland scaling is disabled");
});

test("disabled Docker and Tailscale retire activation and imported trust", () => {
Expand Down
4 changes: 2 additions & 2 deletions tests/verify-system
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,8 @@ if feature_enabled proprietary_apps; then
check 'ChatGPT repository key matches the reviewed OpenAI key' \
cmp -s "$repo_root/roles/apps/files/chatgpt-repository-key.asc" \
/etc/pki/rpm-gpg/RPM-GPG-KEY-chatgpt
check 'ChatGPT launcher follows the desktop display scale' \
grep -qx 'Exec=chatgpt %U' \
check 'ChatGPT launcher uses native Wayland for desktop display scaling' \
grep -qx 'Exec=chatgpt --ozone-platform=wayland %U' \
"$HOME/.local/share/applications/chatgpt.desktop"
check 'Brave restore, locale spellcheck, and 1Password policy is valid JSON' \
jq -e --arg language "${regional_locale%%_*}" \
Expand Down
Loading