Skip to content

Fix call-quality bugs from the real Zoiper test: (1) embed the proces… #55

Fix call-quality bugs from the real Zoiper test: (1) embed the proces…

Fix call-quality bugs from the real Zoiper test: (1) embed the proces… #55

Workflow file for this run

name: Build and Release AgentBridge
# The release is now AUTOMATIC: pushing master with IsPrerelease=false in AgentBridge.csproj
# (in the pushed commit) triggers the wait for the dependency NuGet packages, the build of the
# 5 platform archives and the GitHub release — the tag v1.yy.MM.dd is created on the fly. No
# tag push and no release.ps1 invocation are needed anymore. With IsPrerelease=true, or when
# today's tag already exists, the run is skipped. See docs/RELEASING.md.
on:
push:
branches: [master]
workflow_dispatch:
permissions:
contents: write
jobs:
# Release gate: when IsPrerelease=true in AgentBridge.csproj the version carries a
# "-prerelease" suffix and no GitHub release is created. See AGENTS.md.
check-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.ver.outputs.version }}
do_release: ${{ steps.gate.outputs.do_release }}
steps:
- uses: actions/checkout@v4
with:
path: AgentBridge
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Detect version + release gate
id: ver
shell: bash
run: |
# -getProperty:Version prints the raw value (single property) — grep handles both
# raw ("1.26.08.09") and JSON ({"Properties":{"Version":"..."}}) output shapes.
VER=$(dotnet msbuild AgentBridge/AgentBridge.csproj -getProperty:Version -nologo | grep -oE '[0-9]+(\.[0-9]+)*(-[a-z0-9]+)?' | head -n1)
echo "version=$VER"
case "$VER" in *-prerelease*) echo "prerelease=true" ;; *) echo "prerelease=false" ;; esac
echo "prerelease=$(case "$VER" in *-prerelease*) echo true ;; *) echo false ;; esac)" >> "$GITHUB_OUTPUT"
echo "version=$VER" >> "$GITHUB_OUTPUT"
- name: Decide whether to release
id: gate
shell: bash
# The checkout above uses path: AgentBridge, so git must run from inside the repo
# (the workspace root is not a git repository — 'origin' does not exist there).
working-directory: AgentBridge
env:
VERSION: ${{ steps.ver.outputs.version }}
PRERELEASE: ${{ steps.ver.outputs.prerelease }}
run: |
if [ "$PRERELEASE" = "true" ]; then
echo "IsPrerelease=true -> prerelease build, no GitHub release"
echo "do_release=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if git ls-remote --tags origin "refs/tags/v$VERSION" | grep -q .; then
echo "Tag v$VERSION already exists -> no second release for this version"
echo "do_release=false" >> "$GITHUB_OUTPUT"
else
echo "do_release=true" >> "$GITHUB_OUTPUT"
fi
build:
needs: check-version
if: needs.check-version.outputs.do_release == 'true'
name: Build ${{ matrix.rid }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
rid: win-x64
ext: .exe
- os: ubuntu-latest
rid: linux-x64
ext: ''
# linux-arm64: supported since KokoroSharp 0.8.4 (phonemizer is the pure-managed
# MisakiSharp — no espeak-ng binary needed) + the native Microsoft.ML.OnnxRuntime
# package ships libonnxruntime.so for linux-arm64. Cross-compiled from the x64
# runner (pure managed code + RID-specific NuGet assets).
- os: ubuntu-latest
rid: linux-arm64
ext: ''
- os: macos-latest
rid: osx-x64
ext: ''
- os: macos-latest
rid: osx-arm64
ext: ''
steps:
- name: Checkout
uses: actions/checkout@v4
with:
path: AgentBridge
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
# The dependency NuGet packages are date-versioned (1.yy.MM.dd) and published by each
# repo's publish.yml when sync-all.ps1 pushed them; nuget.org propagation is not
# instant (official figures: up to 30 minutes). A GLOBAL 30-minute window from the start
# of the wait: each cycle checks ALL packages and ends as soon as every one is visible;
# after the window, packages still missing (only changed repos publish today) are
# reported with a warning and the build proceeds — the floating 1.* restore picks the
# latest available version, which for an unchanged repo is identical to today's version.
- name: Wait for dependency packages on NuGet
shell: bash
env:
VERSION: ${{ needs.check-version.outputs.version }}
run: |
NVER=$(printf '%s' "$VERSION" | awk -F. '{for(i=1;i<=NF;i++){gsub(/^0+/,"",$i); if($i=="")$i=0; printf "%s%s",(i>1?".":""),$i} print ""}')
echo "Waiting for dependency packages at version $NVER ..."
for i in $(seq 1 60); do
missing=""
for pkg in graphene.aiorchestrator alltomarkdown mermaidrendering graphene.reversemarkdown uisupportgeneric graphene.documenttool graphene.spreadsheettool; do
if curl -fsS "https://api.nuget.org/v3-flatcontainer/$pkg/index.json" | grep -q "\"$NVER\""; then
echo "$pkg $NVER available (attempt $i)"
else
missing="$missing $pkg"
fi
done
if [ -z "$missing" ]; then break; fi
sleep 30
done
if [ -n "$missing" ]; then
echo "::warning::after 30 min these packages are not yet at $NVER; proceeding with the latest available version (no publish for these repos today):$missing"
fi
# Builds against the published NuGet packages (Graphene.AIOrchestrator 1.* and its
# dependencies) — the sibling repos are private and never checked out here.
- name: Publish
shell: bash
run: |
dotnet publish AgentBridge/AgentBridge.csproj -c Release -r ${{ matrix.rid }} \
--self-contained true \
-p:PublishSingleFile=true \
-p:IncludeNativeLibrariesForSelfExtract=true \
-p:DebugType=None -p:DebugSymbols=false \
-o ./publish
# The archive deliberately ships kokoro.onnx (325 MB) plus the KokoroSharp
# voices/ + voices-zh/ content: single-file publish bundles managed code only,
# and the TTS endpoints need those assets next to the exe. The native
# onnxruntime engine is included per-RID by the Microsoft.ML.OnnxRuntime
# package (libonnxruntime.so / onnxruntime.dll).
#
# Tool plugins (Graphene.DocumentTool, Graphene.SpreadsheetTool) are loaded DYNAMICALLY
# from Tools/ by ToolPluginHost (byte-loaded, never referenced): the single-file publish
# cannot bundle them. Fetch the published packages and ship each plugin's assembly +
# XML docs into publish/Tools/<Plugin>/. (Graphene.OfficeTool is intentionally NOT
# fetched here — it is not part of the NuGet release set.)
- name: Fetch tool plugins into Tools/
shell: bash
env:
VERSION: ${{ needs.check-version.outputs.version }}
run: |
NVER=$(printf '%s' "$VERSION" | awk -F. '{for(i=1;i<=NF;i++){gsub(/^0+/,"",$i); if($i=="")$i=0; printf "%s%s",(i>1?".":""),$i} print ""}')
mkdir -p /tmp/plugins publish/Tools
for entry in "graphene.documenttool:DocumentTool" "graphene.spreadsheettool:SpreadsheetTool"; do
id="${entry%%:*}"; tool="${entry##*:}"
pver="$NVER"
# Fall back to the latest published version when today's is not out yet
# (only changed repos publish today's date-versioned package).
if ! curl -fsSI "https://api.nuget.org/v3-flatcontainer/$id/$NVER/$id.$NVER.nupkg" >/dev/null 2>&1; then
pver=$(curl -fsS "https://api.nuget.org/v3-flatcontainer/$id/index.json" | grep -oE '"[0-9]+(\.[0-9]+)+"' | tr -d '"' | sort -V | tail -n1)
fi
nupkg="/tmp/plugins/$id.$pver.nupkg"
if [ -z "$pver" ] || ! curl -fsSL -o "$nupkg" "https://api.nuget.org/v3-flatcontainer/$id/$pver/$id.$pver.nupkg"; then
echo "::warning::plugin package $id (fallback $pver) not found; tool '$tool' will be missing from Tools/"
continue
fi
tmp="/tmp/plugins/$tool"
mkdir -p "$tmp"
if command -v unzip >/dev/null 2>&1; then
unzip -qo "$nupkg" "lib/net10.0/*" -d "$tmp"
else
powershell -Command "Expand-Archive -Path '$nupkg' -DestinationPath '$tmp' -Force"
fi
mkdir -p "publish/Tools/$tool"
cp "$tmp"/lib/net10.0/$tool.dll "$tmp"/lib/net10.0/$tool.xml "publish/Tools/$tool/"
done
find publish/Tools -type f 2>/dev/null | sort || true
- name: Package
shell: bash
run: |
cd publish
tar -czf ../agentbridge-${{ matrix.rid }}.tar.gz .
cd ..
ls -lh agentbridge-${{ matrix.rid }}.tar.gz
- name: Upload archive
uses: actions/upload-artifact@v4
with:
name: agentbridge-${{ matrix.rid }}
path: agentbridge-${{ matrix.rid }}.tar.gz
release:
needs: [check-version, build]
if: needs.check-version.outputs.do_release == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download archives
uses: actions/download-artifact@v4
with:
path: artifacts
# Pin the tag to the commit that triggered this run (github.sha = the gate-off commit) so
# a later master push (e.g. the IsPrerelease restore after a button release) cannot move
# it. The GITHUB_TOKEN push does not re-trigger workflows. The tag is informational:
# nothing listens on it.
- name: Tag the triggering commit
shell: bash
run: |
git tag "v${{ needs.check-version.outputs.version }}" "$GITHUB_SHA"
git push origin "v${{ needs.check-version.outputs.version }}"
# Creates the GitHub release (the tag already exists) with all 5 platform archives.
- name: Create GitHub Release v${{ needs.check-version.outputs.version }}
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.check-version.outputs.version }}
files: artifacts/**/*.tar.gz