diff --git a/.cargo-clippy-flags b/.cargo-clippy-flags new file mode 100644 index 0000000..97c655c --- /dev/null +++ b/.cargo-clippy-flags @@ -0,0 +1 @@ +--workspace --exclude rtbit-desktop --no-default-features --features default-tls -- -D warnings diff --git a/.woodpecker.yml b/.woodpecker.yml index 1ae45e0..d71a2f0 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -3,6 +3,7 @@ when: branch: main - event: tag - event: manual + - event: pull_request steps: - name: fmt @@ -63,7 +64,11 @@ steps: - if [ -n "$CI_COMMIT_TAG" ]; then export CARGO_PROFILE_RELEASE_LTO=fat CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 CARGO_PROFILE_RELEASE_STRIP=symbols; fi - cargo build --profile release-github -p rtbit --no-default-features --features default-tls - ls -lh target/release-github/rtbit - - if [ -n "$CI_COMMIT_TAG" ]; then cargo install cargo-deb && cargo deb -p rtbit --no-build --no-strip --profile release-github -o target/release-github/rtbit_amd64.deb && ls -lh target/release-github/rtbit_amd64.deb; fi + - if [ -n "$CI_COMMIT_TAG" ]; then cargo install cargo-deb --registry crates-io && cargo deb -p rtbit --no-build --no-strip --profile release-github -o target/release-github/rtbit_amd64.deb && ls -lh target/release-github/rtbit_amd64.deb; fi + when: + - event: push + branch: main + - event: tag - name: build-windows image: rust:1.88-bookworm @@ -79,9 +84,13 @@ steps: - if [ -n "$CI_COMMIT_TAG" ]; then export CARGO_PROFILE_RELEASE_LTO=fat CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 CARGO_PROFILE_RELEASE_STRIP=symbols; fi - cargo build --profile release-github -p rtbit --target x86_64-pc-windows-gnu --no-default-features --features default-tls - ls -lh target/x86_64-pc-windows-gnu/release-github/rtbit.exe + when: + - event: push + branch: main + - event: tag - name: publish-release - image: alpine:3.21 + image: alpine:3.23 when: - event: tag environment: @@ -92,18 +101,73 @@ steps: - mkdir -p ~/.ssh - echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_ed25519 - chmod 600 ~/.ssh/id_ed25519 - - ssh-keyscan -H 100.92.4.57 >> ~/.ssh/known_hosts 2>/dev/null + - ssh-keyscan -H 100.92.4.57 >> ~/.ssh/known_hosts 2>/dev/null || true - echo "Publishing release $CI_COMMIT_TAG" - cp target/release-github/rtbit "rtbit-$CI_COMMIT_TAG-linux-x86_64" - cp target/x86_64-pc-windows-gnu/release-github/rtbit.exe "rtbit-$CI_COMMIT_TAG-windows-x86_64.exe" - cp target/release-github/rtbit_amd64.deb "rtbit-$CI_COMMIT_TAG-amd64.deb" 2>/dev/null || true - - sha256sum rtbit-$CI_COMMIT_TAG-* > "SHA256SUMS-$CI_COMMIT_TAG.txt" - - ssh -o StrictHostKeyChecking=accept-new root@100.92.4.57 "mkdir -p /root/downloads/rusttorrent/$CI_COMMIT_TAG" - - scp -o StrictHostKeyChecking=accept-new rtbit-$CI_COMMIT_TAG-* SHA256SUMS-$CI_COMMIT_TAG.txt root@100.92.4.57:/root/downloads/rusttorrent/$CI_COMMIT_TAG/ - - ssh -o StrictHostKeyChecking=accept-new root@100.92.4.57 "cd /root/downloads/rusttorrent/$CI_COMMIT_TAG && ln -sf rtbit-$CI_COMMIT_TAG-linux-x86_64 rtbit-linux-x86_64 && ln -sf rtbit-$CI_COMMIT_TAG-windows-x86_64.exe rtbit-windows-x86_64.exe" - - ssh -o StrictHostKeyChecking=accept-new root@100.92.4.57 "cd /root/downloads/rusttorrent && rm -rf latest && ln -s $CI_COMMIT_TAG latest" + - | + set -e + TAG="$CI_COMMIT_TAG" + sha256sum rtbit-$TAG-* > "SHA256SUMS-$TAG.txt" + ssh -o StrictHostKeyChecking=accept-new root@100.92.4.57 "mkdir -p /root/downloads/rusttorrent/$TAG" + scp -o StrictHostKeyChecking=accept-new rtbit-$TAG-* "SHA256SUMS-$TAG.txt" root@100.92.4.57:/root/downloads/rusttorrent/$TAG/ + ssh -o StrictHostKeyChecking=accept-new root@100.92.4.57 "cd /root/downloads/rusttorrent/$TAG && ln -sf rtbit-$TAG-linux-x86_64 rtbit-linux-x86_64 && ln -sf rtbit-$TAG-windows-x86_64.exe rtbit-windows-x86_64.exe" + ssh -o StrictHostKeyChecking=accept-new root@100.92.4.57 "ln -sfn $TAG /root/downloads/rusttorrent/latest" - echo "Published https://dl.rusttorrent.dev/latest/" + - name: forgejo-release + image: alpine:3.23 + when: + - event: tag + environment: + FORGEJO_TOKEN: + from_secret: git_auth_token + commands: + - apk add --no-cache curl jq + - | + TAG="$CI_COMMIT_TAG" + API="https://repo.indexarr.net/api/v1" + REPO="indexarr/rustTorrent" + echo "Creating Forgejo release $TAG" + + BODY="## Downloads\n\n" + BODY="$BODY- **Linux x86_64**: \`rtbit-$TAG-linux-x86_64\`\n" + BODY="$BODY- **Windows x86_64**: \`rtbit-$TAG-windows-x86_64.exe\`\n" + BODY="$BODY- **Debian/Ubuntu**: \`rtbit-$TAG-amd64.deb\`\n" + BODY="$BODY- **Docker**: \`ghcr.io/ausagentsmith-org/rusttorrent:$TAG\`\n" + BODY="$BODY\nSHA256 checksums in \`SHA256SUMS-$TAG.txt\`" + + # Delete existing release by tag if present (idempotent retry) + EXISTING_ID=$(curl -s -H "Authorization: token $FORGEJO_TOKEN" \ + "$API/repos/$REPO/releases/tags/$TAG" | jq -r '.id // empty') + if [ -n "$EXISTING_ID" ]; then + echo "Deleting existing release ID=$EXISTING_ID" + curl -s -X DELETE -H "Authorization: token $FORGEJO_TOKEN" \ + "$API/repos/$REPO/releases/$EXISTING_ID" + fi + + RELEASE_ID=$(curl -s -X POST \ + -H "Authorization: token $FORGEJO_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"tag_name\":\"$TAG\",\"name\":\"rustTorrent $TAG\",\"body\":\"$BODY\",\"draft\":false,\"prerelease\":true}" \ + "$API/repos/$REPO/releases" | jq -r '.id') + + if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then + echo "ERROR: Failed to create Forgejo release"; exit 1 + fi + echo "Forgejo release created: ID=$RELEASE_ID" + + for file in "rtbit-$TAG-linux-x86_64" "rtbit-$TAG-windows-x86_64.exe" "rtbit-$TAG-amd64.deb" "SHA256SUMS-$TAG.txt"; do + [ -f "$file" ] || continue + echo "Uploading $file" + curl -sf -X POST \ + -H "Authorization: token $FORGEJO_TOKEN" \ + -F "attachment=@$file" \ + "$API/repos/$REPO/releases/$RELEASE_ID/assets" > /dev/null + done + echo "Forgejo release $TAG complete" + - name: build-and-push image: woodpeckerci/plugin-docker-buildx when: @@ -135,18 +199,73 @@ steps: - PLUGIN_PASSWORD - name: push-ghcr - image: woodpeckerci/plugin-docker-buildx + image: quay.io/skopeo/stable when: - event: tag - settings: - repo: ghcr.io/ausagentsmith-org/rusttorrent - registry: ghcr.io - username: AusAgentSmith - password: + environment: + GH_TOKEN: from_secret: gh_release_token - tag: ["${CI_COMMIT_TAG}", "latest", "alpha"] - build_args_from_env: - - PLUGIN_PASSWORD + FORGEJO_TOKEN: + from_secret: git_auth_token + commands: + - SRC="docker://repo.indexarr.net/indexarr/rusttorrent:$CI_COMMIT_TAG" + - SRC_CREDS="--src-creds=$FORGEJO_TOKEN:$FORGEJO_TOKEN" + - DST_CREDS="--dest-creds=AusAgentSmith:$GH_TOKEN" + - for tag in $CI_COMMIT_TAG latest alpha; do skopeo copy $SRC_CREDS $DST_CREDS $SRC "docker://ghcr.io/ausagentsmith-org/rusttorrent:$tag"; done + + - name: github-release + image: alpine:3.23 + when: + - event: tag + environment: + GH_TOKEN: + from_secret: gh_release_token + commands: + - apk add --no-cache curl jq + - | + TAG="$CI_COMMIT_TAG" + REPO="AusAgentSmith-org/rustTorrent" + echo "Creating GitHub release $TAG on $REPO" + + BODY="## Downloads\n\n" + BODY="$BODY- **Linux x86_64**: \`rtbit-$TAG-linux-x86_64\`\n" + BODY="$BODY- **Windows x86_64**: \`rtbit-$TAG-windows-x86_64.exe\`\n" + BODY="$BODY- **Debian/Ubuntu**: \`rtbit-$TAG-amd64.deb\`\n" + BODY="$BODY- **Docker**: \`ghcr.io/ausagentsmith-org/rusttorrent:$TAG\`\n" + BODY="$BODY\nSHA256 checksums in \`SHA256SUMS-$TAG.txt\`" + + # Delete existing release by tag if present (idempotent retry) + EXISTING_ID=$(curl -s -H "Authorization: token $GH_TOKEN" \ + "https://api.github.com/repos/$REPO/releases/tags/$TAG" | jq -r '.id // empty') + if [ -n "$EXISTING_ID" ]; then + echo "Deleting existing GitHub release ID=$EXISTING_ID" + curl -s -X DELETE -H "Authorization: token $GH_TOKEN" \ + "https://api.github.com/repos/$REPO/releases/$EXISTING_ID" + curl -s -X DELETE -H "Authorization: token $GH_TOKEN" \ + "https://api.github.com/repos/$REPO/git/refs/tags/$TAG" || true + fi + + RELEASE_ID=$(curl -s -X POST \ + -H "Authorization: token $GH_TOKEN" \ + -H "Content-Type: application/json" \ + -d "{\"tag_name\":\"$TAG\",\"target_commitish\":\"main\",\"name\":\"rustTorrent $TAG\",\"body\":\"$BODY\",\"draft\":false,\"prerelease\":true}" \ + "https://api.github.com/repos/$REPO/releases" | jq -r '.id') + + if [ -z "$RELEASE_ID" ] || [ "$RELEASE_ID" = "null" ]; then + echo "ERROR: Failed to create GitHub release"; exit 1 + fi + echo "Release created: ID=$RELEASE_ID" + + for file in "rtbit-$TAG-linux-x86_64" "rtbit-$TAG-windows-x86_64.exe" "rtbit-$TAG-amd64.deb" "SHA256SUMS-$TAG.txt"; do + [ -f "$file" ] || continue + echo "Uploading $file" + curl -sf -X POST \ + -H "Authorization: token $GH_TOKEN" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@$file" \ + "https://uploads.github.com/repos/$REPO/releases/$RELEASE_ID/assets?name=$file" > /dev/null + done + echo "GitHub release $TAG complete" - name: discord-success image: alpine/curl diff --git a/Cargo.toml b/Cargo.toml index 309d220..78f9393 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ dht = { version = "0.1.1", registry = "forgejo", package = "librtbit-dht", defau librtbit-lsd = { version = "0.1.1", registry = "forgejo", default-features = false } peer_binary_protocol = { version = "0.1.1", registry = "forgejo", package = "librtbit-peer-protocol", default-features = false } sha1w = { version = "0.1.1", registry = "forgejo", package = "librtbit-sha1-wrapper", default-features = false } -tracker_comms = { version = "0.1.1", registry = "forgejo", package = "librtbit-tracker-comms", default-features = false } +tracker_comms = { version = "0.1.2", registry = "forgejo", package = "librtbit-tracker-comms", default-features = false } librtbit-upnp = { version = "0.1.1", registry = "forgejo" } upnp-serve = { version = "0.1.1", registry = "forgejo", package = "librtbit-upnp-serve", default-features = false } diff --git a/bench/docker-compose.yml b/bench/docker-compose.yml index 7f2158e..628db31 100644 --- a/bench/docker-compose.yml +++ b/bench/docker-compose.yml @@ -108,7 +108,7 @@ services: # ── Metrics: cAdvisor ────────────────────────────────────────────────── cadvisor: - image: gcr.io/cadvisor/cadvisor:v0.49.1 + image: gcr.io/cadvisor/cadvisor:v0.55.1 privileged: true volumes: - /:/rootfs:ro diff --git a/bench/seeder/Dockerfile b/bench/seeder/Dockerfile index 864dd1e..6da8640 100644 --- a/bench/seeder/Dockerfile +++ b/bench/seeder/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.21 +FROM alpine:3.23 RUN apk add --no-cache transmission-daemon curl RUN mkdir -p /config /data/testdata /data/torrents COPY settings.json /config/settings.json diff --git a/benchv2/Dockerfile b/benchv2/Dockerfile index 23bdb2a..4676c1a 100644 --- a/benchv2/Dockerfile +++ b/benchv2/Dockerfile @@ -7,7 +7,7 @@ COPY src/ src/ RUN cargo build --release && \ ./target/release/benchv2 --help > /dev/null -FROM alpine:3.21 +FROM alpine:3.23 RUN apk add --no-cache ca-certificates curl COPY --from=builder /app/target/release/benchv2 /usr/local/bin/benchv2 ENTRYPOINT ["benchv2"] diff --git a/crates/librtbit/webui/package.json b/crates/librtbit/webui/package.json index 6c4639a..d4011c4 100644 --- a/crates/librtbit/webui/package.json +++ b/crates/librtbit/webui/package.json @@ -37,6 +37,6 @@ "typescript": "^5.3.2", "typescript-eslint": "^8.57.1", "vite": "^7", - "vite-plugin-svgr": "^4.2.0" + "vite-plugin-svgr": "^5.2.0" } } diff --git a/package-lock.json b/package-lock.json index 5061fca..a1b6ed0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -75,7 +75,22 @@ "typescript": "^5.3.2", "typescript-eslint": "^8.57.1", "vite": "^7", - "vite-plugin-svgr": "^4.2.0" + "vite-plugin-svgr": "^5.2.0" + } + }, + "crates/librtbit/webui/node_modules/vite-plugin-svgr": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-5.2.0.tgz", + "integrity": "sha512-qj2eAKF8C6PZWemVTvQA0xgQIcP1hHU6Buh7fl6BhvayWwnuxE+z417miKxeDvRWbDrupQ1oK99hfxElopJ3sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.3.0", + "@svgr/core": "^8.1.0", + "@svgr/plugin-jsx": "^8.1.0" + }, + "peerDependencies": { + "vite": ">=3.0.0" } }, "desktop": { @@ -4745,21 +4760,6 @@ } } }, - "node_modules/vite-plugin-svgr": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/vite-plugin-svgr/-/vite-plugin-svgr-4.5.0.tgz", - "integrity": "sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.2.0", - "@svgr/core": "^8.1.0", - "@svgr/plugin-jsx": "^8.1.0" - }, - "peerDependencies": { - "vite": ">=2.6.0" - } - }, "node_modules/warning": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..ce10b6b --- /dev/null +++ b/renovate.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ], + "labels": [ + "dependencies" + ], + "schedule": [ + "before 6am on Monday" + ] +}