build.yml 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. name: CI
  2. on:
  3. push:
  4. branches: [main, master]
  5. paths:
  6. - '**/*.cpp'
  7. - '**/*.h'
  8. - '**/*.hpp'
  9. - '**/CMakeLists.txt'
  10. - '.github/workflows/**'
  11. pull_request:
  12. types: [opened, synchronize, reopened]
  13. workflow_dispatch:
  14. concurrency:
  15. group: ${{ github.workflow }}-${{ github.head_ref && github.ref || github.run_id }}
  16. cancel-in-progress: true
  17. env:
  18. # HuggingFace model info
  19. HF_MODEL_REPO: GaboxR67/MelBandRoformers
  20. HF_CHECKPOINT_PATH: melbandroformers/vocals/voc_fv6.ckpt
  21. HF_CONFIG_PATH: melbandroformers/vocals/voc_gabox.yaml
  22. # Music-Source-Separation-Training repo
  23. MSST_REPO: https://github.com/ZFTurbo/Music-Source-Separation-Training.git
  24. jobs:
  25. # ===========================================================================
  26. # Prepare: Generate test data (runs once, shared via artifacts)
  27. # ===========================================================================
  28. prepare-test-data:
  29. runs-on: ubuntu-latest
  30. steps:
  31. - name: Checkout
  32. uses: actions/checkout@v4
  33. - name: Setup Python
  34. uses: actions/setup-python@v5
  35. with:
  36. python-version: '3.11'
  37. cache: 'pip'
  38. - name: Clone MSST Repository
  39. run: git clone --depth 1 ${{ env.MSST_REPO }} msst
  40. - name: Install Dependencies
  41. run: |
  42. pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu
  43. pip install -r msst/requirements.txt
  44. pip install huggingface_hub scipy soundfile gguf librosa ml_collections einops pyyaml
  45. - name: Download Model from HuggingFace
  46. env:
  47. HF_TOKEN: ${{ secrets.HF_TOKEN }}
  48. run: |
  49. python -c "
  50. from huggingface_hub import hf_hub_download
  51. import os
  52. token = os.environ.get('HF_TOKEN') or None
  53. hf_hub_download('${{ env.HF_MODEL_REPO }}', '${{ env.HF_CHECKPOINT_PATH }}',
  54. local_dir='./model', token=token)
  55. hf_hub_download('${{ env.HF_MODEL_REPO }}', '${{ env.HF_CONFIG_PATH }}',
  56. local_dir='./model', token=token)
  57. "
  58. - name: Generate Test Audio
  59. run: |
  60. python -c "
  61. import numpy as np
  62. import scipy.io.wavfile as wav
  63. sr = 44100
  64. duration = 5.0
  65. t = np.linspace(0, duration, int(sr * duration))
  66. # Create a more complex test signal
  67. left = (np.sin(2 * np.pi * 440 * t) + 0.5 * np.sin(2 * np.pi * 880 * t)) * 0.3
  68. right = (np.sin(2 * np.pi * 660 * t) + 0.5 * np.sin(2 * np.pi * 1320 * t)) * 0.3
  69. stereo = np.stack([left, right], axis=1).astype(np.float32)
  70. wav.write('test_audio.wav', sr, stereo)
  71. print(f'Generated test audio: {len(t)} samples, {duration}s')
  72. "
  73. - name: Generate Test Data
  74. run: |
  75. python scripts/generate_test_data.py \
  76. --model-repo msst \
  77. --audio test_audio.wav \
  78. --checkpoint model/${{ env.HF_CHECKPOINT_PATH }} \
  79. --config model/${{ env.HF_CONFIG_PATH }} \
  80. --output test_data
  81. - name: Convert Model to GGUF
  82. run: |
  83. python scripts/convert_to_gguf.py \
  84. --ckpt model/${{ env.HF_CHECKPOINT_PATH }} \
  85. --config model/${{ env.HF_CONFIG_PATH }} \
  86. --out model.gguf \
  87. --dtype fp16
  88. - name: Upload Test Data Artifact
  89. uses: actions/upload-artifact@v4
  90. with:
  91. name: test-data
  92. path: |
  93. test_data/
  94. model.gguf
  95. test_audio.wav
  96. retention-days: 1
  97. # ===========================================================================
  98. # Build Matrix: Core Platforms + Vulkan
  99. # ===========================================================================
  100. build:
  101. needs: prepare-test-data
  102. strategy:
  103. fail-fast: false
  104. matrix:
  105. include:
  106. # Tier 1: Core Platforms (CPU)
  107. - { name: linux-x64-cpu, os: ubuntu-22.04, backend: cpu, test: true }
  108. - { name: linux-arm64-cpu, os: ubuntu-22.04-arm, backend: cpu, test: true }
  109. - { name: macos-arm64, os: macos-latest, backend: cpu, test: true }
  110. - { name: macos-x64, os: macos-15-intel, backend: cpu, test: true }
  111. - { name: windows-x64-msvc, os: windows-2025, backend: cpu, test: true }
  112. # Tier 2: Vulkan Backend
  113. - { name: linux-vulkan, os: ubuntu-24.04, backend: vulkan, test: true }
  114. - { name: windows-vulkan, os: windows-2025, backend: vulkan, test: true }
  115. runs-on: ${{ matrix.os }}
  116. steps:
  117. - name: Checkout
  118. uses: actions/checkout@v4
  119. with:
  120. submodules: recursive
  121. - name: Download Test Data
  122. uses: actions/download-artifact@v4
  123. with:
  124. name: test-data
  125. - name: Setup Python
  126. uses: actions/setup-python@v5
  127. with:
  128. python-version: '3.11'
  129. - name: Install Python Dependencies
  130. run: pip install numpy scipy
  131. # ----- Linux Dependencies -----
  132. - name: Install Dependencies (Linux)
  133. if: runner.os == 'Linux'
  134. run: |
  135. sudo apt-get update
  136. sudo apt-get install -y build-essential cmake
  137. - name: Install Vulkan SDK (Linux)
  138. if: matrix.backend == 'vulkan' && runner.os == 'Linux'
  139. run: |
  140. sudo apt-get install -y libvulkan-dev glslc mesa-vulkan-drivers
  141. # ----- macOS Dependencies -----
  142. - name: Install Dependencies (macOS)
  143. if: runner.os == 'macOS'
  144. run: brew install cmake
  145. # ----- Windows Dependencies -----
  146. - name: Install Dependencies (Windows)
  147. if: runner.os == 'Windows'
  148. run: choco install ninja -y
  149. - name: Install Vulkan SDK (Windows)
  150. if: matrix.backend == 'vulkan' && runner.os == 'Windows'
  151. run: |
  152. $VK_VERSION = "1.4.313.2"
  153. curl.exe -o VulkanSDK.exe -L "https://sdk.lunarg.com/sdk/download/${VK_VERSION}/windows/vulkansdk-windows-X64-${VK_VERSION}.exe"
  154. Start-Process -FilePath .\VulkanSDK.exe -ArgumentList "--accept-licenses --default-answer --confirm-command install" -Wait
  155. Add-Content $env:GITHUB_ENV "VULKAN_SDK=C:\VulkanSDK\${VK_VERSION}"
  156. Add-Content $env:GITHUB_PATH "C:\VulkanSDK\${VK_VERSION}\bin"
  157. # ----- Configure -----
  158. - name: Configure (Unix)
  159. if: runner.os != 'Windows'
  160. run: |
  161. cmake -B build \
  162. -DCMAKE_BUILD_TYPE=Release \
  163. -DGGML_CUDA=OFF \
  164. -DGGML_VULKAN=${{ matrix.backend == 'vulkan' && 'ON' || 'OFF' }} \
  165. -DMBR_BUILD_TESTS=ON \
  166. -DMBR_BUILD_CLI=ON
  167. - name: Configure (Windows)
  168. if: runner.os == 'Windows'
  169. run: |
  170. cmake -B build -G "Ninja Multi-Config" `
  171. -DGGML_CUDA=OFF `
  172. -DGGML_VULKAN=${{ matrix.backend == 'vulkan' && 'ON' || 'OFF' }} `
  173. -DMBR_BUILD_TESTS=ON `
  174. -DMBR_BUILD_CLI=ON
  175. # ----- Build -----
  176. - name: Build (Unix)
  177. if: runner.os != 'Windows'
  178. run: cmake --build build --config Release -j $(nproc 2>/dev/null || sysctl -n hw.logicalcpu)
  179. - name: Build (Windows)
  180. if: runner.os == 'Windows'
  181. run: cmake --build build --config Release -j $env:NUMBER_OF_PROCESSORS
  182. # ----- Unit Tests -----
  183. - name: Run Unit Tests
  184. if: matrix.test
  185. env:
  186. MBR_MODEL_PATH: ${{ github.workspace }}/model.gguf
  187. MBR_TEST_DATA_DIR: ${{ github.workspace }}/test_data
  188. run: ctest --test-dir build -C Release --output-on-failure --timeout 300
  189. # ----- CLI Tests -----
  190. - name: Test CLI
  191. if: matrix.test
  192. shell: bash
  193. env:
  194. MBR_MODEL_PATH: ${{ github.workspace }}/model.gguf
  195. run: |
  196. echo "=== CLI Test Suite ==="
  197. # Determine CLI path based on OS
  198. if [[ "$RUNNER_OS" == "Windows" ]]; then
  199. CLI="./build/bin/Release/mel_band_roformer-cli.exe"
  200. else
  201. CLI="./build/mel_band_roformer-cli"
  202. fi
  203. # 1. Test --help
  204. echo "[1/4] Testing --help..."
  205. $CLI --help
  206. # 2. Test with missing arguments (should fail)
  207. echo "[2/4] Testing error handling..."
  208. if $CLI 2>/dev/null; then
  209. echo "ERROR: CLI should fail without arguments"
  210. exit 1
  211. fi
  212. # 3. Generate test audio (short 2-second clip)
  213. echo "[3/4] Generating test audio..."
  214. python3 -c "
  215. import numpy as np
  216. import scipy.io.wavfile as wav
  217. sr = 44100
  218. t = np.linspace(0, 2.0, sr * 2)
  219. stereo = np.stack([np.sin(2*np.pi*440*t), np.sin(2*np.pi*880*t)], axis=1).astype(np.float32) * 0.5
  220. wav.write('cli_test_input.wav', sr, stereo)
  221. "
  222. # 4. Run full inference
  223. echo "[4/4] Running inference..."
  224. $CLI "$MBR_MODEL_PATH" cli_test_input.wav cli_test_output.wav --chunk-size 88200 --overlap 2
  225. # Verify output exists and has reasonable size
  226. if [[ ! -f cli_test_output.wav ]]; then
  227. echo "ERROR: Output file not created"
  228. exit 1
  229. fi
  230. OUTPUT_SIZE=$(stat -c%s cli_test_output.wav 2>/dev/null || stat -f%z cli_test_output.wav)
  231. if [[ $OUTPUT_SIZE -lt 1000 ]]; then
  232. echo "ERROR: Output file too small: $OUTPUT_SIZE bytes"
  233. exit 1
  234. fi
  235. echo "=== CLI Tests Passed ==="
  236. # ----- Upload Artifacts -----
  237. - name: Upload Build Artifacts
  238. uses: actions/upload-artifact@v4
  239. with:
  240. name: build-${{ matrix.name }}
  241. path: |
  242. build/bin/
  243. build/lib*/
  244. build/*.dll
  245. build/*.so
  246. build/*.dylib
  247. build/mel_band_roformer-cli*
  248. build/Release/
  249. retention-days: 7
  250. # ===========================================================================
  251. # CUDA Build: Linux (Compile Only - No GPU for testing)
  252. # ===========================================================================
  253. build-cuda-linux:
  254. runs-on: ubuntu-latest
  255. container: nvidia/cuda:12.6.2-devel-ubuntu24.04
  256. steps:
  257. - name: Checkout
  258. uses: actions/checkout@v4
  259. with:
  260. submodules: recursive
  261. - name: Install Dependencies
  262. run: |
  263. apt-get update
  264. apt-get install -y cmake build-essential ninja-build git
  265. - name: Configure
  266. run: |
  267. cmake -B build -G Ninja \
  268. -DCMAKE_BUILD_TYPE=Release \
  269. -DGGML_CUDA=ON \
  270. -DCMAKE_CUDA_ARCHITECTURES="75;80;86;89" \
  271. -DMBR_BUILD_TESTS=OFF \
  272. -DMBR_BUILD_CLI=ON
  273. - name: Build
  274. run: cmake --build build --config Release -j $(nproc)
  275. - name: Upload Artifacts
  276. uses: actions/upload-artifact@v4
  277. with:
  278. name: build-linux-cuda
  279. path: |
  280. build/bin/
  281. build/lib*/
  282. build/*.so
  283. retention-days: 7
  284. # ===========================================================================
  285. # CUDA Build: Windows (Compile Only - No GPU for testing)
  286. # ===========================================================================
  287. build-cuda-windows:
  288. runs-on: windows-2022
  289. env:
  290. CUDA_VERSION: '12.4'
  291. steps:
  292. - name: Checkout
  293. uses: actions/checkout@v4
  294. with:
  295. submodules: recursive
  296. - name: Install CUDA Toolkit
  297. run: |
  298. # Download and install CUDA toolkit components
  299. mkdir -p "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v${{ env.CUDA_VERSION }}"
  300. choco install unzip -y
  301. $components = @(
  302. "cuda_cudart-windows-x86_64-12.4.127-archive",
  303. "cuda_nvcc-windows-x86_64-12.4.131-archive",
  304. "cuda_nvrtc-windows-x86_64-12.4.127-archive",
  305. "libcublas-windows-x86_64-12.4.5.8-archive",
  306. "cuda_cccl-windows-x86_64-12.4.127-archive"
  307. )
  308. foreach ($comp in $components) {
  309. $url = "https://developer.download.nvidia.com/compute/cuda/redist/$($comp.Split('-')[0])/$($comp.Replace('cuda_', '').Split('-')[0])/windows-x86_64/$comp.zip"
  310. # Simplified: just use the base URL pattern
  311. }
  312. # For CI, use the official CUDA installer approach
  313. curl.exe -o cuda_installer.exe -L "https://developer.download.nvidia.com/compute/cuda/12.4.0/network_installers/cuda_12.4.0_windows_network.exe"
  314. Start-Process -FilePath .\cuda_installer.exe -ArgumentList "-s nvcc_12.4 cudart_12.4 cublas_12.4 cufft_12.4" -Wait -NoNewWindow
  315. Add-Content $env:GITHUB_ENV "CUDA_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.4"
  316. Add-Content $env:GITHUB_PATH "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.4\bin"
  317. - name: Install Ninja
  318. run: choco install ninja -y
  319. - name: Configure
  320. shell: cmd
  321. run: |
  322. call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
  323. cmake -B build -G "Ninja Multi-Config" ^
  324. -DGGML_CUDA=ON ^
  325. -DCMAKE_CUDA_ARCHITECTURES="75;80;86;89" ^
  326. -DMBR_BUILD_TESTS=OFF ^
  327. -DMBR_BUILD_CLI=ON
  328. - name: Build
  329. run: cmake --build build --config Release -j $env:NUMBER_OF_PROCESSORS
  330. - name: Upload Artifacts
  331. uses: actions/upload-artifact@v4
  332. with:
  333. name: build-windows-cuda
  334. path: |
  335. build/bin/
  336. build/Release/
  337. build/*.dll
  338. retention-days: 7