Skip to content

Releases: distronode-corporation/bridgewatch

bridgewatch v1.2.0

Choose a tag to compare

@github-actions github-actions released this 25 Oct 13:44
e7ad97a

Crash reports that stay off until you say yes, the licence texts in every bundle, the
provenance attestation attached to the release, Tauri 2.12 (building from source now
needs Rust 1.90) and MiniJinja 3, and fixes for a pipeline that failed before its first
job reading green and for a quiet watch repeating a notification on every tick.

Added

  • Opt-in crash reports. The release builds can send a crash report to Distronode's
    Sentry organisation in the European Union (de.sentry.io) when the tray app panics, and only after the user says yes: the popover
    asks once, defaulting to Don't send, and Settings → UI → Send crash reports
    ([ui].send_crash_reports, unset until answered) changes the answer, taking effect at
    once. With no yes, no crash-report client is created. Home-folder names are replaced
    with <user> in every path in a report, and the user, IP and host name are dropped.
    The address is compiled in by the release workflow only (BRIDGEWATCH_SENTRY_DSN), so
    a build you compile yourself, or a fork's, never sends or asks. The release
    workflow also uploads the macOS .dSYMs and the Linux binaries to Sentry and records
    the release's commits, and the Linux binaries now keep their symbol table so a report
    names its functions. sentry 0.49.3 on rustls (no OpenSSL). Proved against a local
    stand-in server by src-tauri/tests/crash_reports.rs.
  • Licence files in every bundle. The .dmg, .deb, .rpm and .AppImage now carry
    LICENSE, NOTICE and the licence texts of the third-party code built into them:
    THIRD-PARTY-LICENSES-rust.txt, generated by cargo-about from Cargo.lock under the
    same allow-list as deny.toml, and THIRD-PARTY-LICENSES-npm.txt, generated from the
    npm packages the frontend build actually keeps. On Linux they are in
    /usr/share/doc/bridgewatch/ (.deb) or /usr/share/licenses/bridgewatch/ (.rpm).
    Until now the packages shipped the binary, the icons and a .desktop file only.
  • The provenance attestation is attached to the release as
    bridgewatch_<version>.intoto.jsonl, so gh attestation verify --bundle works
    offline.
  • .github/SUPPORT.md, and a "Licence of contributions" section in CONTRIBUTING.md.
  • osv-scanner.toml, mirroring the eight advisories deny.toml tolerates (same ids,
    same reasons), so OpenSSF Scorecard's Vulnerabilities check, which reads OSV and not
    deny.toml, honours them too.

Changed

  • Tauri 2.12 on the Rust side too, matching @tauri-apps/api and @tauri-apps/cli
    2.12: tauri 2.12.2 and tauri-build 2.7.1, with the plugins autostart 2.7.0,
    notification 2.5.1, opener 2.7.0 and positioner 2.4.0. Tauri 2.12 needs Rust 1.90, so
    building from source now needs Rust 1.90 or newer (was 1.88).
  • MiniJinja 3 renders the notification templates (was 2.24). The shipped title and
    body render exactly as before. One thing a custom template can see differently: a list
    printed whole, such as {{failures}}, now uses Python-style quotes (['a', 'b'], was
    ["a", "b"]); {{failures | join(', ')}} is unchanged and is the better spelling.
  • The frontend build's source-map-js is 1.2.2 (GHSA-68fv-2mgg-jv7q, a denial of service
    through indexed source-map section offsets; build time only).
  • The .deb's Maintainer is Distronode <opensource@distronode.com>, and the .deb and
    .rpm name https://www.distronode.com/open-source/bridgewatch as their homepage.
  • The example config and the test fixtures use a placeholder GitLab project id,
    12345678, and scripts/record-fixture.sh now requires the project argument instead
    of defaulting to one.
  • The bug report form asks for the provider and host (GitHub.com, GitHub Enterprise
    Server, GitLab.com or self-managed GitLab) and the Linux architecture.
  • bridgewatch watch --json prints each notification as a JSON line,
    {"notify": {...}}, between the snapshots. It used to print plain text there, which
    broke | jq.
  • Usage mistakes exit 64: an unknown --account in fixture record, and a
    fixture scrub directory holding no recordings (which used to pass --check
    having read nothing).
  • init --token-command takes everything after it, hyphenated arguments included, so
    --token-command gh auth token --hostname ghe.example.com works. Put it last.
  • scripts/record-fixture.sh scrubs through bridgewatch fixture scrub, so the Rust
    allow-list is the only one (it now needs cargo), takes the project id from the
    recorded pipeline, and refuses a non-numeric pipeline id before any request.
  • A host written with a default port or in upper case (https://GitLab.com:443) is one
    host everywhere: the CLI keyring item is glab:gitlab.com:token, and GitHub's next
    page is followed. Before, each place parsed the URL its own way.
  • The notification ledger is written only when it changed, not on every tick, and the
    ledger and eta.json keep a symlink and the file's permissions when saved.
  • tauri.conf.json no longer carries a version; Tauri reads Cargo.toml's.

Fixed

  • A pipeline that failed before it had a job read green. A .gitlab-ci.yml that
    does not parse, or a GitHub run that ended startup_failure or timed_out with no
    jobs, showed the outline check and check exited 0. It is now a blocking failure,
    pipeline failed.
  • One quiet watch could repeat a notification on every tick. Once the ledger held
    2000 keys, trimming dropped the smallest pipeline id, which next to GitHub's run ids
    was a quiet GitLab project's newest row: the key just recorded. Trimming now spares
    every pipeline still on screen.
  • A GitHub secondary rate limit that arrived as a 403 with no retry-after read as
    "not authorised, check the token" and was retried within seconds. It is a rate limit,
    and waits a minute.
  • Forget in Settings left the forgotten token in use until a restart; the account
    now stops polling. Saving or forgetting a token no longer freezes the tray while a
    Keychain prompt waits.
  • A sign-in closed or double-clicked while starting went on polling the provider for up
    to 15 minutes.
  • Opening the popover ran two polls back to back instead of one.
  • An open job log was fetched again, and blanked, on every tick.
  • A token command with a quoted argument (sh -c "pass show …") was split on spaces
    when Settings saved it.
  • Settings kept saying "valid" after another editor broke the file, said "Not signed
    in." when the keychain could not be read, and said nothing when Open file, the
    popover's Pipelines or Overwrite failed.
  • An unreadable config file was reported as "no accounts defined" instead of the read
    error, and "hot reload is off" now says why.
  • The wizard refused watch ids with a dot or a space that Settings and the core accept,
    and kept a pasted URL's ?tab=… or #… in the project path.
  • A notification template that fails to render warns once, not on every tick.
  • SECURITY.md described bridgewatch as sending authenticated GET requests and
    nothing else, and as following no redirect. Since 1.0 it also signs in through the
    OAuth device flow, and since 1.1 it sends the opt-in retry and play POSTs and follows
    one redirect, without credentials, to fetch a job's log. It now says so, and documents
    where sign-in tokens are kept, the actions = true gate and the log file.

Security

  • rustls-webpki 0.103.16 in Cargo.lock, for RUSTSEC-2026-0382 (CVE-2026-111943):
    0.103.15 could accept a certificate chain through one of the distrusted emSign
    intermediates, whose private keys are now public.
  • webpki-root-certs 1.0.10 in Cargo.lock, for RUSTSEC-2026-0383 (the same emSign
    distrust): 1.0.9 still bundled the emSign ECC Root CA - G3. No target bridgewatch ships
    compiles it (it arrives through rustls-platform-verifier on wasm32 only), so this clears
    lock-based scanners and keeps a future target from picking up the old root.
  • The frontend tests' undici is 8.12.2 (GHSA-xjj6-f33q-929c, a denial of service through
    excessive content-encodings; test time only, not in the app).

bridgewatch v1.1.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 19:55

Added

  • Deploy ETA. A running row now says how long this watch's deploys usually take and
    how far in this one is (usually ~11m · 6m 30s in in the popover, the same after the
    row in bridgewatch check and bridgewatch watch, and an eta object in their
    --json). It is learned with no extra API requests: each pipeline that deploys adds
    its push-to-marker-finished time, the median of the last 20 is shown once there are 3,
    and it is hidden when the row settles or has run past twice the usual time. Kept in
    eta.json beside the notification ledger and shared by the app and the CLI. On by
    default; eta = false on a watch, or the new Deploy ETA box in Settings, turns it
    off.
  • A log file. The app now writes its log to a daily file as well as to stderr, in
    ~/Library/Logs/bridgewatch on macOS and $XDG_STATE_HOME/bridgewatch (by default
    ~/.local/state/bridgewatch) on Linux, keeping the last 7 days. A macOS app started
    from Finder or the Dock sends stderr nowhere, so until now it left no log at all. The
    tray menu's new Open log folder opens it. The level is unchanged: RUST_LOG
    still wins, then [log].level, then warn.
  • Linux arm64 and .rpm release assets. Every release now ships a .deb, an .rpm
    and an .AppImage for both x86_64 and arm64 Linux, each built on Ubuntu 22.04 (the
    oldest GitHub runner per architecture), so the glibc floor stays 2.35 on both. The
    .rpm requires /usr/bin/secret-tool, which resolves to libsecret on Fedora and to
    secret-tool on openSUSE.
  • The end of a failed job's log, in the popover and on the command line. A failed
    job (parent or child, GitLab or GitHub) gets a log button that shows its last 40
    lines under the row, as plain text with escape sequences, section markers and runner
    timestamps taken out, with a link to the full log. bridgewatch log <job-url> prints
    the same. Read on demand only, never polled, and at most 256 KiB of a log is read.
    GitHub serves a log from a signed storage URL: bridgewatch follows that one redirect
    itself, over https only, and sends no token there.
  • Retry and play, opt in. With actions = true on an account, a failed or canceled
    job gets retry and a GitLab manual job gets play, each confirmed first, and
    bridgewatch retry <job-url> and bridgewatch play <job-url> do the same (--yes to
    skip the question, required without a terminal). Off by default: without it the
    client refuses every write before anything is sent. The token needs the api scope on
    GitLab or Actions: write on GitHub, and a GitLab sign-in made with read_api is asked
    to sign in again rather than sent. Every write is logged at info. The README's
    section Retry and play has the details.

Changed

  • A tick's requests run side by side. A watch's pipelines, each pipeline's jobs and
    bridges, the child pipelines behind them, and the watches themselves are fetched
    concurrently, at most 4 requests at a time per account, instead of one after another.
    Measured with bridgewatch check on one watch with a deep bridge fan-out, the
    requests after the pipeline list took 11 to 12 s one after another and 3.1 s now. Rows, notifications, the error a watch reports and the order of the
    Debug section's request list are exactly what the one-at-a-time poller produced.
  • Only the accounts a watch uses have their token resolved. bridgewatch check --watch <id> no longer reads a credential (or raises a Keychain prompt) for an account
    that watch does not use, and a broken credential on such an account no longer fails
    it.
  • One universal macOS .dmg (bridgewatch_<version>_universal.dmg) replaces the
    separate Apple Silicon and Intel downloads. It is signed and notarised as before, and
    the release checks that its binary carries both architectures.

Fixed

Four of these were seen on real pushes to a GitLab parent/child project.

  • "Deployed" before anything shipped. With several deploy_markers, the first one
    to succeed read as deployed while the others were still queued, so a push showed the
    filled check ~30 s in and ~20 minutes before the main deploy ran. A success now counts
    only once no other marker can still move: none is queued or running in a live
    pipeline, and no live trigger job that dive would walk into still has an unread
    child.
  • "Failed" at pipeline birth. A trigger job that had not yet created its child
    pipeline read as a dead bridge, so every push went red on its first poll and raised a
    blocking_failure notification. It now reads by its own status (running, awaiting a
    gate, skipped or canceled), and only a trigger that settled without a child is dead.
  • "Deployed" announced more than once for one push. The notification was keyed on
    the winning marker's name, which changed as later markers passed. It is now keyed on
    the pipeline, and a ledger written by 1.0.0 is still honoured, so upgrading does not
    repeat a deploy already announced.
  • A skipped pipeline hid the real verdict. A push that matched no job's rules
    created a skipped pipeline that took the newest row and turned the icon canceled.
    Skipped pipelines are now passed over and do not count against show.settled. A
    canceled pipeline still shows.
  • The setup wizard offered check jobs as deploy markers. A job whose name or stage
    leads with verify, test, lint, check, validate or smoke (for example
    verify:origins_deploy_script) is no longer offered.
  • A keyring lookup that never answers no longer stalls polling. Reading another
    tool's credential (glab's or gh's empty-user item) now has the same 10 s limit as a
    token command, and running out of it is reported as the store not answering rather
    than as a missing credential.

bridgewatch v1.0.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 07:22

Added

  • GitHub Actions. An account takes provider = "github" (the default stays
    gitlab, so an existing file means what it always did), and base_url, api_path
    and header default to github.com's. GitHub Enterprise Server is base_url plus
    api_path = "/api/v3". A GitHub watch names its repository as owner/repo and its
    sources are workflow events. It reads in one of two forms:
    • group = "run", the default: one workflow run is one row, optionally narrowed to one
      workflow with workflow = "ci.yml" (a file name or a numeric id).
    • group = "commit": every run one push started (same commit, event and branch,
      created within fan_out_secs, default 90, of the newest) is one row, with each run
      as a bridge. The verdict rules are the ones a GitLab parent pipeline gets, so a push
      that deployed while a sibling workflow failed reads deployed_with_failure, and
      dive selects workflows by name.
  • expect, for a workflow that never started. On a commit group,
    expect = ["ci.yml", "release.yml"] names workflow files every push must start. Once
    the group has settled and its window has passed, a missing one is a dead bridge, read
    as a GitLab trigger job that created no child is; until then it is a pending job, so
    the row reads running rather than green. config validate warns about the shapes that
    would read a group dead for the wrong reason.
  • Setting up GitHub from the wizard, Settings and the CLI. The wizard offers GitHub
    Actions beside GitLab, github.com or GitHub Enterprise, gh's keyring item when one
    exists (the empty-user item under gh:<host>, which follows gh auth switch),
    repositories by owner/repo, workflow events and an optional workflow. Test
    connection
    lists a classic token's scopes and warns when repo is missing. New
    GitHub watches poll at 30 s live and 120 s idle. bridgewatch init gains
    --provider, --gh and --workflow. Settings dims the keys that do not apply to an
    account's provider, and changing an account's provider drops the old provider's
    default base_url, api_path and header while keeping values you customised.
  • GitHub's rate limit is handled as one. A 403 or 429 carrying
    x-ratelimit-remaining: 0 or retry-after backs off until GitHub's reset time rather
    than being read as a bad token. Requests to GitHub are conditional (ETags, kept in
    memory), and an authenticated 304 does not count against the 5,000 an hour, so a
    settled GitHub watch costs nothing.
  • examples/github.toml, a GitHub example beside the GitLab one, following this
    repository's own workflows in both forms.
  • The job view links a bridge to the trigger job itself, beside the existing link to the
    child pipeline it created. They are different pages in GitLab and either can be the one
    that explains a verdict. A bridge with no URL shows no link.
  • On macOS the tray tooltip names the current state, for example "bridgewatch: deployed".
    Linux has no tray tooltip, and its tray still reports the binary name as its title over
    D-Bus: the only lever Tauri 2 offers there draws text in the panel beside the icon.

Changed

  • API responses are fetched gzip-compressed. A 20-row pipelines list drops from 7550 bytes
    to 1480, and an installed build was measured at about 70 MB an hour while a pipeline is
    live, which matters on a metered connection.
  • [log].level = "info", the default, now says something. One line each time a
    configuration is loaded or reloaded, naming the file, its account and watch counts and
    the log level actually in force, and one line for every watch whose verdict changes.
    debug adds per-tick and per-request detail, never a token. The configuration line now
    survives a first run, where the setup wizard writes the file after startup.

Fixed

  • bridgewatch init and the setup wizard no longer add a second primary watch to a file
    that already has one. The new watch is written as role = "secondary", with a note on
    stderr from the CLI and a note on the wizard's review step; --primary, or Make
    this watch primary too
    in the wizard, keeps it primary. A fresh config is written as
    before.
  • check --watch and watch --watch now answer for the watches you name. Naming only
    secondary watches printed icon: unknown and exited 4 over a verdict that had been read
    perfectly well, so a failed schedule never exited 1. Without --watch, and in the tray,
    nothing changes: primary watches alone decide.
  • Log output no longer carries ANSI colour escapes when stderr is not a terminal, so a
    piped bridgewatch check and the desktop app's lines in the systemd journal are plain
    text. NO_COLOR is honoured.
  • The bridgewatch CLI now follows the logging rule the app and the README already
    described: [log].level applies to bridgewatch's own crates and leaves everything else
    at warn, and an empty RUST_LOG counts as unset instead of silencing the run. A
    non-empty RUST_LOG still wins whole.
  • Configuration docs corrected where they contradicted the code, in the README, the
    example config and the hints the Settings window shows: [icon].theme describes the
    <glyph>.png and <glyph>@1x.png files that are actually read, and deploy_markers
    says that the order they are listed in decides which success is reported, not which
    job ran first.

Removed

  • The "First run" banner on the Settings accounts tab. Nothing has seeded an example
    config since the setup wizard replaced that, so the banner could never appear.

Security

  • On macOS a keyring token source with user = "" now asks for the item whose account
    is empty (security find-generic-password -a ""). It used to ask by service alone,
    and when a service holds more than one item macOS returns a named one: gh keeps two
    under gh:<host>, so the lookup could read a different account's token than the one
    configured once somebody ran gh auth switch. glab writes only one item, so its
    lookup reads what it always did.
  • A GitHub account's links open on its web host (github.com for api.github.com, the
    server itself for Enterprise Server), matched by scheme, host and port like every
    other link; look-alike hosts, other ports and gist.github.com are still refused. A
    GitHub pagination Link that names another host is refused rather than followed, so
    the token never travels with it.
  • quick-xml 0.38.4 -> 0.42.0 (through plist 1.10.1) for RUSTSEC-2026-0194 and
    RUSTSEC-2026-0195, found by the new cargo deny job before GitHub's database had them.
  • CI now runs cargo deny (advisories, licences, sources), zizmor over the workflows,
    dependency review on pull requests and a weekly OpenSSF Scorecard.
  • Release builds run in a tag-only release environment, which holds the macOS signing
    identity as its own environment secrets, so no branch workflow and no pull request can
    read it. v* tags are protected against being moved or deleted.
  • A weekly job re-runs cargo deny and npm audit --audit-level=high. Advisories land
    against code that did not change, so a scan that only runs on a push never sees them.
    The npm audit covers the whole tree, dev dependencies included, because this is a Vite
    app and they are what gets bundled into the shipped frontend.
  • Dependabot's patch and minor updates now enable GitHub auto-merge and land on their own
    once the eight checks the main ruleset requires have passed, dependency review among
    them. A major update waits for a person. The workflow triggers on pull_request, never
    pull_request_target, and never checks out the pull request's code.
  • deny.toml now lists all seven unmaintained transitive crates by advisory id, each with
    the path it arrives by and what would retire it: proc-macro-error through Tauri's GTK 3
    stack, smartstring through rhai, and five unic crates through urlpattern and
    tauri-utils. cargo deny now judges unmaintained crates across the whole tree instead
    of only the workspace's direct dependencies, so those seven are tolerated by name and a
    new abandoned crate anywhere fails CI. No dependency changed.

bridgewatch v0.1.0

Choose a tag to compare

@github-actions github-actions released this 18 Sep 08:43

First release. GitLab only, macOS and Linux.

GitHub support is coming

GitHub Actions is planned for 0.2 and is deliberately not in this release. bridgewatch's
value is walking a parent pipeline through its trigger jobs into the child pipelines.
GitHub has no parent/child pipelines: a push fans out into independent workflow runs,
related only by commit (head_sha) and event. Until bridgewatch has a commit-group
mapping that assembles those runs into one unit, a GitHub mode would be the same
per-workflow status dot other monitors already show.

Added

  • Bridge-aware pipeline reading. Walks a parent pipeline's trigger jobs (bridges)
    into their child pipelines and reads the child job lists, dive.depth levels deep,
    selected by dive.bridges, dive.exclude and dive.only_when. A bridge whose child
    was never created is reported as dead.
  • Source-aware watches. Each watch filters by ref (exact, glob or re: regex) and by
    pipeline source, so pushes, schedules and preflight branches on one project are
    separate watches. Primary watches drive the tray icon and notifications; secondary
    watches only add rows. With several primary watches the worst state wins, and
    validation warns about it.
  • Deploy verdict from marker jobs. deploy_markers names the jobs whose success
    means "deployed", found in the parent or any dived child. sibling_failure and
    post_deploy_failure (downgrade, fail, ignore) decide what a failure elsewhere
    does to a successful deploy. A marker that failed counts as a failure even when the job
    was allowed to fail.
  • Eight icon states: unknown, failed, deployed_with_failure, deployed,
    running, canceled, parked_gate, succeeded_no_deploy. A pipeline whose job lists
    could not be read is unknown, never green. Monochrome template glyphs on macOS,
    coloured on Linux, remappable per state with [icon].states, or replaced from a theme
    directory of PNGs.
  • Per-job classes through [watches.jobs] (literal or re: keys, first match wins):
    gate, warning, blocking, ignore. The table applies to bridges too. gate does
    not excuse a gated job that ran and failed.
  • Full job view in the popover. Every pipeline row expands into the parent's jobs
    and one row per bridge with its child's jobs, grouped by stage in pipeline order, with
    a status dot, a live marker and a locally ticking duration per job. Expansion survives
    refreshes. [ui].jobs (all by default, or failures) and a per-watch
    watches.show.jobs choose what is listed. Jobs carry started_at, finished_at and
    duration.
  • Faster live polling. poll.live_secs defaults to 5 s (idle stays 60 s). Opening
    the popover polls at once when the last poll is at least 2 s old, and the popover shows
    "updated Ns ago". GitLab offers no push channel to a desktop app, so this is polling;
    the per-tick request cost is documented in the README.
  • First-run setup wizard. Opens when there is no config file at the default path:
    account and token (glab's keyring item detected when present, a pasted token, an
    environment variable or a command), a connection test that names the user and warns
    about project tokens and missing read_api, a project list or typed id/path/URL,
    branch and sources with optional schedule and preflight watches, suggested deploy
    markers, notifications and poll speed, and a review of the exact config.toml. Always
    skippable ("Skip, I'll edit config.toml" writes nothing). Re-openable from the tray
    menu and Settings, and on an existing file it edits rather than replaces.
  • bridgewatch CLI (crates/bridgewatch-cli, built from source): check and
    watch (with --watch, --json, --fixture, and --ticks on watch), init
    (the wizard from flags: offline, prints and never writes), config path, config validate, config schema, config dump, fixture record and fixture scrub.
    --config is accepted before or after the subcommand.
  • Documented exit codes. 0 deployed or green, 1 failed, 2 deployed with failure,
    3 running, parked or canceled, 4 unknown, 64 usage error, 70 other error, 78 bad
    configuration. Verdict codes and error codes never overlap.
  • crates/bridgewatch-core, a Rust library with no Tauri dependency: config, token
    resolution, GitLab client, verdict engine, poller and notifications, tested against
    pipelines recorded from a real project and put through a personal-data allow-list.
  • Tauri 2 GUI. Tray icon per state; popover with per-watch rows, the job view, an
    error strip and a Debug section (config path, last poll, request log); Settings with
    Accounts, Watches, Icon, Verdict, UI and Log tabs plus an "Edit as text" tab with
    diagnostics by line and column; tray menu with Show status, Open pipelines page,
    Refresh now, Reload config, Open config file, Settings, Setup wizard, Launch at login
    and Quit. No Dock icon on macOS. UI built on shadcn-svelte components (vendored) and
    Tailwind CSS 4, following the OS light or dark appearance, with a popover vibrancy
    material on macOS.
  • GUI and file parity. Every config key has a Settings control and every control a
    key, enforced by a test against the generated JSON Schema.
  • Config editing that keeps your file. Reads and writes go through toml_edit, so
    comments and key order survive a GUI save. The file is hot-reloaded; an invalid file
    leaves the last good configuration running and shows its errors. GUI saves are
    compare-and-swap, so an open Settings window cannot overwrite a change made on disk.
    Unknown keys and values that name nothing are warnings, not errors.
  • Credential sources: an OS keyring item (including glab's, stored with an empty
    user name, with its go-keyring wrapper unwrapped), bridgewatch's own keyring entry
    (the default), an environment variable, or the first line of a command's output (no
    shell, stdin closed, 10 s timeout). A literal token in the config file is refused.
  • Security checks in the shell. Writing a command token source, or sending a
    credential to a host it has not been sent to before, needs an explicit confirmation
    described by the Rust side. Every link opens through one Rust function that allows
    only the scheme, host and port of a configured account. The web views hold no plugin
    permission beyond events. HTTP redirects are refused so a token never follows one, and
    a plain http:// base URL off loopback is warned about.
  • Launch at login through the OS login item, reflected in the tray menu, Settings and
    the config file.
  • Logging: [log].level applies to the app and is re-applied on reload; a non-empty
    RUST_LOG wins.
  • [verdict].script: an optional sandboxed Rhai script (no file imports, no eval,
    capped operations and call depth) that replaces the built-in rules. A failing script
    yields unknown.
  • Resilience. A failed token resolution or poller build retries with backoff (5 s
    up to 300 s) instead of stopping; a crashed poll loop is restarted and reported; a tray
    image that fails to draw falls back to a visible glyph and is re-asserted periodically.
  • examples/distronode.toml, a complete worked configuration with three watches.
  • Release assets: .dmg for Apple Silicon and Intel (signed with the Distronode
    Corporation Developer ID and notarised by Apple), .deb (depends on
    libsecret-tools) and .AppImage for x86_64 Linux, built on Ubuntu 22.04, each with a
    GitHub build provenance attestation.

Known limitations

  • Glob and regex refs, and watches with more than one source, are filtered client-side
    over the newest page of pipelines (30 to 100), because GitLab filters ref by exact
    name only.
  • Desktop notifications cannot open a URL when clicked (the Tauri notification plugin
    passes only title, body, icon and sound), so notify.click has no effect yet.
  • No poll on wake from sleep; opening the popover polls at once.
  • The CLI is not included in the release assets.
  • The wizard's deploy-marker suggestions look at the parent and direct children only.
  • Reading a glab keyring item for a self-managed instance follows glab's
    glab:<host>:token naming, which has not been checked against a live install.
  • Windows is not targeted.