mirror of
https://github.com/remsky/Kokoro-FastAPI.git
synced 2025-08-05 16:48:53 +00:00
Bump version to 0.3.0 and update related configurations; add misaki patch script and remove obsolete build workflow
This commit is contained in:
parent
e2313abe72
commit
6a2d3a54cf
15 changed files with 411 additions and 297 deletions
87
.github/workflows/build-push.yml
vendored
87
.github/workflows/build-push.yml
vendored
|
@ -1,87 +0,0 @@
|
|||
name: Docker Build and push
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ 'v*.*.*' ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version to build and publish (e.g. v0.2.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
prepare-release:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.get-version.outputs.version }}
|
||||
is_prerelease: ${{ steps.check-prerelease.outputs.is_prerelease }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get version
|
||||
id: get-version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check if prerelease
|
||||
id: check-prerelease
|
||||
run: |
|
||||
echo "is_prerelease=${{ contains(steps.get-version.outputs.version, '-pre') }}" >> $GITHUB_OUTPUT
|
||||
|
||||
build-images:
|
||||
needs: prepare-release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
BUILDKIT_STEP_LOG_MAX_SIZE: 10485760
|
||||
# This environment variable will override the VERSION variable in your HCL file.
|
||||
VERSION: ${{ needs.prepare-release.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Free disk space
|
||||
run: |
|
||||
echo "Listing current disk space"
|
||||
df -h
|
||||
echo "Cleaning up disk space..."
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache
|
||||
docker system prune -af
|
||||
echo "Disk space after cleanup"
|
||||
df -h
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver-opts: |
|
||||
image=moby/buildkit:latest
|
||||
network=host
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push images
|
||||
run: |
|
||||
# No need to override VERSION via --set; the env var does the job.
|
||||
docker buildx bake --push
|
102
.github/workflows/docker-publish.yml
vendored
102
.github/workflows/docker-publish.yml
vendored
|
@ -1,102 +0,0 @@
|
|||
name: Docker Build and Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [ 'v*.*.*' ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Version to release (e.g. v0.2.0)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
prepare-release:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.get-version.outputs.version }}
|
||||
is_prerelease: ${{ steps.check-prerelease.outputs.is_prerelease }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get version
|
||||
id: get-version
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "version=${{ inputs.version }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "version=$(cat VERSION)" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check if prerelease
|
||||
id: check-prerelease
|
||||
run: echo "is_prerelease=${{ contains(steps.get-version.outputs.version, '-pre') }}" >> $GITHUB_OUTPUT
|
||||
|
||||
build-images:
|
||||
needs: prepare-release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Free disk space
|
||||
run: |
|
||||
echo "Listing current disk space"
|
||||
df -h
|
||||
echo "Cleaning up disk space..."
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
sudo rm -rf /opt/ghc
|
||||
sudo rm -rf /opt/hostedtoolcache
|
||||
docker system prune -af
|
||||
echo "Disk space after cleanup"
|
||||
df -h
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver-opts: |
|
||||
image=moby/buildkit:latest
|
||||
network=host
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push images
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
BUILDKIT_STEP_LOG_MAX_SIZE: 10485760
|
||||
VERSION: ${{ needs.prepare-release.outputs.version }}
|
||||
run: docker buildx bake --push
|
||||
|
||||
create-release:
|
||||
needs: [prepare-release, build-images]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ needs.prepare-release.outputs.version }}
|
||||
generate_release_notes: true
|
||||
draft: true
|
||||
prerelease: ${{ needs.prepare-release.outputs.is_prerelease }}
|
95
.github/workflows/release.yml
vendored
Normal file
95
.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
name: Create Release and Publish Docker Images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- release # Trigger when commits are pushed to the release branch (e.g., after merging master)
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- 'docs/**'
|
||||
|
||||
jobs:
|
||||
prepare-release:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.get-version.outputs.version }}
|
||||
version_tag: ${{ steps.get-version.outputs.version_tag }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get version from VERSION file
|
||||
id: get-version
|
||||
run: |
|
||||
VERSION_PLAIN=$(cat VERSION)
|
||||
echo "version=${VERSION_PLAIN}" >> $GITHUB_OUTPUT
|
||||
echo "version_tag=v${VERSION_PLAIN}" >> $GITHUB_OUTPUT # Add 'v' prefix for tag
|
||||
|
||||
build-images:
|
||||
needs: prepare-release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write # Needed to push images to GHCR
|
||||
env:
|
||||
DOCKER_BUILDKIT: 1
|
||||
BUILDKIT_STEP_LOG_MAX_SIZE: 10485760
|
||||
# This environment variable will override the VERSION variable in docker-bake.hcl
|
||||
VERSION: ${{ needs.prepare-release.outputs.version_tag }} # Use tag version (vX.Y.Z) for bake
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Free disk space # Optional: Keep if needed for large builds
|
||||
run: |
|
||||
echo "Listing current disk space"
|
||||
df -h
|
||||
echo "Cleaning up disk space..."
|
||||
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache
|
||||
docker system prune -af
|
||||
echo "Disk space after cleanup"
|
||||
df -h
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3 # Use v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3 # Use v3
|
||||
with:
|
||||
driver-opts: |
|
||||
image=moby/buildkit:latest
|
||||
network=host
|
||||
|
||||
- name: Log in to GitHub Container Registry
|
||||
uses: docker/login-action@v3 # Use v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push images using Docker Bake
|
||||
run: |
|
||||
echo "Building and pushing images for version ${{ needs.prepare-release.outputs.version_tag }}"
|
||||
# The VERSION env var above sets the tag for the bake file targets
|
||||
docker buildx bake --push
|
||||
|
||||
create-release:
|
||||
needs: [prepare-release, build-images]
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # Needed to create releases
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for release notes generation
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2 # Use v2
|
||||
with:
|
||||
tag_name: ${{ needs.prepare-release.outputs.version_tag }} # Use vX.Y.Z tag
|
||||
name: Release ${{ needs.prepare-release.outputs.version_tag }}
|
||||
generate_release_notes: true # Auto-generate release notes
|
||||
draft: false # Publish immediately
|
||||
prerelease: false # Mark as a stable release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
20
README.md
20
README.md
|
@ -3,12 +3,12 @@
|
|||
</p>
|
||||
|
||||
# <sub><sub>_`FastKoko`_ </sub></sub>
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
[](https://huggingface.co/spaces/Remsky/Kokoro-TTS-Zero)
|
||||
|
||||
[](https://github.com/hexgrad/kokoro)
|
||||
[](https://github.com/hexgrad/misaki)
|
||||
[](https://github.com/hexgrad/kokoro)
|
||||
[](https://github.com/hexgrad/misaki)
|
||||
|
||||
[](https://huggingface.co/hexgrad/Kokoro-82M/commit/9901c2b79161b6e898b7ea857ae5298f47b8b0d6)
|
||||
|
||||
|
@ -24,10 +24,6 @@ Dockerized FastAPI wrapper for [Kokoro-82M](https://huggingface.co/hexgrad/Kokor
|
|||
### Integration Guides
|
||||
[](https://github.com/remsky/Kokoro-FastAPI/wiki/Setup-Kubernetes) [](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-DigitalOcean) [](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-SillyTavern)
|
||||
[](https://github.com/remsky/Kokoro-FastAPI/wiki/Integrations-OpenWebUi)
|
||||
|
||||
|
||||
|
||||
|
||||
## Get Started
|
||||
|
||||
<details>
|
||||
|
@ -41,8 +37,8 @@ Refer to the core/config.py file for a full list of variables which can be manag
|
|||
# the `latest` tag can be used, but should not be considered stable as it may include `nightly` branch builds
|
||||
# it may have some bonus features however, and feedback/testing is welcome
|
||||
|
||||
docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:v0.2.2 # CPU, or:
|
||||
docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.2 #NVIDIA GPU
|
||||
docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:v0.3.0 # CPU, or:
|
||||
docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.3.0 #NVIDIA GPU
|
||||
```
|
||||
|
||||
|
||||
|
@ -66,7 +62,7 @@ docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.2 #NV
|
|||
# *Note for Apple Silicon (M1/M2) users:
|
||||
# The current GPU build relies on CUDA, which is not supported on Apple Silicon.
|
||||
# If you are on an M1/M2/M3 Mac, please use the `docker/cpu` setup.
|
||||
# MPS (Apple’s GPU acceleration) support is planned but not yet available.
|
||||
# MPS (Apple's GPU acceleration) support is planned but not yet available.
|
||||
|
||||
# Models will auto-download, but if needed you can manually download:
|
||||
python docker/scripts/download_model.py --output api/src/models/v1_0
|
||||
|
@ -139,8 +135,8 @@ with client.audio.speech.with_streaming_response.create(
|
|||
|
||||
</details>
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
<details>
|
||||
<summary>OpenAI-Compatible Speech Endpoint</summary>
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
v0.2.1
|
||||
0.3.0
|
||||
|
|
|
@ -2,8 +2,8 @@ apiVersion: v2
|
|||
name: kokoro-fastapi
|
||||
description: A Helm chart for deploying the Kokoro FastAPI TTS service to Kubernetes
|
||||
type: application
|
||||
version: 0.2.0
|
||||
appVersion: "0.2.0"
|
||||
version: 0.3.0
|
||||
appVersion: "0.3.0"
|
||||
|
||||
keywords:
|
||||
- tts
|
||||
|
|
|
@ -20,7 +20,7 @@ services:
|
|||
|
||||
# # Gradio UI service [Comment out everything below if you don't need it]
|
||||
# gradio-ui:
|
||||
# image: ghcr.io/remsky/kokoro-fastapi-ui:v0.2.0
|
||||
# image: ghcr.io/remsky/kokoro-fastapi-ui:v${VERSION}
|
||||
# # Uncomment below (and comment out above) to build from source instead of using the released image
|
||||
# build:
|
||||
# context: ../../ui
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
name: kokoro-tts-gpu
|
||||
services:
|
||||
kokoro-tts:
|
||||
# image: ghcr.io/remsky/kokoro-fastapi-gpu:v0.2.0
|
||||
# image: ghcr.io/remsky/kokoro-fastapi-gpu:v${VERSION}
|
||||
build:
|
||||
context: ../..
|
||||
dockerfile: docker/gpu/Dockerfile
|
||||
|
@ -24,7 +24,7 @@ services:
|
|||
|
||||
# # Gradio UI service
|
||||
# gradio-ui:
|
||||
# image: ghcr.io/remsky/kokoro-fastapi-ui:v0.2.0
|
||||
# image: ghcr.io/remsky/kokoro-fastapi-ui:v${VERSION}
|
||||
# # Uncomment below to build from source instead of using the released image
|
||||
# # build:
|
||||
# # context: ../../ui
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "kokoro-fastapi"
|
||||
version = "0.1.4"
|
||||
version = "0.3.0"
|
||||
description = "FastAPI TTS Service"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
|
@ -31,10 +31,11 @@ dependencies = [
|
|||
"matplotlib>=3.10.0",
|
||||
"mutagen>=1.47.0",
|
||||
"psutil>=6.1.1",
|
||||
"kokoro @ git+https://github.com/hexgrad/kokoro.git@31a2b6337b8c1b1418ef68c48142328f640da938",
|
||||
'misaki[en,ja,ko,zh] @ git+https://github.com/hexgrad/misaki.git@ebc76c21b66c5fc4866ed0ec234047177b396170',
|
||||
"spacy==3.7.2",
|
||||
"en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1-py3-none-any.whl",
|
||||
"espeakng-loader==0.2.4",
|
||||
"kokoro==0.9.2",
|
||||
"misaki[en,ja,ko,zh]==0.9.3",
|
||||
"spacy==3.8.5",
|
||||
"en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.8.0/en_core_web_sm-3.8.0-py3-none-any.whl",
|
||||
"inflect>=7.5.0",
|
||||
"phonemizer-fork>=3.3.2",
|
||||
"av>=14.2.0",
|
||||
|
@ -53,8 +54,8 @@ test = [
|
|||
"pytest-cov==6.0.0",
|
||||
"httpx==0.26.0",
|
||||
"pytest-asyncio==0.25.3",
|
||||
"openai>=1.59.6",
|
||||
"tomli>=2.0.1",
|
||||
"jinja2>=3.1.6"
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
|
|
11
readme-parts/config.yaml
Normal file
11
readme-parts/config.yaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
# README Configuration
|
||||
# version is now automatically loaded from the VERSION file
|
||||
tests_passed: "69"
|
||||
coverage: "52"
|
||||
kokoro_version: "0.7.9"
|
||||
kokoro_commit: "31a2b63"
|
||||
misaki_version: "0.7.9"
|
||||
misaki_commit: "ebc76c2"
|
||||
model_version: "1.0"
|
||||
model_commit: "9901c2b"
|
||||
model_commit_full: "9901c2b79161b6e898b7ea857ae5298f47b8b0d6"
|
45
scripts/fix_misaki.py
Normal file
45
scripts/fix_misaki.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
"""
|
||||
Patch for misaki package to fix the EspeakWrapper.set_data_path issue.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import importlib.util
|
||||
|
||||
# Find the misaki package
|
||||
try:
|
||||
import misaki
|
||||
misaki_path = os.path.dirname(misaki.__file__)
|
||||
print(f"Found misaki package at: {misaki_path}")
|
||||
except ImportError:
|
||||
print("Misaki package not found. Make sure it's installed.")
|
||||
sys.exit(1)
|
||||
|
||||
# Path to the espeak.py file
|
||||
espeak_file = os.path.join(misaki_path, "espeak.py")
|
||||
|
||||
if not os.path.exists(espeak_file):
|
||||
print(f"Could not find {espeak_file}")
|
||||
sys.exit(1)
|
||||
|
||||
# Read the current content
|
||||
with open(espeak_file, 'r') as f:
|
||||
content = f.read()
|
||||
|
||||
# Check if the problematic line exists
|
||||
if "EspeakWrapper.set_data_path(espeakng_loader.get_data_path())" in content:
|
||||
# Replace the problematic line
|
||||
new_content = content.replace(
|
||||
"EspeakWrapper.set_data_path(espeakng_loader.get_data_path())",
|
||||
"# Fixed line to use data_path attribute instead of set_data_path method\n"
|
||||
"EspeakWrapper.data_path = espeakng_loader.get_data_path()"
|
||||
)
|
||||
|
||||
# Write the modified content back
|
||||
with open(espeak_file, 'w') as f:
|
||||
f.write(new_content)
|
||||
|
||||
print(f"Successfully patched {espeak_file}")
|
||||
else:
|
||||
print(f"The problematic line was not found in {espeak_file}")
|
||||
print("The file may have already been patched or the issue is different.")
|
|
@ -4,40 +4,37 @@ import tomli
|
|||
from pathlib import Path
|
||||
|
||||
def extract_dependency_info():
|
||||
"""Extract version and commit hash for kokoro and misaki from pyproject.toml"""
|
||||
"""Extract version for kokoro and misaki from pyproject.toml"""
|
||||
with open("pyproject.toml", "rb") as f:
|
||||
pyproject = tomli.load(f)
|
||||
|
||||
deps = pyproject["project"]["dependencies"]
|
||||
info = {}
|
||||
kokoro_found = False
|
||||
misaki_found = False
|
||||
|
||||
# Extract kokoro info
|
||||
for dep in deps:
|
||||
if dep.startswith("kokoro @"):
|
||||
# Extract version from the dependency string if available
|
||||
version_match = re.search(r"kokoro @ git\+https://github\.com/hexgrad/kokoro\.git@", dep)
|
||||
if version_match:
|
||||
# If no explicit version, use v0.7.9 as shown in the README
|
||||
version = "v0.7.9"
|
||||
commit_match = re.search(r"@([a-f0-9]{7})", dep)
|
||||
if commit_match:
|
||||
info["kokoro"] = {
|
||||
"version": version,
|
||||
"commit": commit_match.group(1)
|
||||
}
|
||||
elif dep.startswith("misaki["):
|
||||
# Extract version from the dependency string if available
|
||||
version_match = re.search(r"misaki\[.*?\] @ git\+https://github\.com/hexgrad/misaki\.git@", dep)
|
||||
if version_match:
|
||||
# If no explicit version, use v0.7.9 as shown in the README
|
||||
version = "v0.7.9"
|
||||
commit_match = re.search(r"@([a-f0-9]{7})", dep)
|
||||
if commit_match:
|
||||
info["misaki"] = {
|
||||
"version": version,
|
||||
"commit": commit_match.group(1)
|
||||
}
|
||||
|
||||
# Match kokoro==version
|
||||
kokoro_match = re.match(r"^kokoro==(.+)$", dep)
|
||||
if kokoro_match:
|
||||
info["kokoro"] = {"version": kokoro_match.group(1)}
|
||||
kokoro_found = True
|
||||
|
||||
# Match misaki[...] ==version or misaki==version
|
||||
misaki_match = re.match(r"^misaki(?:\[.*?\])?==(.+)$", dep)
|
||||
if misaki_match:
|
||||
info["misaki"] = {"version": misaki_match.group(1)}
|
||||
misaki_found = True
|
||||
|
||||
# Stop if both found
|
||||
if kokoro_found and misaki_found:
|
||||
break
|
||||
|
||||
if not kokoro_found:
|
||||
raise ValueError("Kokoro version not found in pyproject.toml dependencies")
|
||||
if not misaki_found:
|
||||
raise ValueError("Misaki version not found in pyproject.toml dependencies")
|
||||
|
||||
return info
|
||||
|
||||
def run_pytest_with_coverage():
|
||||
|
@ -98,20 +95,24 @@ def update_readme_badges(passed_tests, coverage_percentage, dep_info):
|
|||
|
||||
# Update kokoro badge
|
||||
if "kokoro" in dep_info:
|
||||
# Find badge like kokoro-v0.9.2::abcdefg-BB5420 or kokoro-v0.9.2-BB5420
|
||||
kokoro_version = dep_info["kokoro"]["version"]
|
||||
content = re.sub(
|
||||
r'!\[Kokoro\]\(https://img\.shields\.io/badge/kokoro-[^)]+\)',
|
||||
f'',
|
||||
r'(!\[Kokoro\]\(https://img\.shields\.io/badge/kokoro-)[^)-]+(-BB5420\))',
|
||||
lambda m: f"{m.group(1)}{kokoro_version}{m.group(2)}",
|
||||
content
|
||||
)
|
||||
|
||||
# Update misaki badge
|
||||
if "misaki" in dep_info:
|
||||
# Find badge like misaki-v0.9.3::abcdefg-B8860B or misaki-v0.9.3-B8860B
|
||||
misaki_version = dep_info["misaki"]["version"]
|
||||
content = re.sub(
|
||||
r'!\[Misaki\]\(https://img\.shields\.io/badge/misaki-[^)]+\)',
|
||||
f'',
|
||||
r'(!\[Misaki\]\(https://img\.shields\.io/badge/misaki-)[^)-]+(-B8860B\))',
|
||||
lambda m: f"{m.group(1)}{misaki_version}{m.group(2)}",
|
||||
content
|
||||
)
|
||||
|
||||
|
||||
readme_path.write_text(content)
|
||||
return True
|
||||
|
||||
|
@ -128,11 +129,11 @@ def main():
|
|||
print(f"- Tests: {passed_tests} passed")
|
||||
print(f"- Coverage: {coverage_percentage}%")
|
||||
if "kokoro" in dep_info:
|
||||
print(f"- Kokoro: {dep_info['kokoro']['version']}::{dep_info['kokoro']['commit']}")
|
||||
print(f"- Kokoro: {dep_info['kokoro']['version']}")
|
||||
if "misaki" in dep_info:
|
||||
print(f"- Misaki: {dep_info['misaki']['version']}::{dep_info['misaki']['commit']}")
|
||||
print(f"- Misaki: {dep_info['misaki']['version']}")
|
||||
else:
|
||||
print("Failed to update badges")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
195
scripts/update_version.py
Executable file
195
scripts/update_version.py
Executable file
|
@ -0,0 +1,195 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Version Update Script
|
||||
|
||||
This script reads the version from the VERSION file and updates references
|
||||
in pyproject.toml, the Helm chart, and README.md.
|
||||
"""
|
||||
|
||||
import re
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
|
||||
# Get the project root directory
|
||||
ROOT_DIR = Path(__file__).parent.parent
|
||||
|
||||
# --- Configuration ---
|
||||
VERSION_FILE = ROOT_DIR / "VERSION"
|
||||
PYPROJECT_FILE = ROOT_DIR / "pyproject.toml"
|
||||
HELM_CHART_FILE = ROOT_DIR / "charts" / "kokoro-fastapi" / "Chart.yaml"
|
||||
README_FILE = ROOT_DIR / "README.md"
|
||||
# --- End Configuration ---
|
||||
|
||||
def update_pyproject(version: str):
|
||||
"""Updates the version in pyproject.toml"""
|
||||
if not PYPROJECT_FILE.exists():
|
||||
print(f"Skipping: {PYPROJECT_FILE} not found.")
|
||||
return
|
||||
|
||||
try:
|
||||
content = PYPROJECT_FILE.read_text()
|
||||
# Regex to find and capture current version = "X.Y.Z" under [project]
|
||||
pattern = r'(^\[project\]\s*(?:.*\s)*?version\s*=\s*)"([^"]+)"'
|
||||
match = re.search(pattern, content, flags=re.MULTILINE)
|
||||
|
||||
if not match:
|
||||
print(f"Warning: Version pattern not found in {PYPROJECT_FILE}")
|
||||
return
|
||||
|
||||
current_version = match.group(2)
|
||||
if current_version == version:
|
||||
print(f"Already up-to-date: {PYPROJECT_FILE} (version {version})")
|
||||
else:
|
||||
# Perform replacement
|
||||
new_content = re.sub(pattern, rf'\1"{version}"', content, count=1, flags=re.MULTILINE)
|
||||
PYPROJECT_FILE.write_text(new_content)
|
||||
print(f"Updated {PYPROJECT_FILE} from {current_version} to {version}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing {PYPROJECT_FILE}: {e}")
|
||||
|
||||
def update_helm_chart(version: str):
|
||||
"""Updates the version and appVersion in the Helm chart"""
|
||||
if not HELM_CHART_FILE.exists():
|
||||
print(f"Skipping: {HELM_CHART_FILE} not found.")
|
||||
return
|
||||
|
||||
try:
|
||||
content = HELM_CHART_FILE.read_text()
|
||||
original_content = content
|
||||
updated_count = 0
|
||||
|
||||
# Update 'version:' line (unquoted)
|
||||
# Looks for 'version:' followed by optional whitespace and the version number
|
||||
version_pattern = r"^(version:\s*)(\S+)"
|
||||
current_version_match = re.search(version_pattern, content, flags=re.MULTILINE)
|
||||
if current_version_match and current_version_match.group(2) != version:
|
||||
content = re.sub(version_pattern, rf"\g<1>{version}", content, count=1, flags=re.MULTILINE)
|
||||
print(f"Updating 'version' in {HELM_CHART_FILE} from {current_version_match.group(2)} to {version}")
|
||||
updated_count += 1
|
||||
elif current_version_match:
|
||||
print(f"Already up-to-date: 'version' in {HELM_CHART_FILE} is {version}")
|
||||
else:
|
||||
print(f"Warning: 'version:' pattern not found in {HELM_CHART_FILE}")
|
||||
|
||||
|
||||
# Update 'appVersion:' line (quoted or unquoted)
|
||||
# Looks for 'appVersion:' followed by optional whitespace, optional quote, the version, optional quote
|
||||
app_version_pattern = r"^(appVersion:\s*)(\"?)([^\"\s]+)(\"?)"
|
||||
current_app_version_match = re.search(app_version_pattern, content, flags=re.MULTILINE)
|
||||
|
||||
if current_app_version_match:
|
||||
leading_whitespace = current_app_version_match.group(1) # e.g., "appVersion: "
|
||||
opening_quote = current_app_version_match.group(2) # e.g., '"' or ''
|
||||
current_app_ver = current_app_version_match.group(3) # e.g., '0.2.0'
|
||||
closing_quote = current_app_version_match.group(4) # e.g., '"' or ''
|
||||
|
||||
# Check if quotes were consistent (both present or both absent)
|
||||
if opening_quote != closing_quote:
|
||||
print(f"Warning: Inconsistent quotes found for appVersion in {HELM_CHART_FILE}. Skipping update for this line.")
|
||||
elif current_app_ver == version and opening_quote == '"': # Check if already correct *and* quoted
|
||||
print(f"Already up-to-date: 'appVersion' in {HELM_CHART_FILE} is \"{version}\"")
|
||||
else:
|
||||
# Always replace with the quoted version
|
||||
replacement = f'{leading_whitespace}"{version}"' # Ensure quotes
|
||||
original_display = f"{opening_quote}{current_app_ver}{closing_quote}" # How it looked before
|
||||
target_display = f'"{version}"' # How it should look
|
||||
|
||||
# Only report update if the displayed value actually changes
|
||||
if original_display != target_display:
|
||||
content = re.sub(app_version_pattern, replacement, content, count=1, flags=re.MULTILINE)
|
||||
print(f"Updating 'appVersion' in {HELM_CHART_FILE} from {original_display} to {target_display}")
|
||||
updated_count += 1
|
||||
else:
|
||||
# It matches the target version but might need quoting fixed silently if we didn't update
|
||||
# Or it was already correct. Check if content changed. If not, report up-to-date.
|
||||
if not (content != original_content and updated_count > 0): # Avoid double message if version also changed
|
||||
print(f"Already up-to-date: 'appVersion' in {HELM_CHART_FILE} is {target_display}")
|
||||
|
||||
|
||||
else:
|
||||
print(f"Warning: 'appVersion:' pattern not found in {HELM_CHART_FILE}")
|
||||
|
||||
|
||||
# Write back only if changes were made
|
||||
if content != original_content:
|
||||
HELM_CHART_FILE.write_text(content)
|
||||
# Confirmation message printed above during the specific update
|
||||
elif updated_count == 0 and current_version_match and current_app_version_match :
|
||||
# If no updates were made but patterns were found, confirm it's up-to-date overall
|
||||
print(f"Already up-to-date: {HELM_CHART_FILE} (version {version})")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing {HELM_CHART_FILE}: {e}")
|
||||
|
||||
def update_readme(version_with_v: str):
|
||||
"""Updates Docker image tags in README.md"""
|
||||
if not README_FILE.exists():
|
||||
print(f"Skipping: {README_FILE} not found.")
|
||||
return
|
||||
|
||||
try:
|
||||
content = README_FILE.read_text()
|
||||
# Regex to find and capture current ghcr.io/.../kokoro-fastapi-(cpu|gpu):vX.Y.Z
|
||||
pattern = r'(ghcr\.io/remsky/kokoro-fastapi-(?:cpu|gpu)):(v\d+\.\d+\.\d+)'
|
||||
matches = list(re.finditer(pattern, content)) # Find all occurrences
|
||||
|
||||
if not matches:
|
||||
print(f"Warning: Docker image tag pattern not found in {README_FILE}")
|
||||
else:
|
||||
updated_needed = False
|
||||
for match in matches:
|
||||
current_tag = match.group(2)
|
||||
if current_tag != version_with_v:
|
||||
updated_needed = True
|
||||
break # Only need one mismatch to trigger update
|
||||
|
||||
if updated_needed:
|
||||
# Perform replacement on all occurrences
|
||||
new_content = re.sub(pattern, rf'\1:{version_with_v}', content)
|
||||
README_FILE.write_text(new_content)
|
||||
print(f"Updated Docker image tags in {README_FILE} to {version_with_v}")
|
||||
else:
|
||||
print(f"Already up-to-date: Docker image tags in {README_FILE} (version {version_with_v})")
|
||||
|
||||
# Check for ':latest' tag usage remains the same
|
||||
if ':latest' in content:
|
||||
print(f"Warning: Found ':latest' tag in {README_FILE}. Consider updating manually if needed.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error processing {README_FILE}: {e}")
|
||||
|
||||
|
||||
def main():
|
||||
# Read the version from the VERSION file
|
||||
if not VERSION_FILE.exists():
|
||||
print(f"Error: {VERSION_FILE} not found.")
|
||||
return
|
||||
|
||||
try:
|
||||
version = VERSION_FILE.read_text().strip()
|
||||
if not re.match(r"^\d+\.\d+\.\d+$", version):
|
||||
print(f"Error: Invalid version format '{version}' in {VERSION_FILE}. Expected X.Y.Z")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"Error reading {VERSION_FILE}: {e}")
|
||||
return
|
||||
|
||||
print(f"Read version: {version} from {VERSION_FILE}")
|
||||
print("-" * 20)
|
||||
|
||||
# Prepare versions (with and without 'v')
|
||||
version_plain = version
|
||||
version_with_v = f"v{version}"
|
||||
|
||||
# Update files
|
||||
update_pyproject(version_plain)
|
||||
update_helm_chart(version_plain)
|
||||
update_readme(version_with_v)
|
||||
|
||||
print("-" * 20)
|
||||
print("Version update script finished.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -1,49 +0,0 @@
|
|||
{
|
||||
"document": "doc.report.command",
|
||||
"version": "ov/command/slim/1.1",
|
||||
"engine": "linux/amd64|ALP|x.1.42.2|29e62e7836de7b1004607c51c502537ffe1969f0|2025-01-16_07:48:54AM|x",
|
||||
"containerized": false,
|
||||
"host_distro": {
|
||||
"name": "Ubuntu",
|
||||
"version": "22.04",
|
||||
"display_name": "Ubuntu 22.04.5 LTS"
|
||||
},
|
||||
"type": "slim",
|
||||
"state": "error",
|
||||
"target_reference": "kokoro-fastapi:latest",
|
||||
"system": {
|
||||
"type": "",
|
||||
"release": "",
|
||||
"distro": {
|
||||
"name": "",
|
||||
"version": "",
|
||||
"display_name": ""
|
||||
}
|
||||
},
|
||||
"source_image": {
|
||||
"identity": {
|
||||
"id": ""
|
||||
},
|
||||
"size": 0,
|
||||
"size_human": "",
|
||||
"create_time": "",
|
||||
"architecture": "",
|
||||
"container_entry": {
|
||||
"exe_path": ""
|
||||
}
|
||||
},
|
||||
"minified_image_size": 0,
|
||||
"minified_image_size_human": "",
|
||||
"minified_image": "",
|
||||
"minified_image_id": "",
|
||||
"minified_image_digest": "",
|
||||
"minified_image_has_data": false,
|
||||
"minified_by": 0,
|
||||
"artifact_location": "",
|
||||
"container_report_name": "",
|
||||
"seccomp_profile_name": "",
|
||||
"apparmor_profile_name": "",
|
||||
"image_stack": null,
|
||||
"image_created": false,
|
||||
"image_build_engine": ""
|
||||
}
|
|
@ -10,9 +10,17 @@ export PYTHONPATH=$PROJECT_ROOT:$PROJECT_ROOT/api
|
|||
export MODEL_DIR=src/models
|
||||
export VOICES_DIR=src/voices/v1_0
|
||||
export WEB_PLAYER_PATH=$PROJECT_ROOT/web
|
||||
# Set the espeak-ng data path to your location
|
||||
export ESPEAK_DATA_PATH=/usr/lib/x86_64-linux-gnu/espeak-ng-data
|
||||
|
||||
# Run FastAPI with CPU extras using uv run
|
||||
# Note: espeak may still require manual installation,
|
||||
uv pip install -e ".[cpu]"
|
||||
uv run --no-sync python docker/scripts/download_model.py --output api/src/models/v1_0
|
||||
|
||||
# Apply the misaki patch to fix possible EspeakWrapper issue in older versions
|
||||
# echo "Applying misaki patch..."
|
||||
# python scripts/fix_misaki.py
|
||||
|
||||
# Start the server
|
||||
uv run --no-sync uvicorn api.src.main:app --host 0.0.0.0 --port 8880
|
||||
|
|
Loading…
Add table
Reference in a new issue