Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
b2f0fab
rtbit-fluent: Files tab as a folder Tree with include/skip priority (…
thedancingdeveloper Nov 2, 2026
ec60da3
rtbit-ui-core: drop last egui reference from error doc comment (WI-2770)
thedancingdeveloper Nov 2, 2026
df9ef85
Revert "rtbit-fluent: Files tab as a folder Tree with include/skip pr…
thedancingdeveloper Nov 2, 2026
c316e6c
rtbit-fluent: Files tab as a folder Tree with include/skip priority (…
thedancingdeveloper Nov 2, 2026
2eb6cf0
test(swarmforge): router-level tests for POST /torrents/{id}/files/{i…
thedancingdeveloper Nov 2, 2026
b2df236
qbit: real app/preferences share limits and dht/pex/lsd; apply on set…
thedancingdeveloper Nov 2, 2026
6188937
ci: report nightly release dry-run failures (WI-2898)
thedancingdeveloper Nov 2, 2026
a2c2cae
rtbit-fluent: main-screen keyboard shortcuts (WI-2869)
thedancingdeveloper Nov 2, 2026
209f52a
ci: enforce cargo-deny dependency policy
thedancingdeveloper Nov 2, 2026
19d550c
Add torrent table keyboard navigation
thedancingdeveloper Nov 2, 2026
5455afc
rtbit-fluent: add detail pane empty states
thedancingdeveloper Nov 2, 2026
d3b4c28
Improve toolbar accessibility and focus visibility
thedancingdeveloper Nov 2, 2026
497c7aa
rtbit-fluent: dialogs close on Escape and confirm on Enter (WI-2871)
thedancingdeveloper Nov 2, 2026
ebfbd0d
rtbit-fluent: daemon-lost banner with 1s-30s backoff reconnect (WI-2874)
thedancingdeveloper Nov 2, 2026
838f1de
rtbit-fluent: tests for detail pane tabs (WI-2875)
thedancingdeveloper Nov 2, 2026
8fb1c91
rtbit-fluent: tests for status bar, shell navigation and bridge error…
thedancingdeveloper Nov 2, 2026
a2c9bed
qbit API: app/getFreeSpaceAtPath and real free_space_on_disk in sync/…
thedancingdeveloper Nov 2, 2026
f063caf
rtbit-fluent: right-click context menu on torrent rows (WI-2878)
thedancingdeveloper Nov 2, 2026
b3a02db
qbit API: add torrents/pieceAvailability (WI-2886)
thedancingdeveloper Nov 2, 2026
518924b
rtbit-fluent: persist table sort and column widths; add Up column (WI…
thedancingdeveloper Nov 2, 2026
eea577f
docs: audit Fluent client parity (WI-2877)
thedancingdeveloper Nov 2, 2026
b782389
feat(rtbit-fluent): open add dialog from torrent drops
thedancingdeveloper Nov 2, 2026
40c23d6
rtbit-fluent: add RSS rule priority selector (#287)
thedancingdeveloper Nov 2, 2026
5b233c7
rtbit-fluent: add trackers from torrent detail (#286)
thedancingdeveloper Nov 2, 2026
af4d5d9
Add per-category share limits (WI-2889)
thedancingdeveloper Nov 2, 2026
69ea435
Report real qbit API build information
thedancingdeveloper Nov 2, 2026
00a0324
Resolve metadata test merge
thedancingdeveloper Nov 2, 2026
cad86b3
CI: check generated parity summary drift
thedancingdeveloper Nov 2, 2026
ef03a41
ci: test fluent app for client dependency changes
thedancingdeveloper Nov 2, 2026
dae71ca
Add Radarr and Lidarr replay fixtures (WI-2896)
thedancingdeveloper Nov 2, 2026
1f89c15
Add missing payload diagnosis
thedancingdeveloper Nov 2, 2026
2d31158
Add bulk category and tag editing
thedancingdeveloper Nov 2, 2026
108ab19
Add real per-file priority levels
thedancingdeveloper Nov 2, 2026
398aa57
Release: smoke-test fluent artifacts before publishing
thedancingdeveloper Nov 2, 2026
a22f83f
CI: smoke test daemon container in merge queue
thedancingdeveloper Nov 2, 2026
af192c3
Add fluent per-file priority controls
thedancingdeveloper Nov 2, 2026
f48f217
librtbit: crash-safe atomic state writes; quarantine corrupt state files
thedancingdeveloper Nov 2, 2026
a92f7b6
Low-disk guard: default 1 GiB floor and 'low disk space' status error
thedancingdeveloper Nov 2, 2026
c89b066
Fixes #290: bound graceful shutdown save
thedancingdeveloper Nov 2, 2026
4f91875
fix: add tracker and DHT retry backoff (Fixes #299)
thedancingdeveloper Nov 2, 2026
6d7c0eb
rtbit-fluent: add filter sidebar (Fixes #297)
thedancingdeveloper Nov 2, 2026
4910bc4
rtbit-fluent: add status bar speed controls (Fixes #296)
thedancingdeveloper Nov 2, 2026
1e7f000
fix(fluent-1): restore build after concurrent lands
thedancingdeveloper Nov 2, 2026
4396fe3
Fixes #291: add torrent metadata and management controls
thedancingdeveloper Nov 2, 2026
2747b76
Add torrent location and rename dialogs; Fixes #298
thedancingdeveloper Nov 2, 2026
8352486
Implement qbit app network and shutdown endpoints (Fixes #293)
thedancingdeveloper Nov 2, 2026
0d2bd93
Fix release dry-run runner policy
thedancingdeveloper Nov 2, 2026
8c13378
chore: fold Dependabot updates and group scheduling
thedancingdeveloper Nov 2, 2026
c63569e
Harden session recovery and torrent locations
thedancingdeveloper Nov 2, 2026
cb37c65
feat(qbit): report in-flight piece states and refresh parity notes (F…
thedancingdeveloper Nov 2, 2026
fa94515
style: cargo fmt
thedancingdeveloper Nov 2, 2026
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
72 changes: 9 additions & 63 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,77 +1,23 @@
# Dependabot version-update configuration.
#
# Security updates are enabled separately at the repo level and run regardless
# of this file. This config adds scheduled *version* updates to keep manifests
# and lockfiles fresh proactively. Updates are grouped to minimise PR noise.
version: 2
updates:
# ---- Rust: main workspace (covers all crates/* and desktop/src-tauri) ----
- package-ecosystem: cargo
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 10
interval: monthly
groups:
cargo-minor-patch:
update-types:
- minor
- patch

# ---- Rust: benchv2 (excluded from the workspace) ----
- package-ecosystem: cargo
directory: "/benchv2"
schedule:
interval: weekly
open-pull-requests-limit: 5
groups:
benchv2-minor-patch:
update-types:
- minor
- patch

# ---- Rust: fuzz (excluded from the workspace) ----
- package-ecosystem: cargo
directory: "/fuzz"
schedule:
interval: weekly
open-pull-requests-limit: 5
groups:
fuzz-minor-patch:
update-types:
- minor
- patch

# ---- npm: web UI (crates/librtbit/webui) ----
- package-ecosystem: npm
directory: "/crates/librtbit/webui"
schedule:
interval: weekly
open-pull-requests-limit: 10
groups:
webui-minor-patch:
update-types:
- minor
- patch

# ---- npm: root workspace (includes the desktop package) ----
cargo:
patterns: ["*"]
- package-ecosystem: npm
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
interval: monthly
groups:
root-npm-minor-patch:
update-types:
- minor
- patch

# ---- GitHub Actions workflows ----
npm:
patterns: ["*"]
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
open-pull-requests-limit: 5
interval: monthly
groups:
actions-all:
patterns:
- "*"
actions:
patterns: ["*"]
24 changes: 18 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
rust: ${{ steps.classify.outputs.rust }}
rust_full: ${{ steps.classify.outputs.rust_full }}
rust_packages: ${{ steps.classify.outputs.rust_packages }}
rust_fluent: ${{ steps.classify.outputs.rust_fluent }}
desktop: ${{ steps.classify.outputs.desktop }}
webui: ${{ steps.classify.outputs.webui }}
website: ${{ steps.classify.outputs.website }}
Expand All @@ -46,11 +47,11 @@ jobs:
run: |
set -euo pipefail
if [[ "$EVENT" != pull_request ]]; then
printf 'rust=true\nrust_full=true\nrust_packages=\ndesktop=true\nwebui=true\nwebsite=true\n' >>"$GITHUB_OUTPUT"
printf 'rust=true\nrust_full=true\nrust_packages=\nrust_fluent=true\ndesktop=true\nwebui=true\nwebsite=true\n' >>"$GITHUB_OUTPUT"
exit 0
fi
files="$(git diff --name-only "$(git merge-base "$BASE_SHA" HEAD)" HEAD)"
rust=false full=false desktop=false webui=false website=false
rust=false full=false fluent=false desktop=false webui=false website=false
packages=()
add_package() {
local pkg
Expand Down Expand Up @@ -80,8 +81,15 @@ jobs:
# The menu description has no window toolkit, so CI can test it.
# The Tauri binary stays excluded: the runner has no webkit.
desktop/menu/*) rust=true desktop=true; add_package rtbit-desktop-menu ;;
# The native app consumes the daemon's API types directly.
crates/librtbit/src/http_api_types.rs)
rust=true; fluent=true ;;
crates/librtbit/*) rust=true desktop=true; add_package swarmforge ;;
crates/rtbit/*) rust=true; add_package rtbit ;;
# The native client and UI crates are reverse dependencies of the
# fluent app, so changes to either must test the app as well.
crates/rtbit-client/*|crates/rtbit-ui-core/*)
rust=true; fluent=true ;;
website/*) website=true ;;
# An unrecognised crate path (a new member, or a path we have not
# mapped yet) is not safe to narrow, so it takes everything.
Expand All @@ -90,11 +98,11 @@ jobs:
done <<<"$files"
# A Rust change we could not attribute to a package still needs the
# full workspace rather than no check at all.
if [[ "$rust" == true && "$full" == false && ${#packages[@]} -eq 0 ]]; then
if [[ "$rust" == true && "$full" == false && "$fluent" == false && ${#packages[@]} -eq 0 ]]; then
full=true
fi
printf 'rust=%s\nrust_full=%s\nrust_packages=%s\ndesktop=%s\nwebui=%s\nwebsite=%s\n' \
"$rust" "$full" "${packages[*]-}" "$desktop" "$webui" "$website" | tee -a "$GITHUB_OUTPUT"
printf 'rust=%s\nrust_full=%s\nrust_packages=%s\nrust_fluent=%s\ndesktop=%s\nwebui=%s\nwebsite=%s\n' \
"$rust" "$full" "${packages[*]-}" "$fluent" "$desktop" "$webui" "$website" | tee -a "$GITHUB_OUTPUT"

# Shell checks for the release scripts and repository layout. They take
# seconds and touch no network, so they run on every event.
Expand Down Expand Up @@ -154,7 +162,7 @@ jobs:
with:
shared-key: ci
save-if: ${{ env.RUST_CACHE_SAVE_IF }}
- uses: taiki-e/install-action@8cca0918f8471c33515202b73f56ab27f2bed283 # v2.87.29
- uses: taiki-e/install-action@5488ac5a951645ce95062214902ac4b6bc1a1037 # v2.87.32
with:
tool: cargo-nextest
- uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
Expand All @@ -181,10 +189,14 @@ jobs:
- name: Test
env:
SCOPE_ARGS: ${{ steps.scope.outputs.args }}
RUST_FLUENT: ${{ needs.changes.outputs.rust_fluent }}
CARGO_PROFILE_TEST_DEBUG: 0
run: |
read -r -a args <<<"$SCOPE_ARGS"
cargo nextest run "${args[@]}" --all-targets --locked --no-default-features --features default-tls
if [[ "$RUST_FLUENT" == true ]]; then
cargo nextest run -p rtbit-fluent --all-targets --locked
fi
# The shipped binary is worth a release-profile compile on a PR that
# touches it. The queue builds it for every entry anyway.
- name: Build the release binary
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ jobs:
esac
fi
printf 'ref=%s\n' "$ref" >> "$GITHUB_OUTPUT"
- uses: github/codeql-action/init@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0
- uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
languages: ${{ matrix.language }}
- uses: github/codeql-action/analyze@6f2ac81f5cd81fe351a197ba0b00d91d03cd2aee # v4.39.0
- uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
category: /language:${{ matrix.language }}
ref: ${{ steps.target.outputs.ref }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/compat-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down Expand Up @@ -72,7 +72,7 @@ jobs:
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
63 changes: 62 additions & 1 deletion .github/workflows/container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
branches: [main, dev]
tags: ['v*']
workflow_dispatch:
merge_group:
types: [checks_requested]

permissions:
contents: read
Expand All @@ -16,6 +18,7 @@ concurrency:

jobs:
publish:
if: github.event_name != 'merge_group'
# Privileged publication capacity is selected only for this repository and
# this workflow deliberately has no pull_request trigger.
runs-on: [self-hosted, linux, docker, publish]
Expand All @@ -25,7 +28,7 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down Expand Up @@ -80,3 +83,61 @@ jobs:
-H 'Accept: application/vnd.oci.image.index.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.docker.distribution.manifest.v2+json' \
"https://ghcr.io/v2/thedancingdeveloper-org/rusttorrent/manifests/$tag" > manifest.json
jq -e '.schemaVersion == 2' manifest.json >/dev/null

smoke:
if: github.event_name == 'merge_group'
runs-on: [self-hosted, linux, docker, publish]
permissions:
contents: read
env:
IMAGE: rusttorrent-container-smoke:${{ github.sha }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Build the daemon image
run: docker build --tag "$IMAGE" --file Dockerfile .
- name: Start and probe the daemon
shell: bash
run: |
set -euo pipefail
volume="rusttorrent-smoke-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
container="rusttorrent-smoke-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}"
cleanup() {
docker rm --force "$container" >/dev/null 2>&1 || true
docker volume rm "$volume" >/dev/null 2>&1 || true
docker image rm "$IMAGE" >/dev/null 2>&1 || true
}
trap cleanup EXIT

docker volume create "$volume" >/dev/null
docker run --detach --name "$container" --volume "$volume:/home/rtbit/db" \
--publish 3030:3030 "$IMAGE" >/dev/null

deadline=$((SECONDS + 30))
setup_token=''
while (( SECONDS < deadline )); do
if ! setup_token=$(docker exec "$container" cat /home/rtbit/db/session/setup-token 2>/dev/null); then
setup_token=''
fi
if [[ -n "$setup_token" ]] && curl --fail --silent --show-error \
--output /dev/null http://127.0.0.1:3030/healthz; then
break
fi
sleep 1
done
[[ -n "$setup_token" ]]
(( SECONDS < deadline ))

curl --fail --silent --show-error \
--header 'Content-Type: application/json' \
--data "{\"username\":\"smoke\",\"password\":\"smoke-password\",\"setup_token\":\"$setup_token\"}" \
http://127.0.0.1:3030/api/v2/auth/setup >/dev/null
version=$(curl --fail --silent --show-error \
--user smoke:smoke-password http://127.0.0.1:3030/api/v2/app/webapiVersion)
[[ "$version" == '2.11.3' ]]
curl --fail --silent --show-error \
http://127.0.0.1:3030/healthz >/dev/null

docker stop --time 30 "$container" >/dev/null
[[ "$(docker inspect --format '{{.State.ExitCode}}' "$container")" == 0 ]]
docker run --rm --volume "$volume:/data" --entrypoint sh "$IMAGE" \
-c 'test -s /data/session/session.json'
19 changes: 19 additions & 0 deletions .github/workflows/policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,22 @@ jobs:
- name: Verify migration policies
shell: bash
run: bash ci/migration-policy.sh
- name: Detect dependency policy changes
id: dependency-policy
if: github.event_name == 'pull_request'
shell: bash
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
if git diff --quiet "$BASE_SHA" HEAD -- Cargo.lock ':(glob)**/Cargo.toml' deny.toml; then
echo "run=false" >> "$GITHUB_OUTPUT"
else
echo "run=true" >> "$GITHUB_OUTPUT"
fi
- uses: taiki-e/install-action@8cca0918f8471c33515202b73f56ab27f2bed283 # v2.87.29
if: github.event_name != 'pull_request' || steps.dependency-policy.outputs.run == 'true'
with:
tool: cargo-deny@0.20.2
- name: Verify Rust dependency policy
if: github.event_name != 'pull_request' || steps.dependency-policy.outputs.run == 'true'
run: cargo deny check advisories licenses bans sources
62 changes: 62 additions & 0 deletions .github/workflows/release-dry-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ jobs:
cargo build -p rtbit-fluent --release --target x86_64-pc-windows-msvc
rm -rf target/desktop-stage
bash packaging/scripts/build-desktop.sh windows "$tag" target/desktop-stage
- name: Smoke-test Windows fluent artifact
shell: bash
run: |
set -euo pipefail
version="$(sed -n 's/^version = "\(.*\)"/\1/p' crates/rtbit/Cargo.toml | head -1)"
tag="v$version"
expected="rtbit-fluent $version"
actual="$(target/desktop-stage/rtbit-fluent-"$tag"-windows-x86_64.exe --version)"
test "$actual" = "$expected"
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: release-dry-run-windows-fluent-${{ github.sha }}
Expand Down Expand Up @@ -157,6 +166,14 @@ jobs:
rm -rf target/desktop-stage
bash packaging/scripts/build-desktop.sh linux "$tag" target/desktop-stage
bash packaging/scripts/build-desktop.sh sbom "$tag" target/desktop-stage
- name: Smoke-test Linux fluent artifact
shell: bash
run: |
set -euo pipefail
tag="${{ steps.tag.outputs.tag }}"
expected="rtbit-fluent ${tag#v}"
actual="$(target/desktop-stage/rtbit-fluent-"$tag"-linux-x86_64 --version)"
test "$actual" = "$expected"
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
continue-on-error: true
with:
Expand Down Expand Up @@ -278,3 +295,48 @@ jobs:
done
test "$count" -eq 2 || { echo "::error::expected 2 signed executables (daemon and fluent), verified $count"; exit 1; }
(cd release-artifacts && sha256sum -c "SHA256SUMS-$tag.txt")

report-failure:
name: Report release dry-run failure
if: >-
${{ always() && github.event_name != 'pull_request' &&
(needs.build-windows-fluent.result == 'failure' || needs.dry-run.result == 'failure') }}
needs: [build-windows-fluent, dry-run]
runs-on: [self-hosted, linux]
permissions:
contents: read
issues: write
steps:
- name: Open or update the tracking issue
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const title = '[CI] Release dry run is failing';
const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const report = [
`The ${context.eventName} release dry run failed.`,
'',
`Run: ${runUrl}`,
`Commit: ${context.sha}`,
'',
'This workflow does not publish release artifacts.',
].join('\n');
const {data: issues} = await github.rest.issues.listForRepo({
...context.repo,
state: 'open',
per_page: 100,
});
const existing = issues.find(issue => !issue.pull_request && issue.title === title);
if (existing) {
await github.rest.issues.createComment({
...context.repo,
issue_number: existing.number,
body: report,
});
} else {
await github.rest.issues.create({
...context.repo,
title,
body: report,
});
}
Loading
Loading