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..e197043 100644 --- a/crates/librtbit/webui/package.json +++ b/crates/librtbit/webui/package.json @@ -34,7 +34,7 @@ "eslint-plugin-react-refresh": "^0.5.2", "prettier": "^3.7", "tailwindcss": "^4.1.18", - "typescript": "^5.3.2", + "typescript": "^6.0.3", "typescript-eslint": "^8.57.1", "vite": "^7", "vite-plugin-svgr": "^4.2.0" diff --git a/package-lock.json b/package-lock.json index 5061fca..eee1654 100644 --- a/package-lock.json +++ b/package-lock.json @@ -72,12 +72,26 @@ "eslint-plugin-react-refresh": "^0.5.2", "prettier": "^3.7", "tailwindcss": "^4.1.18", - "typescript": "^5.3.2", + "typescript": "^6.0.3", "typescript-eslint": "^8.57.1", "vite": "^7", "vite-plugin-svgr": "^4.2.0" } }, + "crates/librtbit/webui/node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "desktop": { "name": "rtbit-desktop", "version": "0.0.1", @@ -4588,6 +4602,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" 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" + ] +}