name: Build Sidecar (Linux) on: workflow_dispatch: inputs: tag: description: 'Sidecar release tag to build (e.g. sidecar-v1.0.3)' required: true jobs: build-sidecar-linux: name: Build Sidecar (Linux) runs-on: ubuntu-latest env: PYTHON_VERSION: "3.11" RELEASE_TAG: "${{ inputs.tag }}" steps: - name: Show tag run: | echo "Building for tag: ${RELEASE_TAG}" - uses: actions/checkout@v4 with: ref: ${{ inputs.tag }} - name: Install uv run: | if command -v uv &> /dev/null; then echo "uv already installed: $(uv --version)" else curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> $GITHUB_PATH fi - name: Set up Python run: uv python install ${{ env.PYTHON_VERSION }} - name: Install system dependencies run: | sudo apt-get update sudo apt-get install -y portaudio19-dev - name: Build sidecar (CUDA) run: | uv sync --frozen || uv sync uv run pyinstaller local-transcription-headless.spec - name: Package sidecar (CUDA) run: | cd dist/local-transcription-backend && zip -r ../../sidecar-linux-x86_64-cuda.zip . - name: Build sidecar (CPU) run: | rm -rf dist/local-transcription-backend build/ uv pip install torch torchaudio --index-url https://download.pytorch.org/whl/cpu --force-reinstall # Run pyinstaller directly from venv to prevent uv run from # re-resolving torch back to the CUDA version via pyproject.toml sources .venv/bin/pyinstaller local-transcription-headless.spec - name: Package sidecar (CPU) run: | cd dist/local-transcription-backend && zip -r ../../sidecar-linux-x86_64-cpu.zip . - name: Upload to sidecar release env: BUILD_TOKEN: ${{ secrets.BUILD_TOKEN }} run: | sudo apt-get install -y jq REPO_API="${GITHUB_SERVER_URL}/api/v1/repos/${GITHUB_REPOSITORY}" TAG="${RELEASE_TAG}" echo "Waiting for sidecar release ${TAG} to be available..." for i in $(seq 1 30); do RELEASE_JSON=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \ "${REPO_API}/releases/tags/${TAG}") RELEASE_ID=$(echo "$RELEASE_JSON" | jq -r '.id // empty') if [ -n "${RELEASE_ID}" ] && [ "${RELEASE_ID}" != "null" ]; then echo "Found sidecar release: ${TAG} (ID: ${RELEASE_ID})" break fi echo "Attempt ${i}/30: Release not ready yet, retrying in 10s..." sleep 10 done if [ -z "${RELEASE_ID}" ] || [ "${RELEASE_ID}" = "null" ]; then echo "ERROR: Failed to find sidecar release for tag ${TAG} after 30 attempts." exit 1 fi for file in sidecar-*.zip; do filename=$(basename "$file") encoded_name=$(echo "$filename" | sed 's/ /%20/g') echo "Uploading ${filename} ($(du -h "$file" | cut -f1))..." ASSET_ID=$(curl -s -H "Authorization: token ${BUILD_TOKEN}" \ "${REPO_API}/releases/${RELEASE_ID}/assets" | jq -r ".[] | select(.name == \"${filename}\") | .id // empty") if [ -n "${ASSET_ID}" ]; then curl -s -X DELETE -H "Authorization: token ${BUILD_TOKEN}" \ "${REPO_API}/releases/${RELEASE_ID}/assets/${ASSET_ID}" fi HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ -H "Authorization: token ${BUILD_TOKEN}" \ -H "Content-Type: application/octet-stream" \ -T "$file" \ "${REPO_API}/releases/${RELEASE_ID}/assets?name=${encoded_name}") echo "Upload response: HTTP ${HTTP_CODE}" done