Skip to content

Commit ddea9b1

Browse files
authored
Merge pull request #353 from fedoraBee/feat/v1.5.44-hide-banner-option
feat: Add -B/--hide-banner option and cli.hide_banner config setting to hide ASCII header banner
2 parents 814d207 + 058876f commit ddea9b1

16 files changed

Lines changed: 482 additions & 29 deletions

‎MAINTAINERS.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,10 @@ When you are ready to cut a new release, follow these steps to generate the
9090
tbump X.Y.Z --no-push
9191
```
9292

93-
_Note: `tbump` will automatically trigger the `before_commit` hook, run
94-
`update-package-metadata.py`, generate the changelog and bundle everything
93+
_Note: `tbump` will automatically trigger the `before_commit` hooks to
94+
regenerate the status screenshot
95+
(`scripts/maintainer/generate-screenshot.py`), run
96+
`update-package-metadata.py`, generate the changelog, and bundle everything
9597
into a single release commit and local tag._
9698

9799
💡 **Tip for Release Candidates:** You can safely use standard SemVer tags

‎README.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ updates. It features Snapper-integrated atomic rollbacks, multi-channel alerting
1212
user-level execution. Designed for reliability and ease of use, it ensures your
1313
Flatpak environment remains current and resilient.
1414

15+
<!-- prettier-ignore-start -->
16+
<!-- markdownlint-disable-next-line MD033 -->
17+
<div align="center"><img src="assets/status-screenshot.png" alt="Flatpak Automatic
18+
System Status Overview" width="750"></div>
19+
<!-- prettier-ignore-end -->
20+
1521
## ✨ Features
1622

1723
- **Automated Flatpak Updates:** Keep your flatpak applications up-to-date
@@ -154,8 +160,8 @@ first run).
154160
To trigger an update manually or use the advanced CLI:
155161

156162
```text
157-
usage: flatpak-automatic [-h] [-d] [-t] [-f] [-s] [-l] [-a] [-c] [-r]
158-
[--desktop-mode] [-e] [-x]
163+
usage: flatpak-automatic [-h] [-d] [-t] [-f] [-s] [-B] [-v] [-V] [-l] [-a] [-c]
164+
[-r] [--desktop-mode] [-e] [-x]
159165
160166
Flatpak Automatic - Advanced Update Automation
161167
@@ -165,6 +171,9 @@ options:
165171
-t, --test-notify Send a test notification to configured endpoints and exit.
166172
-f, --force Force the update process, ignoring safeguards.
167173
-s, --status Display system monitoring overview and exit.
174+
-B, --hide-banner Hide the header ASCII banner upon execution.
175+
-v, --version Show application version and exit.
176+
-V, --verbose Enable verbose output (e.g. detailed status view with -s/--status).
168177
-l, --history Display recent update history from journalctl and exit.
169178
-a, --apply-schedule Apply systemd timer overrides based on config settings.
170179
-c, --check-config Validate and print the current configuration, then exit.

‎assets/status-screenshot.png‎

107 KB
Loading

‎config/config.default.yaml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ exclusions: []
3838
# Type: string, Default: always
3939
auto_notify: always
4040

41+
# ------------------------------------------------------------------------------
42+
# CLI & Interface Settings
43+
# ------------------------------------------------------------------------------
44+
45+
cli:
46+
# Hide the ASCII header banner when executing from terminal.
47+
# Type: boolean, Default: false
48+
hide_banner: false
49+
4150
# ------------------------------------------------------------------------------
4251
# Systemd Timer Schedule
4352
# ------------------------------------------------------------------------------

‎config/config.example.yaml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ exclusions:
3131
# Notification trigger policy: 'always', 'on-change', 'on-failure', or 'never'.
3232
auto_notify: always
3333

34+
# ------------------------------------------------------------------------------
35+
# CLI & Interface Settings
36+
# ------------------------------------------------------------------------------
37+
38+
cli:
39+
# Hide the ASCII header banner when executing from terminal.
40+
hide_banner: false
41+
3442
# ------------------------------------------------------------------------------
3543
# Systemd Timer Schedule
3644
# ------------------------------------------------------------------------------

‎config/config.user.default.yaml‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ exclusions: []
3232
# Type: string, Default: always
3333
auto_notify: always
3434

35+
# ------------------------------------------------------------------------------
36+
# CLI & Interface Settings
37+
# ------------------------------------------------------------------------------
38+
39+
cli:
40+
# Hide the ASCII header banner when executing from terminal.
41+
# Type: boolean, Default: false
42+
hide_banner: false
43+
3544
# ------------------------------------------------------------------------------
3645
# Systemd Timer Schedule (User Scope)
3746
# ------------------------------------------------------------------------------

‎config/templates/default_mail_success.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# ✅ Update Report: Success
22

3-
The `flatpak-automatic` agent has successfully installed **${UPDATE_COUNT}**
3+
The `flatpak-automatic` agent has successfully installed
4+
**${UPDATE_COUNT}**
45
updates on the host **${HOSTNAME}**.
56

67
## Installation Details

‎docs/development.md‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ Usage:
7575
[--dry-run]
7676
```
7777

78+
## Screenshot Generation Tool
79+
80+
A `scripts/maintainer/generate-screenshot.py` script automatically captures the
81+
output of `flatpak-automatic -s` (including the full ASCII header banner) and
82+
renders a high-resolution terminal screenshot image saved at
83+
`assets/status-screenshot.png` for display in `README.md`. This script is
84+
automatically invoked during release version bumps via `tbump`.
85+
86+
Usage:
87+
88+
```bash
89+
python3 scripts/maintainer/generate-screenshot.py
90+
```
91+
7892
## Testing Matrix
7993

8094
This project enforces a Shift-Left testing approach.

‎docs/flatpak-automatic.1‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
flatpak-automatic \- Secure, systemd-native automation for Flatpak updates
55
.SH SYNOPSIS
66
.B flatpak-automatic
7-
[\fB\-d\fR] [\fB\-t\fR] [\fB\-f\fR] [\fB\-s\fR] [\fB\-l\fR] [\fB\-a\fR] [\fB\-c\fR] [\fB\-r\fR] [\fB\-e\fR] [\fB\-x\fR] [\fB\-\-desktop\-mode\fR]
7+
[\fB\-d\fR] [\fB\-t\fR] [\fB\-f\fR] [\fB\-s\fR] [\fB\-B\fR] [\fB\-v\fR] [\fB\-V\fR] [\fB\-l\fR] [\fB\-a\fR] [\fB\-c\fR] [\fB\-r\fR] [\fB\-e\fR] [\fB\-x\fR] [\fB\-\-desktop\-mode\fR]
88
.SH DESCRIPTION
99
.B flatpak-automatic
1010
is a secure, systemd-native automation wrapper for Flatpak updates. It features Snapper-integrated atomic rollbacks, multi-channel alerting (Apprise, Mail, Webhooks, Desktop), and supports both system-wide and rootless user-level execution. Designed for reliability and ease of use, it ensures your Flatpak environment remains current and resilient.
@@ -32,6 +32,15 @@ Force the update process, bypassing the minimum delay guard and auto_update poli
3232
.BR \-s ", " \-\-status
3333
Display a system monitoring overview of configuration and pending updates.
3434
.TP
35+
.BR \-B ", " \-\-hide\-banner
36+
Hide the header ASCII banner upon execution.
37+
.TP
38+
.BR \-v ", " \-\-version
39+
Display the installed application version and exit.
40+
.TP
41+
.BR \-V ", " \-\-verbose
42+
Enable verbose output (e.g. detailed status view of installed Flatpaks and runtimes with -s/--status).
43+
.TP
3544
.BR \-l ", " \-\-history
3645
Display recent execution history from journalctl.
3746
.TP
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/env python3
2+
"""Script to generate terminal status screenshot for README using rich, chrome/cairosvg."""
3+
4+
import os
5+
from pathlib import Path
6+
import re
7+
import shutil
8+
import subprocess
9+
import sys
10+
from PIL import Image, ImageChops
11+
from rich.console import Console
12+
from rich.terminal_theme import TerminalTheme
13+
from rich.text import Text
14+
15+
16+
# Authentic terminal color palette matching standard terminal emulators (with rich purple HEADER)
17+
VIBRANT_TERMINAL_THEME = TerminalTheme(
18+
background=(41, 41, 41),
19+
foreground=(248, 248, 242),
20+
normal=[
21+
(0, 0, 0),
22+
(255, 85, 85),
23+
(80, 250, 123),
24+
(241, 250, 140),
25+
(139, 233, 253),
26+
(189, 147, 249), # Purple (#BD93F9)
27+
(0, 229, 255),
28+
(191, 191, 191),
29+
],
30+
bright=[
31+
(98, 114, 164),
32+
(255, 110, 110),
33+
(105, 255, 148),
34+
(255, 255, 165),
35+
(120, 190, 255),
36+
(189, 147, 249), # Bright Purple (#BD93F9)
37+
(0, 229, 255),
38+
(255, 255, 255),
39+
],
40+
)
41+
42+
43+
def crop_margins(image_path: Path) -> None:
44+
"""Crop white outer margins from generated screenshot."""
45+
im = Image.open(image_path)
46+
im_rgb = im.convert("RGB")
47+
bg = Image.new("RGB", im_rgb.size, (255, 255, 255))
48+
diff = ImageChops.difference(im_rgb, bg)
49+
bbox = diff.getbbox()
50+
if bbox:
51+
cropped = im.crop(bbox)
52+
cropped.save(image_path)
53+
54+
55+
def convert_svg_to_png(svg_path: Path, output_png: Path) -> None:
56+
"""Convert SVG to PNG using Google Chrome/Chromium if available, falling back to cairosvg."""
57+
chrome_bin = shutil.which("google-chrome") or shutil.which("chromium")
58+
59+
if chrome_bin:
60+
temp_png = svg_path.parent / "temp_chrome.png"
61+
cmd = [
62+
chrome_bin,
63+
"--headless",
64+
"--disable-gpu",
65+
"--hide-scrollbars",
66+
f"--screenshot={temp_png}",
67+
"--window-size=1000,800",
68+
str(svg_path),
69+
]
70+
subprocess.run(
71+
cmd,
72+
check=True,
73+
stdout=subprocess.DEVNULL,
74+
stderr=subprocess.DEVNULL,
75+
)
76+
77+
if temp_png.exists():
78+
crop_margins(temp_png)
79+
shutil.move(temp_png, output_png)
80+
return
81+
82+
# Fallback to cairosvg
83+
import cairosvg
84+
85+
svg_data = svg_path.read_text(encoding="utf-8")
86+
svg_data = re.sub(
87+
r"font-family:\s*([^;]+);",
88+
r"font-family: \1, 'Noto Color Emoji', 'Noto Emoji', 'Segoe UI Emoji', 'Apple Color Emoji', 'Symbola', monospace;",
89+
svg_data,
90+
)
91+
cairosvg.svg2png(
92+
bytestring=svg_data.encode("utf-8"),
93+
write_to=str(output_png),
94+
)
95+
96+
97+
def generate_screenshot() -> None:
98+
"""Run status command as root (or fallback), capture terminal output with ASCII header banner, and export to PNG image."""
99+
script_path = Path(__file__).resolve()
100+
repo_root = script_path.parent.parent.parent
101+
assets_dir = repo_root / "assets"
102+
assets_dir.mkdir(parents=True, exist_ok=True)
103+
output_png = assets_dir / "status-screenshot.png"
104+
temp_svg = assets_dir / "temp_status.svg"
105+
106+
src_dir = str(repo_root / "src")
107+
if src_dir not in sys.path:
108+
sys.path.insert(0, src_dir)
109+
110+
from flatpak_automatic.cli import banner
111+
112+
cli_script = repo_root / "src" / "flatpak-automatic.py"
113+
114+
output_text = None
115+
116+
# Try non-interactive sudo first, then interactive sudo, then non-root execution
117+
attempts = [
118+
["sudo", "-n", sys.executable, str(cli_script), "-s"],
119+
["sudo", sys.executable, str(cli_script), "-s"],
120+
[sys.executable, str(cli_script), "-s"],
121+
]
122+
123+
if os.geteuid() == 0:
124+
attempts.insert(0, [sys.executable, str(cli_script), "-s"])
125+
126+
for cmd in attempts:
127+
try:
128+
result = subprocess.run(
129+
cmd,
130+
cwd=repo_root,
131+
capture_output=True,
132+
text=True,
133+
check=True,
134+
timeout=5,
135+
)
136+
output_text = result.stdout.strip()
137+
if output_text:
138+
break
139+
except Exception:
140+
continue
141+
142+
if not output_text:
143+
# Ultimate fallback
144+
result = subprocess.run(
145+
[sys.executable, str(cli_script), "-s"],
146+
cwd=repo_root,
147+
capture_output=True,
148+
text=True,
149+
check=True,
150+
)
151+
output_text = result.stdout.strip()
152+
153+
banner_text = banner()
154+
full_output = f"{banner_text}\n{output_text}"
155+
156+
console = Console(record=True, width=100)
157+
rich_text = Text.from_ansi(full_output)
158+
console.print(rich_text)
159+
160+
svg_data = console.export_svg(
161+
title="flatpak-automatic -s", theme=VIBRANT_TERMINAL_THEME
162+
)
163+
temp_svg.write_text(svg_data, encoding="utf-8")
164+
165+
convert_svg_to_png(temp_svg, output_png)
166+
167+
if temp_svg.exists():
168+
temp_svg.unlink()
169+
170+
print(f"Successfully generated screenshot at: {output_png}")
171+
172+
173+
if __name__ == "__main__":
174+
generate_screenshot()

0 commit comments

Comments
 (0)