Repository navigation
Rewrite: layered architecture, working AP+STA on real hardware, modern GUI, gated CI/CD - #1
Merged
Merged
Conversation
…issues Restructure apsta into layers (core -> config/state -> hw/net -> services -> cmd) with errors carrying hints, rendered only by the CLI. The GUI becomes a client of the CLI via JSON and pkexec. Fixes: - AP+STA detection respects per-group limits; reports same-channel needs - strategies (hostapd, nmcli virtual, nmcli single) with transactional rollback; runtime state moved to /run/apsta; stale state cleaned on start - hostapd config sets country code, 802.11n/ac, WMM and a control socket - conflict-free subnet, system DNS, firewalld/iptables/nftables backends, ip_forward restored on stop - `apsta run` supervises the hotspot (resume, driver reset, channel changes); daemons run as transient systemd units; enable supports OpenRC and runit - random password on first start; no passwords in argv or the journal; polkit action instead of `pkexec sh`; no shell=True - client list from associated stations; working disconnect/block; unique tc priorities for rate limits Adds unit and integration tests (simulated network stack, no root or hardware needed), coverage gate in CI, and contributor docs.
The previous GUI used Adw.ToolbarView, Adw.Banner and Adw.EntryRow, so it crashed on Ubuntu/Pop!_OS 22.04, Linux Mint 21 and Debian 12. Newer widgets now go through apsta_gui/compat.py with baseline fallbacks. - Hotspot / Devices / Settings tabs: status hero with one start/stop button, per-device speed limit / disconnect / block, Share dialog with QR code, band and interface pickers, profiles, start-at-boot toggle, hardware report, toasts, shortcuts and an About window - escape SSIDs and hostnames before display (Pango markup) - explain pkexec failures; show a window when the CLI is missing - own app icon; StartupWMClass matches the app ID - CLI: `config --json` and autostart state in `status --json` - scripts/gui_smoke.py builds every view headlessly; CI runs it on Ubuntu 22.04, Debian 12, Ubuntu 24.04, Fedora and Arch - portability test rejects libadwaita APIs newer than the baseline
GUI - prefer the newest libadwaita widgets (ToolbarView, adaptive tabs with a bottom bar on narrow windows, SwitchRow, ButtonRow, Adw.Dialog, AboutDialog, Adw.Spinner) with fallbacks down to libadwaita 1.1 - work around libadwaita 1.5 collapsing page width without a font DPI - replace the deprecated Gdk.Texture.new_for_pixbuf - smoke test: Xvfb fallback, per-process display, dialog screenshots; checked on Ubuntu 22.04/24.04, Debian 12 and Arch CLI - --json output is clean JSON; messages go to stderr in that mode - status --limit-kbps without --limit-client is a usage error, not a crash - detect and status share one interface JSON shape (`type`) Docs - ARCHITECTURE: GUI structure, data flow, compatibility strategy, testing - new docs/json-output.md documenting --json output and exit codes - README desktop-app, scripting and troubleshooting sections; CONTRIBUTING setup for uv and pip, GUI rules, screenshot steps Tooling - dev tools as a PEP 735 dependency group; `make dev` (uv or pip); Makefile runs tools via `python -m` and explains missing tools - uv.lock; Python >= 3.10; CI on 3.10/3.12/3.14; latest action versions Tests - TTY-independent output tests; sleep hook tests; apsta run, prompts, supervisor SIGKILL escalation, deprecated flags; coverage gate 94 %
…nager)
Verified end to end on Arch: phone joined, got DHCP and internet while the
laptop stayed on Wi-Fi; stop restored the system exactly.
- keep NetworkManager away from the AP interface with a runtime
unmanaged-devices config (appended with +=) written before the interface
exists; wpa_supplicant had blocked hostapd ("Match already configured")
- consider hostapd up only at state=ENABLED and a hotspot alive only when
it broadcasts an SSID; a __ap vif reports type AP before anything runs
- cap transient unit restarts (StartLimitBurst=5 per 60 s)
- take the regulatory country from the phy's self-managed domain when the
global domain is 00
- skip non-netdev (P2P-device) blocks in `iw dev`; AP interfaces have no
connected_ssid
- GUI: hide the profile switcher when there is only one profile
- scripts/hardware_check.sh: start, keep up for a phone, stop, verify cleanup
- fake test world mirrors the real driver; regression tests for each fix
- release.yml: verify versions + CHANGELOG -> full CI and package builds (reusable workflows) -> build provenance attestation -> publish to PyPI, GitHub release (notes from CHANGELOG.md, SHA256SUMS), pacman repo, AUR, PPA. Nothing publishes unless every check passed. - ci.yml: actionlint, shellcheck for all scripts, tests on Python 3.10, 3.12, 3.14 (+3.15 pre-release, non-blocking), GUI on Ubuntu 22.04/24.04/ 26.04, Debian 12/13, Fedora, Arch; wheel/sdist build with twine check - packages.yml: lintian; install tests of the .deb on Ubuntu 24.04/26.04 and Debian 13, and of the Arch package - codeql.yml (python + actions) and dependabot.yml (actions + uv) - actions on their latest major versions; concurrency and timeouts on every workflow; least-privilege permissions per job - scripts/release_check.py, scripts/release_notes.py; bump_version.py releases the CHANGELOG "Unreleased" section - shellcheck fixes in apsta-sleep, install.sh, hardware_check.sh - GUI: shorter band subtitle; `make gui`
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
There was a problem hiding this comment.
CodeQL found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
From the first GitHub Actions run and CodeQL: - `config --generate-password` wrote the new password to /var/log/apsta.log; secrets now go through output.reveal_secret(), which never logs - log file is owner-only (0600) and existing world-readable logs are tightened - SIGKILL escalation test treats zombies as dead (containers without init) - shellcheck: pinned v0.11.0 in CI (was the runner's copy); fix SC2015 and SC2336 in install.sh; `make lint-ci` runs the same linters locally - CodeQL quality notes: explained empty excepts, no cli<->completion import cycle, abstract method body, test cleanups - release_check test keeps its ::error:: output out of CI annotations - PyPI publish action on its explicit latest version (v1.14.2)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A rewrite of apsta's internals, fixing the correctness, reliability and security problems found in review, plus a redesigned GUI and a gated release pipeline. Verified end to end on real hardware (Intel AX201, Arch, NetworkManager 1.58): a phone joined, got DHCP and internet while the laptop stayed on Wi-Fi, and
stoprestored the system exactly.Core
core→config/state→hw/net→services→cmd), argv-only subprocesses, errors with hints./run.ip_forwardrestored.apsta runwatcher (resume, channel changes), sleep hook, systemd/OpenRC/runit.pkexec sh.GUI
Quality
CI/CD
release.yml: verify versions + CHANGELOG → CI + package builds → provenance attestation → PyPI, GitHub release, pacman repo, AUR, PPA. Nothing publishes unless everything passed.See
CHANGELOG.mdfor upgrade notes (Python ≥ 3.10,--force→--allow-disconnect, deprecatedstatusflags,detect --jsonkeys).Test plan