diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..08a1323 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +/.cargo +**/target/ +**/node_modules/ +/docker +/*.md +/Makefile +/LICENSE diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml new file mode 100644 index 0000000..d7f3415 --- /dev/null +++ b/.github/workflows/release-linux.yml @@ -0,0 +1,120 @@ +name: Release binaries for Linux and Docker + +on: + push: + tags: + - "v*.*.*" + +jobs: + build-docker-cross: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + platform: [linux/arm/v7, linux/amd64, linux/arm64] + steps: + - uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + id: builder1 + + - name: Cache + uses: actions/cache@v4 + id: cache + with: + path: | + usr-local-cargo-git-db + usr-local-cargo-registry-cache + usr-local-cargo-registry-index + src-target + key: docker-xx-v1-${{ matrix.platform }}-release + save-always: true + + - name: inject cache into docker + uses: reproducible-containers/buildkit-cache-dance@v3.1.0 + with: + cache-map: | + { + "usr-local-cargo-git-db": "/usr/local/cargo/git/db", + "usr-local-cargo-registry-cache": "/usr/local/cargo/registry/cache", + "usr-local-cargo-registry-index": "/usr/local/cargo/registry/index", + "src-target": "/src/target" + } + skip-extraction: ${{ steps.cache.outputs.cache-hit }} + + - name: cross-compile the binary + run: | + set -e + + mkdir -p target/cross + docker buildx ls + + mkdir -p target/cross/${{ matrix.platform }} + docker build --builder ${{ steps.builder1.outputs.name }} \ + --platform ${{ matrix.platform }} \ + -f docker/Dockerfile.xx \ + --output type=local,dest=target/cross/${{ matrix.platform }} ./ + + - name: list files + run: find target/cross/ + + - name: generate-archive-key + id: gen_artifact_key + run: | + echo "key=$(echo ${{ matrix.platform }} | tr '/' '-')" >> "$GITHUB_OUTPUT" + + - name: copy binary for release + run: | + cd target/cross + cp -l ${{ matrix.platform }}/arm/v7/rqbit rqbit-${{ steps.gen_artifact_key.outputs.key }} + + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: | + target/cross/rqbit-${{ steps.gen_artifact_key.outputs.key }} + + - name: Archive target/cross/ + uses: actions/upload-artifact@v4 + with: + name: ${{ steps.gen_artifact_key.outputs.key }} + path: target/cross/${{ matrix.platform }}/rqbit + + build-push-docker-multiarch: + runs-on: ubuntu-latest + needs: build-docker-cross + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + with: + name: linux-arm-v7 + path: target/cross/linux/arm/v7/rqbit + + - uses: actions/download-artifact@v4 + with: + name: linux-arm64 + path: target/cross/linux/arm64/rqbit + + - uses: actions/download-artifact@v4 + with: + name: linux-amd64 + path: target/cross/linux/amd64/rqbit + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v6 + with: + push: true + tags: ikatson/rqbit:${{ github.ref_name }} + platforms: linux/amd64,linux/arm64,linux/arm/v7 + context: target/cross/ + file: docker/Dockerfile diff --git a/.github/workflows/release-osx.yml b/.github/workflows/release-osx.yml new file mode 100644 index 0000000..342f131 --- /dev/null +++ b/.github/workflows/release-osx.yml @@ -0,0 +1,49 @@ +name: Release binaries for OSX + +on: + push: + tags: + - "v*.*.*" + +env: + CARGO_TERM_COLOR: always + +jobs: + release-macos: + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: install Tauri + run: cargo install tauri-cli --profile dev + - name: npm install (desktop) + working-directory: desktop + run: npm install + - name: npm install (librqbit/webui) + working-directory: crates/librqbit/webui + run: npm install + + - name: cargo tauri build + working-directory: desktop + run: + rustup target add aarch64-apple-darwin && rustup target add x86_64-apple-darwin && + cargo tauri build --target universal-apple-darwin --ci + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: | + desktop/src-tauri/target/universal-apple-darwin/release/bundle/dmg/rqbit-desktop_*_universal.dmg + + - name: Make a directory for output artifacts + run: mkdir -p target/artifacts + + - name: Build release OSX universal binary + run: rustup target install aarch64-apple-darwin && + cargo build --profile release-github --target x86_64-apple-darwin && + cargo build --profile release-github --target aarch64-apple-darwin && + lipo ./target/x86_64-apple-darwin/release-github/rqbit ./target/aarch64-apple-darwin/release-github/rqbit -create -output ./target/artifacts/rqbit-osx-universal + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: | + target/artifacts/rqbit-osx-universal diff --git a/.github/workflows/release-windows.yml b/.github/workflows/release-windows.yml new file mode 100644 index 0000000..ea8475d --- /dev/null +++ b/.github/workflows/release-windows.yml @@ -0,0 +1,40 @@ +name: Release binaries for Windows + +on: + push: + tags: + - "v*.*.*" + +env: + CARGO_TERM_COLOR: always + +jobs: + release-windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + - name: install Tauri + run: cargo install tauri-cli --profile dev + - name: npm install (desktop) + working-directory: desktop + run: npm install + - name: npm install (librqbit/webui) + working-directory: crates/librqbit/webui + run: npm install + + - name: cargo tauri build + working-directory: desktop + run: cargo tauri build --ci + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: | + desktop/src-tauri/target/release/bundle/msi/rqbit-desktop_*_x64_en-US.msi + + - name: Build release + run: cargo build --profile release-github + - uses: softprops/action-gh-release@v1 + with: + generate_release_notes: true + files: | + target/release-github/rqbit.exe diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index b1dfd0e..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,150 +0,0 @@ -name: Release binaries for all platforms - -on: - push: - tags: - - "v*.*.*" - -env: - CARGO_TERM_COLOR: always - -jobs: - release-windows: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - name: install Tauri - run: cargo install tauri-cli --profile dev - - name: npm install (desktop) - working-directory: desktop - run: npm install - - name: npm install (librqbit/webui) - working-directory: crates/librqbit/webui - run: npm install - - - name: cargo tauri build - working-directory: desktop - run: cargo tauri build --ci - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - desktop/src-tauri/target/release/bundle/msi/rqbit-desktop_*_x64_en-US.msi - - - name: Build release - run: cargo build --profile release-github - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - target/release-github/rqbit.exe - - cross-compile-on-macos: - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - - name: install Tauri - run: cargo install tauri-cli --profile dev - - name: npm install (desktop) - working-directory: desktop - run: npm install - - name: npm install (librqbit/webui) - working-directory: crates/librqbit/webui - run: npm install - - - name: cargo tauri build - working-directory: desktop - run: - rustup target add aarch64-apple-darwin && rustup target add x86_64-apple-darwin && - cargo tauri build --target universal-apple-darwin --ci - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - desktop/src-tauri/target/universal-apple-darwin/release/bundle/dmg/rqbit-desktop_*_universal.dmg - - - name: Make a directory for output artifacts - run: mkdir -p target/artifacts - - - name: Build release OSX universal binary - run: rustup target install aarch64-apple-darwin && - cargo build --profile release-github --target x86_64-apple-darwin && - cargo build --profile release-github --target aarch64-apple-darwin && - lipo ./target/x86_64-apple-darwin/release-github/rqbit ./target/aarch64-apple-darwin/release-github/rqbit -create -output ./target/artifacts/rqbit-osx-universal - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - target/artifacts/rqbit-osx-universal - - - name: install linux cross compiler toolchains - run: brew tap messense/macos-cross-toolchains && - brew install x86_64-unknown-linux-musl aarch64-unknown-linux-musl armv7-unknown-linux-musleabihf - - - name: Build release linux x86_64 binary - run: rustup target install x86_64-unknown-linux-musl && - make release-linux-x86_64 && - cp -l target/x86_64-unknown-linux-musl/release-github/rqbit target/artifacts/rqbit-linux-static-x86_64-musl - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - target/artifacts/rqbit-linux-static-x86_64-musl - - - name: Build release linux armv7 binary - run: rustup target install armv7-unknown-linux-musleabihf && - make release-linux-armv7 && - cp -l target/armv7-unknown-linux-musleabihf/release-github/rqbit target/artifacts/rqbit-linux-static-armv7-musl - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - target/artifacts/rqbit-linux-static-armv7-musl - - - name: Build release linux aarch64 binary - run: rustup target install aarch64-unknown-linux-musl && - make release-linux-aarch64 && - cp -l target/aarch64-unknown-linux-musl/release-github/rqbit target/artifacts/rqbit-linux-static-aarch64-musl - - uses: softprops/action-gh-release@v1 - with: - generate_release_notes: true - files: | - target/artifacts/rqbit-linux-static-aarch64-musl - - - name: Create target/docker - run: make create-target-docker - - - name: Archive target/docker/ - uses: actions/upload-artifact@v4 - with: - name: target-docker - path: target/docker/ - - build-push-docker: - runs-on: ubuntu-latest - needs: cross-compile-on-macos - steps: - - name: Download a single artifact - uses: actions/download-artifact@v4 - with: - name: target-docker - path: target/docker - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Login to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ vars.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Build and push - uses: docker/build-push-action@v6 - with: - push: true - tags: ikatson/rqbit:${{ github.ref_name }} - context: target/docker/ - platforms: linux/amd64,linux/arm64,linux/arm/v7 - file: target/docker/Dockerfile diff --git a/crates/librqbit/build.rs b/crates/librqbit/build.rs index a0e9bc0..079171b 100644 --- a/crates/librqbit/build.rs +++ b/crates/librqbit/build.rs @@ -7,7 +7,7 @@ fn run_cmd(cwd: &Path, cmd: &str) -> anyhow::Result<()> { #[cfg(target_os = "windows")] let (shell, shell_args) = ("powershell", ["-command"].as_slice()); #[cfg(not(target_os = "windows"))] - let (shell, shell_args) = ("bash", ["-c"].as_slice()); + let (shell, shell_args) = ("sh", ["-c"].as_slice()); // Run "npm install" in the webui directory let output = Command::new(shell) @@ -15,7 +15,14 @@ fn run_cmd(cwd: &Path, cmd: &str) -> anyhow::Result<()> { .arg(cmd) .current_dir(cwd) .output() - .with_context(|| format!("Failed to execute {} in {:?}", cmd, cwd))?; + .with_context(|| { + format!( + "Failed to execute {} in {:?}. PATH: {:?}", + cmd, + cwd, + std::env::var("PATH").unwrap_or_default() + ) + })?; if !output.status.success() { bail!( diff --git a/docker/Dockerfile b/docker/Dockerfile index f91c1e6..d000800 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,9 +1,10 @@ +# Depends on either outputs of Dockerfile.xx or the binaries compiled elsewhere. FROM scratch -ARG TARGETPLATFORM - ADD https://curl.se/ca/cacert.pem /etc/ssl/cacerts.pem +ARG TARGETPLATFORM + ## Assumes you are running this from respective context folder. COPY --chmod=755 ${TARGETPLATFORM}/rqbit /bin/rqbit diff --git a/docker/Dockerfile.xx b/docker/Dockerfile.xx new file mode 100644 index 0000000..c1bfd50 --- /dev/null +++ b/docker/Dockerfile.xx @@ -0,0 +1,42 @@ +# Dockerfile for cross compiling rqbit binaries from scratch inside docker. +FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx + +FROM --platform=$BUILDPLATFORM rust:alpine AS builder +COPY --from=xx / / + +RUN apk update && apk add clang lld npm python3 perl make + +ARG TARGETPLATFORM +RUN xx-apk add gcc musl-dev + +COPY / /src/ +WORKDIR /src/ + +ENV PROFILE_NAME=release-github +ENV PROFILE_FOLDER=release-github + +RUN --mount=type=cache,target=/usr/local/cargo/git/db \ + --mount=type=cache,target=/usr/local/cargo/registry/cache \ + --mount=type=cache,target=/usr/local/cargo/registry/index \ + --mount=type=cache,target=/src/target <