thx Claude Code! #2450
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build and deploy workflow | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "バージョン情報(A.BB.C / A.BB.C-preview.D)" | |
| required: true | |
| code_signing: | |
| description: "コード署名する" | |
| type: boolean | |
| required: false | |
| default: false | |
| release: | |
| types: | |
| - published | |
| pull_request: | |
| push: | |
| env: | |
| # releaseタグ名か、workflow_dispatchでのバージョン名か、'0.0.0'が入る | |
| VERSION: ${{ github.event.release.tag_name || inputs.version || '0.0.0' }} | |
| # 簡易テストとするかどうか。mainブランチ、release、workflow_dispatch以外は簡易テストとする | |
| IS_SIMPLE_TEST: ${{ github.ref != 'refs/heads/main' && github.event_name != 'release' && github.event_name != 'workflow_dispatch' }} | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| # 全 jobs で利用する定数の定義。実行対象の条件をフィルタリングする。 | |
| # | |
| # c_release_format = plain-cdylib | ios-xcframework | |
| # | |
| # `plain-cdylib`の場合、動的ライブラリとその付属物をZIPに固めたものをC APIとしてリリースする。 | |
| # `ios-xcframework`の場合はiOS用のXCFrameworkをC APIとしてリリースする。また、ONNX Runtimeの | |
| # リンク方法に関わるCargoフィーチャも`c_release_format`によって選択される。 | |
| config: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| includes: ${{ steps.strategy_matrix.outputs.includes }} | |
| deploy: ${{ env.VERSION != '0.0.0' }} | |
| version: ${{ env.VERSION }} | |
| steps: | |
| - name: declare strategy matrix | |
| id: strategy_matrix | |
| run: | | |
| includes='[ | |
| { | |
| "os": "windows-2022", | |
| "target": "x86_64-pc-windows-msvc", | |
| "artifact_name": "windows-x64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": true, | |
| "java": true, | |
| "can_skip_in_simple_test": false | |
| }, | |
| { | |
| "os": "windows-2022", | |
| "target": "i686-pc-windows-msvc", | |
| "artifact_name": "windows-x86", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": true, | |
| "java": true, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "ubuntu-22.04", | |
| "target": "x86_64-unknown-linux-gnu", | |
| "artifact_name": "linux-x64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": true, | |
| "java": true, | |
| "can_skip_in_simple_test": false | |
| }, | |
| { | |
| "os": "ubuntu-22.04", | |
| "target": "aarch64-unknown-linux-gnu", | |
| "artifact_name": "linux-arm64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": true, | |
| "java": true, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "ubuntu-22.04", | |
| "target": "aarch64-linux-android", | |
| "artifact_name": "android-arm64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": false, | |
| "java": true, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "ubuntu-22.04", | |
| "target": "x86_64-linux-android", | |
| "artifact_name": "android-x86_64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": false, | |
| "java": true, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "macos-14", | |
| "target": "aarch64-apple-darwin", | |
| "artifact_name": "osx-arm64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": true, | |
| "java": true, | |
| "can_skip_in_simple_test": false | |
| }, | |
| { | |
| "os": "macos-15-intel", | |
| "target": "x86_64-apple-darwin", | |
| "artifact_name": "osx-x64", | |
| "c_release_format": "plain-cdylib", | |
| "python_whl": true, | |
| "java": true, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "macos-14", | |
| "target": "aarch64-apple-ios", | |
| "artifact_name": "ios-arm64-cpu", | |
| "c_release_format": "ios-xcframework", | |
| "python_whl": false, | |
| "java": false, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "macos-14", | |
| "target": "aarch64-apple-ios-sim", | |
| "artifact_name": "ios-arm64-cpu-sim", | |
| "c_release_format": "ios-xcframework", | |
| "python_whl": false, | |
| "java": false, | |
| "can_skip_in_simple_test": true | |
| }, | |
| { | |
| "os": "macos-15-intel", | |
| "target": "x86_64-apple-ios", | |
| "artifact_name": "ios-x64-cpu", | |
| "c_release_format": "ios-xcframework", | |
| "python_whl": false, | |
| "java": false, | |
| "can_skip_in_simple_test": true | |
| } | |
| ]' | |
| # FIXME: composite action に切り出す | |
| if ${{ env.IS_SIMPLE_TEST }}; then | |
| includes=$(echo "$includes" | jq -c '[.[] | select(.can_skip_in_simple_test == false)]') | |
| fi | |
| includes=$(echo "$includes" | jq -c '[.[] | del(.can_skip_in_simple_test)]') | |
| echo "includes=${includes}" >> "$GITHUB_OUTPUT" | |
| build_and_deploy: | |
| needs: config | |
| environment: ${{ inputs.code_signing && 'code_signing' || '' }} # コード署名用のenvironment | |
| strategy: | |
| matrix: | |
| include: ${{ fromJson(needs.config.outputs.includes) }} | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| ASSET_NAME: voicevox_core-${{ matrix.artifact_name }}-${{ needs.config.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| # NOTE: PyO3の制約で、RustのターゲットとPythonのビット数を一致させる必要がある。 | |
| # https://github.com/PyO3/pyo3/blob/v0.27.1/pyo3-ffi/build.rs#L138-L143 | |
| - name: Determine Python interpreter architecture | |
| if: matrix.python_whl | |
| id: python-interpreter-arch | |
| run: | | |
| case "$RUNNER_ARCH",${{ matrix.target }} in | |
| X64,i686-*) architecture=x86 ;; | |
| X64,x86_64-*|X64,aarch64-*) architecture=x64 ;; | |
| ARM64,aarch64-*) architecture=arm64 ;; | |
| *) | |
| echo 'unexpected architecture' >&2 | |
| exit 1 | |
| esac | |
| echo "architecture=$architecture" >> "$GITHUB_OUTPUT" | |
| - name: Set up Python 3.10 | |
| if: matrix.python_whl | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.10" | |
| architecture: ${{ steps.python-interpreter-arch.outputs.architecture }} | |
| - name: set up ${{ matrix.target }} | |
| uses: ./.github/actions/rust-toolchain-from-file | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Install cross compiler for aarch64-unknown-linux-gnu | |
| if: matrix.target == 'aarch64-unknown-linux-gnu' | |
| run: | | |
| sudo apt update | |
| sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu | |
| - name: Set path for android | |
| if: endsWith(matrix.target, '-linux-android') | |
| run: | | |
| echo "$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin" >> "$GITHUB_PATH" | |
| echo "AR_${{ matrix.target }}=llvm-ar" >> "$GITHUB_ENV" | |
| - name: Install cargo-binstall | |
| uses: taiki-e/install-action@cargo-binstall | |
| - name: Install cargo-edit | |
| run: cargo binstall cargo-edit@^0.11 --no-confirm --log-level debug | |
| - name: set cargo version | |
| run: | | |
| cargo set-version "$VERSION" --exclude voicevox_core_python_api --exclude xtask | |
| if ${{ matrix.python_whl }}; then | |
| sed -i_ 's/version = "\(0\.0\.0\)"/version = "'"$VERSION"'"/' ./crates/voicevox_core_python_api/pyproject.toml | |
| fi | |
| - name: cache target | |
| uses: Swatinem/rust-cache@v2 | |
| - name: build voicevox_core_c_api | |
| shell: bash | |
| run: | | |
| case ${{ matrix.c_release_format }} in | |
| plain-cdylib) linking=load-onnxruntime ;; | |
| ios-xcframework) linking=link-onnxruntime ;; | |
| esac | |
| cargo build -p voicevox_core_c_api -v --features "$linking" --target ${{ matrix.target }} --release | |
| env: | |
| RUSTFLAGS: -C panic=abort | |
| - name: build voicevox_core_python_api | |
| if: matrix.python_whl | |
| id: build-voicevox-core-python-api | |
| run: | | |
| rm -rf ./target/wheels | |
| pip install --upgrade poetry | |
| poetry config virtualenvs.create false | |
| (cd crates/voicevox_core_python_api && poetry install --with dev) | |
| maturin build --manifest-path ./crates/voicevox_core_python_api/Cargo.toml --target ${{ matrix.target }} --release | |
| echo "whl=$(find ./target/wheels -type f)" >> "$GITHUB_OUTPUT" | |
| - name: build voicevox_core_java_api | |
| if: ${{ matrix.java }} | |
| run: cargo build -p voicevox_core_java_api -vv --target ${{ matrix.target }} --release | |
| - name: Organize artifact | |
| run: | | |
| mkdir -p artifact/${{ env.ASSET_NAME }}/{include,lib} | |
| case ${{ matrix.c_release_format }} in | |
| plain-cdylib) feature=VOICEVOX_LOAD_ONNXRUNTIME ;; | |
| ios-xcframework) feature=VOICEVOX_LINK_ONNXRUNTIME ;; | |
| esac | |
| sed 's:^//\(#define '"$feature"'\)$:\1:' crates/voicevox_core_c_api/include/voicevox_core.h \ | |
| > "artifact/${{ env.ASSET_NAME }}/include/voicevox_core.h" | |
| cp -v target/${{ matrix.target }}/release/*voicevox_core.{dll,so,dylib} "artifact/${{ env.ASSET_NAME }}/lib" || true | |
| cp -v target/${{ matrix.target }}/release/voicevox_core.dll.lib "artifact/${{ env.ASSET_NAME }}/lib/voicevox_core.lib" || true | |
| cp -v README.md "artifact/${{ env.ASSET_NAME }}/README.txt" | |
| cp -v LICENSE "artifact/${{ env.ASSET_NAME }}/" | |
| echo "${{ env.VERSION }}" > "artifact/${{ env.ASSET_NAME }}/VERSION" | |
| mkdir java_artifact | |
| cp -v target/${{ matrix.target }}/release/*voicevox_core_java_api.{dll,so,dylib} "java_artifact" || true | |
| - name: Code signing (Windows) | |
| if: startsWith(matrix.os, 'windows') && inputs.code_signing | |
| run: bash build_util/codesign.bash "artifact/${{ env.ASSET_NAME }}/lib/voicevox_core.dll" | |
| env: | |
| ESIGNERCKA_USERNAME: ${{ secrets.ESIGNERCKA_USERNAME }} | |
| ESIGNERCKA_PASSWORD: ${{ secrets.ESIGNERCKA_PASSWORD }} | |
| ESIGNERCKA_TOTP_SECRET: ${{ secrets.ESIGNERCKA_TOTP_SECRET }} | |
| - name: Upload artifact to build XCFramework | |
| if: matrix.c_release_format == 'ios-xcframework' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: voicevox_core-${{ matrix.target }} | |
| path: artifact/${{ env.ASSET_NAME }} | |
| - name: Archive artifact | |
| run: | | |
| cd artifact | |
| 7z a "../${{ env.ASSET_NAME }}.zip" "${{ env.ASSET_NAME }}" | |
| - name: Upload to Release | |
| if: fromJson(needs.config.outputs.deploy) && matrix.c_release_format == 'plain-cdylib' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| prerelease: true | |
| tag_name: ${{ env.VERSION }} | |
| files: |- | |
| ${{ env.ASSET_NAME }}.zip | |
| target_commitish: ${{ github.sha }} | |
| - name: Upload Python whl to Release | |
| if: fromJson(needs.config.outputs.deploy) && matrix.python_whl | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| prerelease: true | |
| tag_name: ${{ env.VERSION }} | |
| files: |- | |
| ${{ steps.build-voicevox-core-python-api.outputs.whl }} | |
| target_commitish: ${{ github.sha }} | |
| - name: Upload voicevox_core_java_api artifact | |
| if: matrix.java | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: voicevox_core_java_api-${{ matrix.artifact_name }} | |
| path: java_artifact | |
| build_xcframework: | |
| if: ${{ !(github.ref != 'refs/heads/main' && github.event_name != 'release' && github.event_name != 'workflow_dispatch') }} # !env.IS_SIMPLE_TEST と同じ | |
| needs: [config, build_and_deploy] | |
| runs-on: macos-14 | |
| env: | |
| IOS_X86_64_PATH: artifact/voicevox_core-x86_64-apple-ios | |
| IOS_AARCH64_SIM_PATH: artifact/voicevox_core-aarch64-apple-ios-sim | |
| IOS_AARCH64_PATH: artifact/voicevox_core-aarch64-apple-ios | |
| ASSET_NAME: voicevox_core-ios-xcframework-cpu-${{ needs.config.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/download-artifact@v5 | |
| with: | |
| name: voicevox_core-x86_64-apple-ios | |
| path: ${{ env.IOS_X86_64_PATH }} | |
| - uses: actions/download-artifact@v5 | |
| with: | |
| name: voicevox_core-aarch64-apple-ios-sim | |
| path: ${{ env.IOS_AARCH64_SIM_PATH }} | |
| - uses: actions/download-artifact@v5 | |
| with: | |
| name: voicevox_core-aarch64-apple-ios | |
| path: ${{ env.IOS_AARCH64_PATH }} | |
| - name: Create xcframework | |
| id: create-xcframework | |
| run: | | |
| build_util/make_ios_xcframework.bash | |
| echo "output_asset_path=${OUTPUT_ASSET_PATH}" >> "$GITHUB_OUTPUT" | |
| env: | |
| OUTPUT_ASSET_PATH: artifact/voicevox_core-ios-xcframework-cpu | |
| - name: Archive artifact | |
| run: | | |
| cd ${{ steps.create-xcframework.outputs.output_asset_path }} | |
| 7z a "../../${{ env.ASSET_NAME }}.zip" "voicevox_core.xcframework" | |
| - name: Upload to Release | |
| if: fromJson(needs.config.outputs.deploy) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| prerelease: true | |
| tag_name: ${{ env.VERSION }} | |
| files: |- | |
| ${{ env.ASSET_NAME }}.zip | |
| target_commitish: ${{ github.sha }} | |
| build_java_package: | |
| runs-on: ubuntu-latest | |
| if: ${{ !(github.ref != 'refs/heads/main' && github.event_name != 'release' && github.event_name != 'workflow_dispatch') }} # !env.IS_SIMPLE_TEST と同じ | |
| needs: [config, build_and_deploy] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Set up Rust | |
| uses: ./.github/actions/rust-toolchain-from-file | |
| - name: Set up Java | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: "17" | |
| distribution: "adopt" | |
| - name: Install cargo-binstall | |
| uses: taiki-e/install-action@cargo-binstall | |
| - name: Install cargo-edit | |
| run: cargo binstall cargo-edit@^0.11 --no-confirm | |
| - name: set cargo version | |
| run: cargo set-version "$VERSION" -p voicevox_core_java_api | |
| - name: "Download artifact" | |
| uses: actions/download-artifact@v5 | |
| with: | |
| pattern: voicevox_core_java_api-* | |
| path: artifacts/ | |
| - name: Print tree | |
| run: tree artifacts | |
| - name: Build voicevoxcore | |
| run: | | |
| cd crates/voicevox_core_java_api | |
| function copy_dll() { | |
| artifact_name=$1 | |
| target=$2 | |
| root=$(echo "$1" | grep -q android && echo jniLibs || echo dll) | |
| dest=lib/src/main/resources/$root/$target | |
| case "$artifact_name" in | |
| windows-*) ext=dll ;; | |
| osx-*) ext=dylib ;; | |
| linux-*) ext=so ;; | |
| android-*) ext=so ;; | |
| *) echo "unknown target: $target"; exit 1 ;; | |
| esac | |
| mkdir -p "$dest" | |
| cp -v "../../artifacts/voicevox_core_java_api-$artifact_name"/*."$ext" "$dest" | |
| } | |
| function clean_dlls() { | |
| rm -rf lib/src/main/resources/dll | |
| rm -rf lib/src/main/resources/jniLibs | |
| } | |
| # desktop | |
| clean_dlls | |
| copy_dll windows-x64 windows-x64 | |
| copy_dll windows-x86 windows-x86 | |
| copy_dll linux-x64 linux-x64 | |
| copy_dll linux-arm64 linux-arm64 | |
| copy_dll osx-x64 macos-x64 | |
| copy_dll osx-arm64 macos-arm64 | |
| OS=desktop ./gradlew publishToMavenLocal | |
| # android | |
| clean_dlls | |
| copy_dll android-arm64 arm64-v8a | |
| copy_dll android-x86_64 x86_64 | |
| cp "$ANDROID_NDK"/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so lib/src/main/resources/jniLibs/arm64-v8a/ | |
| cp "$ANDROID_NDK"/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so lib/src/main/resources/jniLibs/x86_64/ | |
| OS=android ./gradlew publishToMavenLocal | |
| - name: Package | |
| run: | | |
| cd ~/.m2/repository | |
| rm -rf dev || true | |
| zip -r /tmp/java_packages.zip . | |
| - name: Upload to Release | |
| if: fromJson(needs.config.outputs.deploy) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| prerelease: true | |
| tag_name: ${{ env.VERSION }} | |
| files: |- | |
| /tmp/java_packages.zip | |
| target_commitish: ${{ github.sha }} | |
| download_test: | |
| needs: [config, build_and_deploy] | |
| if: fromJson(needs.config.outputs.deploy) | |
| uses: ./.github/workflows/download_test.yml | |
| with: | |
| version: ${{ inputs.version }} |