Server URLs must use http:// or https://. file:// URLs are rejected in the server dialog, since they could never be fetched
Custom script #status# and #projects# placeholders are now shell-quoted, with quoting that follows the surrounding quotes. Scripts that relied on the raw, unquoted text need updating
On Windows a custom script that uses #status# or #projects# is not run. Use the BUILDNOTIFY_STATUS and BUILDNOTIFY_PROJECTS environment variables instead
Settings move to a versioned layout on first start. 2.x can't read them afterwards
Install with uv tool install buildnotify or pipx install buildnotify. The setuptools, paver, tox and Vagrant files are gone
BUILDNOTIFY_STATUS and BUILDNOTIFY_PROJECTS environment variables for the custom script
Automatic migration of 2.x settings, keeping the old keys until the new ones are saved
--settings PATH to use an INI settings file, and --debug to log every fetch
Failing projects listed in the tray tooltip
Symbolic tray icons that differ by shape, with a preference to turn them on
The tray count overlay is sharp on HiDPI screens
All servers are polled in parallel
User-Agent is BuildNotify/<version>, without the OS and kernel version
Flatpak manifest (packaging/flatpak) and AppStream metadata under the io.github.anaynayak.BuildNotify app id. The desktop file and icon are renamed to match
Preferences, the server dialog, the About box and the no-tray message open centred on the screen under the mouse pointer, kept inside the usable area, instead of in a corner of the primary screen
The server dialog hides the Advanced section for GitHub servers, where it had held only the time zone, which applies to cctray feeds. It comes back when you switch to cctray, with the time zone you had chosen
Mute a server or a project from the tray menu's Mute submenu, which has one submenu per server with a Mute whole server toggle followed by that server's projects. You can also pause all notifications for an hour. Muted servers and projects, including every project on a muted server, get no notifications, don't run the custom script, and don't affect the tray icon colour, the failing count or the badge. They stay in the menu with a dimmed icon and a (muted) suffix, and the tooltip adds N muted. Unmuting updates the tray at once. Pausing notifications doesn't change the icon. Mutes and the pause survive a restart
Settings move to schema version 5, which gives each server a source type and a muted flag. Existing servers become cctray feeds and start unmuted
The tray menu's Failing, Building, Passing and Unknown headers are disabled rows with separators between groups,. Native macOS menus don't draw Qt section titles, so they had gone missing or shown as unlabelled groups. A server with no projects shows a single Mute <server> checkbox
Project rows say which server they belong to. A GitHub server with no prefix labels its rows with the repository name, such as [hello-world] CI (main), and an explicit prefix still wins. A cctray project with no prefix whose name also appears on another server gets that server's host in brackets. Notifications and the tooltip use the same label; muting and change detection still go by server and project name
Symbolic tray icons keep at least 3:1 contrast on both light (#f0f0f0) and dark (#2b2b2b) panels: the failure cross is now a lighter red and the grey a little darker. Below 20 px, which includes the 16 px icons used on Windows, the tray badge shows ! instead of a count that would be unreadable
When no system tray is found, the message says BuildNotify needs a system tray and, on GNOME, names the AppIndicator and KStatusNotifierItem Support extension. The box shows the BuildNotify icon and title. BuildNotify still exits with code 1
The server dialog's time zone and certificate checks sit in a collapsed Advanced section that opens by itself when either is set. The field is now Time zone for feed times, its default entry reads Use the feed's offset (stored as before), and you can type part of a zone name, such as Kolkata, to find it
Labels and buttons in Preferences and the server dialog have Alt-key mnemonics, such as Alt+S for Save, with none repeated on a page. The project filter, project list and server list have names for screen readers
A Check now item in the tray menu polls every server immediately. Menu items now read Preferences... (Settings... on macOS), About BuildNotify and Quit BuildNotify (Exit on Windows), and the About box describes cctray feeds and GitHub Actions and links to the project page
Tray icons tell more states apart. Success while building now has a ring, so it no longer looks like plain success, and the same ring marks failure while building. When every server is down and none has projects from an earlier fetch, the icon is a hollow slashed square (a slashed circle in the symbolic set) instead of the grey used for an unknown status. The tooltip also shows the server count and Notifications paused until HH:MM while paused
The server dialog's sign-in choices are None, Username and password and Token. None hides both fields and saves no credentials. Without a keyring, the dialog says credentials can't be stored and names the keyring package to install. A saved cctray bearer token is labelled as a token instead of Password
The certificate prompt now names the host and says it turns off certificate checks for that server. After accepting, the dialog shows Certificate checks off for <host> with a Turn checks back on button
The GitHub form links to token creation, says the token needs Actions: read and that GitHub allows 60 requests an hour without one, and accepts a pasted https://github.com/owner/name URL as the repository
The server dialog's project list has a filter field, an All (N of M) box that shows a partial state when some projects are unticked, a note that new projects in the feed are included automatically, and middle-elided names with the full name as a tooltip
A Failing first sort order, the default for new installs, puts building projects first within each tray menu section, then the newest builds. Existing installs keep their sort order
Unavailable servers get a menu row with their last error and when it happened. The error is one short line with the host but no full URL or credentials
GitHub Actions servers: pick "GitHub Actions" in the server dialog and enter a repository, with optional workflow and branch filters. The latest run of each workflow and branch shows as a project. When a workflow filter matches no finished run in the newest 100 runs, BuildNotify reads up to 4 older pages to find one. The token stays in the system keyring, and BuildNotify waits out GitHub's rate limits on every server that uses the same token. A server with no token, for a public repository, writes nothing to the keyring
With no servers the tray menu says "No servers yet" and offers "Add a server...", which opens the server dialog. Pause and Mute are hidden until a server is configured, and the tooltip says "No servers configured" instead of "No failing builds"
On the first launch with no servers, the server dialog opens once. A first_run/server_prompt_shown setting stops it opening again
Clicking a notification about one project opens its page. Clicking one about several projects or a server opens the tray menu
A " is reachable again" notification follows a connectivity notification once the server answers. The custom script runs for it with BUILDNOTIFY_STATUS set to Connectivity restored
The Servers tab shows each server as a row with its name (prefix, else host), source kind, target (host, or repository with workflow@branch) and the project count from the last poll. The buttons read Add..., Edit... and Remove, with Insert, Enter and Delete shortcuts, and Remove asks for confirmation
Preferences is split into Servers, Menu, Notifications and Advanced tabs, with sentence-case labels, OK and Cancel buttons, and the request timeout and custom script example exposed. The docs screenshots follow the new tabs
The tray menu groups projects under Failing, Building, Passing and Unknown headers with counts, so the status no longer depends on the icon colour alone. Empty sections are left out
With more than 15 projects, passing projects collapse into a Passing (N) submenu so the tray menu fits on screen. Failing and building projects stay top level
Long project names in the tray menu are shortened in the middle to a fixed width, so the job name and build time are no longer cut off. The tooltip shows the whole name
Build times in the tray menu are compact, such as 18m, 11h or 3d, instead of 18 minutes ago
Notification titles name the project or count the builds, such as Build failed: nightly, 3 builds failed, Build fixed: nightly, Still failing: nightly, Build passed: nightly and Can't reach ci.example.org, instead of Broken builds or Yet another successful build. A notification lists at most three names, then and N more. The custom script still gets the old titles in BUILDNOTIFY_STATUS and every name in BUILDNOTIFY_PROJECTS
Failure and connectivity notifications use the warning icon instead of the information icon
When every server is down and nothing is cached, the tray tooltip says "Can't reach any server" instead of "No failing builds"
A server error row in the tray menu reads like jenkins: can't connect (10:00): the server's menu prefix or host, then a short reason such as can't connect, server not found, timed out, sign-in failed, not found, not a cctray feed, certificate not trusted or GitHub rate limit reached. The row is no longer greyed out, and opens a submenu with the full error, a hint, Retry now and Edit server...
The server dialog is a single page with Cancel and Save. Save works without loading the server first, so a server that is down can be added, and all of its projects are included. Load is now Test connection, which shows the project count or a short error next to the button and lists the projects below. Editing a server without testing it keeps its excluded projects. Changing the URL, repository or source type clears the test result and its project list
The server dialog is titled "Add server" for a new server and "Edit server - " when editing one
A feed URL typed without a scheme, such as ci.example.org/cc.xml, gets https:// added instead of an error
Server dialog validation errors show under the field instead of in a message box, when the field loses focus or on Load. "Path to cctray.xml" is now "Feed URL", and an empty one says "Enter the feed URL."
The failing count on the tray icon is a red badge in the bottom-right corner, so it no longer covers the icon. Counts above 99 show as 99+
Bearer and GitHub tokens are stored in the keyring under the username token instead of an empty username, which keyring deprecates. Tokens saved by earlier versions are still read, and move to the new entry the next time settings are saved
The tray icon keeps the same size in every state on macOS. After a poll the icon with a count badge or a muted dimming was a single 22 px picture while the launch icon was a 128 px one, so the menu bar scaled them differently and the icon looked smaller. Every state is now built the same way, with 1x and 2x pictures of the same size
GitHub Actions servers no longer list Dependabot's dynamic runs (event dynamic, workflow path under dynamic/), which added a new row for every run with its run number in the name
Accepting the certificate prompt in the server dialog turns off certificate checks only for that host. Changing the feed URL to another host turns them back on
Saving Preferences no longer cancels a pause set from the tray while the dialog was open
Saving Preferences no longer reverts servers or projects muted or unmuted from the tray while the dialog was open
Saving Preferences no longer lowers the default 120 s polling interval to 60 s. The interval can be set from 10 seconds to an hour
Configure in Preferences is enabled when a server is selected with the keyboard, not only with a mouse click, and Enter opens the selected server for editing
Shell injection through project names in the custom script
Crash on non-XML server responses
Feeds without a <Projects> root are reported as errors instead of showing 0 projects
Feeds are parsed with defusedxml
Keyring errors no longer crash polling, and the keyring is only touched when credentials are set
lastBuildTime parsing with timezone offsets, using zoneinfo
Fetches no longer run on the GUI thread when preferences are saved
A reload during a fetch triggers a new fetch instead of being dropped
The overall status ranks every failure above every success, and Exception counts as a failure
New builds are detected by build time as well as label
Last known projects are kept while a server is unavailable, and the connectivity back-off resets on recovery
A new failing project is notified as broken
The custom script text is kept when the script is disabled
Server list editing: empty lists are saved, Remove with no selection is ignored, edited URLs update the list, duplicates are rejected, and removed servers lose their settings and keyring entry
Added servers are saved only when Preferences is accepted
Editing a server keeps its SSL verification setting
Bearer authentication sends only the Bearer token
The server dialog's Load has a total deadline
The SSL retry prompt shows a No button and defaults to No
The no-tray message is shown, and startup waits for the tray
Quitting goes through the event loop, waits a bounded time for fetch threads and hides the tray icon at once
The preferences and server dialogs are deleted after they close
Future build times read "in ..." instead of "... ago", and the 30-day boundary is fixed