Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
2ac0984
fix(ci): deploy Pages from develop only; unstick /download
justcoding121 Aug 31, 2026
8d6d1f8
Merge pull request #1004 from justcoding121/fix/pages-deploy-develop-…
justcoding121 Aug 31, 2026
33811fa
fix: github.io site base path + Sonar S4036 powershell paths
justcoding121 Aug 31, 2026
ca2b95c
Merge pull request #1005 from justcoding121/fix/pages-base-and-sonar-…
justcoding121 Aug 31, 2026
bc908d7
fix(website): stop /download 301 host-rewrite to github.io
justcoding121 Aug 31, 2026
c2d7747
Merge pull request #1006 from justcoding121/fix/pages-cname-and-base-…
justcoding121 Aug 31, 2026
2567076
fix(website): do not set Pages CNAME behind CloudFront
justcoding121 Aug 31, 2026
dde3974
fix(ci): allow workflow_dispatch Pages deploy from fix branches
justcoding121 Aug 31, 2026
361df8a
Merge pull request #1007 from justcoding121/fix/pages-no-cname-cloudf…
justcoding121 Aug 31, 2026
f1974c7
Harden CI ports, Inspector session IDs/stress, and macOS RPS parity.
justcoding121 Aug 31, 2026
77773ed
fix(ci): install Homebrew libmsquic on macOS ui-portable for HTTP/3
justcoding121 Aug 31, 2026
c32a98c
fix(ci): macOS MsQuic DYLD path and Intel Homebrew bottles
justcoding121 Aug 31, 2026
76fe372
fix: declare ControlPlaneConfig.DashboardPort in PublicAPI
justcoding121 Aug 31, 2026
d720c76
fix(e2e): correct dashboardPort YAML indent after raw-string de-indent
justcoding121 Aug 31, 2026
41165cb
fix(inspector): allow shared read of export zip; retry copy on macOS
justcoding121 Aug 31, 2026
0d298c7
fix(e2e): allow version --check exit 1 when update feed is unreachable
justcoding121 Aug 31, 2026
7c461e5
fix(http3): use localhost SNI for H3 to HTTPS-H1 fast forward
justcoding121 Sep 1, 2026
46b5061
fix(inspector): sync native archive zip IO for macOS headless
justcoding121 Sep 1, 2026
2803f69
ci(rps): Mac-only compare-product-smoke for gate validation
justcoding121 Sep 1, 2026
400f1f5
ci(rps): fix runner_os filter via dynamic matrix fromJSON
justcoding121 Sep 1, 2026
5ade400
fix(website): open DocFX API links outside SPA; Inspector above CLI
justcoding121 Sep 1, 2026
b755393
fix(http3): drop H1 ALPN on H3-to-HTTPS fast path; harden Mac probe t…
justcoding121 Sep 1, 2026
ea54e55
fix(tls): validate origin cert via SslClientAuthenticationOptions
justcoding121 Sep 1, 2026
95ef679
fix(tls): do not offer Tls13-only to HTTPS origins after QUIC
justcoding121 Sep 1, 2026
6d123ba
revert: drop speculative Mac H3-to-HTTPS fixes; keep Tls13 policy
justcoding121 Sep 1, 2026
2026da5
fix(tls): decouple outbound SslProtocols from inbound client handshake
justcoding121 Sep 1, 2026
a84a73e
ci(rps): gate beta/stable publish on Core vs YARP spot in parallel
justcoding121 Sep 1, 2026
d043955
chore(rps): drop H3 error-log debug; Mac H3-H1 TLS Full floor 0.65
justcoding121 Sep 1, 2026
af6feb9
ci(rps): Mac-only compare-product floors for H1 Full and H3-H1 peer
justcoding121 Sep 1, 2026
bacb627
docs(perf): fill Mac compare-product wiki; H3-H3 peer floor 0.74
justcoding121 Sep 1, 2026
12397ff
fix(http3): restore authority SNI for H3 to HTTPS-H1 fast path
justcoding121 Sep 1, 2026
3dc2bf3
Update documentation
github-actions[bot] Sep 1, 2026
8052a9e
chore(release): bump to 7.0.4 for beta cut
justcoding121 Sep 1, 2026
d7d8c05
Merge pull request #1008 from justcoding121/release/7.0.4-beta-bump
justcoding121 Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions .github/workflows/deploy-website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ jobs:
mkdir -p website/.vitepress/dist/api
if [ -d docs/api ]; then
cp -a docs/api/. website/.vitepress/dist/api/
# DocFX has toc.html but no index; /api/ 404s without this.
if [ -f website/.vitepress/dist/api/toc.html ] && [ ! -f website/.vitepress/dist/api/index.html ]; then
cp -f website/.vitepress/dist/api/toc.html website/.vitepress/dist/api/index.html
fi
# DocFX HTML references ../styles and ../fonts from /api/*.html
if [ -d docs/styles ]; then
cp -a docs/styles website/.vitepress/dist/styles
Expand All @@ -76,13 +80,18 @@ jobs:
echo "Warning: docs/api missing; API pages will not be published"
fi

# GitHub Pages + VitePress cleanUrls: /download sometimes keeps a stale
# object while /download.html updates. Publish both shapes so the nav link works.
# GitHub Pages cleanUrls: keep BOTH `page.html` and `page/index.html`.
# Deleting the sibling `.html` forces `/page` (no slash) through a Pages 301
# that rewrites the host to `*.github.io` when the custom-domain CNAME is not
# fully active on the edge (CloudFront → GitHub). That is what made
# titaniumproxy.com/download bounce to github.io.
- name: Mirror cleanUrls HTML as index.html
shell: bash
run: |
set -euo pipefail
dist=website/.vitepress/dist
# Do NOT write a Pages CNAME: titaniumproxy.com DNS points at CloudFront,
# not GitHub. A Pages custom domain causes http↔https redirect loops.
for f in "$dist"/*.html; do
base="$(basename "$f" .html)"
[[ "$base" == "index" || "$base" == "404" ]] && continue
Expand All @@ -106,13 +115,13 @@ jobs:
path: website/.vitepress/dist

deploy:
# Push deploys only from develop (Pages env protection). Manual workflow_dispatch
# may publish from a fix branch to clear a bad artifact urgently.
if: >
github.event_name != 'pull_request' && (
github.ref == 'refs/heads/develop' ||
github.ref == 'refs/heads/beta' ||
github.ref == 'refs/heads/stable' ||
github.event_name == 'release' ||
github.event_name == 'workflow_dispatch'
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'release' && startsWith(github.event.release.tag_name, 'v'))
)
needs: build
runs-on: ubuntu-latest
Expand Down
130 changes: 126 additions & 4 deletions .github/workflows/dotnetcore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
pull: '--rebase --autostash'

# Cross-OS Inspector + Plus dashboard UI gates (Headless / Visual / Playwright).
# Inspector unit suite stays on Windows `build` only - do not re-run it here.
# Inspector unit suite stays on Windows `build` only except Inspector-Stress (below).
ui-portable:
runs-on: ${{ matrix.os }}
timeout-minutes: 35
Expand All @@ -169,6 +169,90 @@ jobs:
with:
dotnet-version: |
10.0.x
- name: Assert in-box MsQuic (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
if (-not [System.Net.Quic.QuicListener]::IsSupported) {
throw 'QuicListener.IsSupported is false on windows-latest (expected in-box MsQuic)'
}
Write-Host "QuicListener.IsSupported=$([System.Net.Quic.QuicListener]::IsSupported)"
- name: Install libmsquic (Linux HTTP/3)
if: runner.os == 'Linux'
run: |
set -euo pipefail
. /etc/os-release
curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 \
"https://packages.microsoft.com/config/${ID}/${VERSION_ID}/packages-microsoft-prod.deb" \
-o packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm -f packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y libmsquic
pwsh -NoProfile -Command 'if (-not [System.Net.Quic.QuicListener]::IsSupported) { throw "QuicListener.IsSupported is false after libmsquic install" }; Write-Host "QuicListener.IsSupported=$([System.Net.Quic.QuicListener]::IsSupported)"'
- name: Install MsQuic (macOS HTTP/3)
if: runner.os == 'macOS'
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
# Intel macOS bottles are sparse; do not force-upgrade openssl (no bottle → job fail).
$env:HOMEBREW_NO_AUTO_UPDATE = '1'
$env:HOMEBREW_NO_INSTALL_UPGRADE = '1'
brew install openssl@3 libmsquic
$prefix = (& brew --prefix).Trim()
$msquicLib = Join-Path $prefix 'opt/libmsquic/lib'
$sslLib = Join-Path $prefix 'opt/openssl@3/lib'
$libDirs = @($msquicLib, $sslLib, (Join-Path $prefix 'lib')) |
Where-Object { Test-Path $_ } |
Select-Object -Unique
$dyld = ($libDirs -join ':')
Add-Content -Path $env:GITHUB_ENV -Value "DYLD_LIBRARY_PATH=$dyld"
Add-Content -Path $env:GITHUB_ENV -Value "DYLD_FALLBACK_LIBRARY_PATH=$dyld"
$env:DYLD_LIBRARY_PATH = $dyld
$env:DYLD_FALLBACK_LIBRARY_PATH = $dyld
Write-Host "DYLD_LIBRARY_PATH=$dyld"

function Test-QuicSupported {
$out = & pwsh -NoProfile -Command {
if (-not [System.Net.Quic.QuicListener]::IsSupported) { '0' } else { '1' }
}
return ($out.Trim() -eq '1')
}

if (-not (Test-QuicSupported)) {
Write-Host 'QuicListener.IsSupported still false after brew; trying Microsoft libmsquic drop…'
$arch = (& uname -m).Trim()
$rid = if ($arch -eq 'arm64') { 'osx-arm64' } else { 'osx-x64' }
$dest = Join-Path $env:RUNNER_TEMP 'msquic-osx'
New-Item -ItemType Directory -Path $dest -Force | Out-Null
$tag = 'v2.4.7'
$url = "https://github.com/microsoft/msquic/releases/download/$tag/msquic_${rid}_$tag.zip"
$zip = Join-Path $env:RUNNER_TEMP 'msquic-osx.zip'
try {
& curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 $url -o $zip
if ($LASTEXITCODE -ne 0) { throw "curl exit $LASTEXITCODE" }
Expand-Archive -Path $zip -DestinationPath $dest -Force
} catch {
Write-Warning "Microsoft release download failed ($url): $_"
}
$found = Get-ChildItem -Path $dest -Recurse -Filter 'libmsquic*.dylib' -ErrorAction SilentlyContinue |
Select-Object -First 1
if ($found) {
$extra = $found.Directory.FullName
# ${extra} — bare $extra: is parsed as a PowerShell drive-qualified variable.
$dyld2 = "${extra}:${dyld}"
Add-Content -Path $env:GITHUB_ENV -Value "DYLD_LIBRARY_PATH=$dyld2"
Add-Content -Path $env:GITHUB_ENV -Value "DYLD_FALLBACK_LIBRARY_PATH=$dyld2"
$env:DYLD_LIBRARY_PATH = $dyld2
$env:DYLD_FALLBACK_LIBRARY_PATH = $dyld2
Write-Host "Added Microsoft dylib dir: $extra"
}
}

if (-not (Test-QuicSupported)) {
throw 'QuicListener.IsSupported is false after macOS MsQuic install (brew + optional Microsoft drop)'
}
Write-Host 'QuicListener.IsSupported=True'
- name: Linux UI fonts + Playwright OS deps
if: runner.os == 'Linux'
run: |
Expand All @@ -194,6 +278,9 @@ jobs:
- name: Inspector Headless + Visual + Plus Playwright
run: |
dotnet test tests/Titanium.E2E.Tests/Titanium.E2E.Tests.csproj --configuration Release --no-build --no-restore --filter "TestCategory=E2E-UI-Headless|TestCategory=E2E-UI-Visual|TestCategory=E2E-UI-Plus-Dashboard"
- name: Inspector retention stress (spill + H3)
run: |
dotnet test tests/Titanium.Inspector.Tests/Titanium.Inspector.Tests.csproj --configuration Release --no-restore --filter "TestCategory=Inspector-Stress"
- name: OS proxy-backend filters
run: |
dotnet test tests/Titanium.Web.Proxy.UnitTests/Titanium.Web.Proxy.UnitTests.csproj --configuration Release --no-build --no-restore --filter "FullyQualifiedName~UnixProxyBypassMapperTests|FullyQualifiedName~MacOsSystemProxyBackendTests|FullyQualifiedName~LinuxSystemProxyBackendTests|FullyQualifiedName~ElevationPromptCancelTests|FullyQualifiedName~SystemProxyBackendFactoryPlatformTests"
Expand All @@ -220,7 +307,9 @@ jobs:
**/playwright-report/**
if-no-files-found: ignore

# Tiered RPS gate for beta/stable publish (editions). Spot runs on PRs via rps-saturation.yml.
# Tiered RPS gates for beta/stable publish (parallel — wall clock ~max of the two).
# Editions: CLI/Plus tax vs Core. Peer: Core reverse vs YARP (+ MITM÷Reverse) so a
# uniform Core slowdown cannot hide behind green edition ratios.
rps-publish-gate:
if: github.event_name == 'push' && (github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/stable')
runs-on: ubuntu-latest
Expand Down Expand Up @@ -251,9 +340,42 @@ jobs:
if (-not $csv) { throw 'No CSV found for edition gate validation' }
pwsh tools/RpsLoadProbe/validate-edition-gates.ps1 -CsvPath $csv.FullName

# Parallel with rps-publish-gate: Core vs YARP on the release SHA (c=64 spot).
# Same validator as PR compare-spot / run-spot-matrix.ps1; does not extend wall clock
# past editions (~60m).
rps-peer-gate:
if: github.event_name == 'push' && (github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/stable')
runs-on: ubuntu-latest
timeout-minutes: 45
permissions:
contents: read
steps:
- uses: actions/checkout@v6
- name: Setup .NET
uses: actions/setup-dotnet@v5
with:
dotnet-version: |
10.0.x
- name: Install libmsquic (HTTP/3)
run: |
set -euo pipefail
. /etc/os-release
curl --fail --silent --show-error --location --proto '=https' --tlsv1.2 \
"https://packages.microsoft.com/config/${ID}/${VERSION_ID}/packages-microsoft-prod.deb" \
-o packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
rm -f packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y libmsquic
pwsh -NoProfile -Command 'if (-not [System.Net.Quic.QuicListener]::IsSupported) { throw "QuicListener.IsSupported is false after libmsquic install" }; Write-Host "QuicListener.IsSupported=$([System.Net.Quic.QuicListener]::IsSupported)"'
- name: compare-spot (Core÷YARP + MITM÷Reverse)
shell: pwsh
run: |
pwsh tools/RpsLoadProbe/run-spot-matrix.ps1

publish:
if: github.event_name == 'push' && (github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/stable')
needs: [build, ui-portable, rps-publish-gate]
needs: [build, ui-portable, rps-publish-gate, rps-peer-gate]
runs-on: windows-latest
environment: nuget-publish
permissions:
Expand Down Expand Up @@ -306,7 +428,7 @@ jobs:
# version tag and dispatch release.yml (GITHUB_TOKEN tag pushes do not re-trigger workflows).
cut-product-tag:
if: github.event_name == 'push' && (github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/stable')
needs: [build, ui-portable, rps-publish-gate]
needs: [build, ui-portable, rps-publish-gate, rps-peer-gate]
runs-on: ubuntu-latest
permissions:
contents: write
Expand Down
11 changes: 4 additions & 7 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -461,10 +461,7 @@ jobs:
set -euo pipefail
# GITHUB_TOKEN `gh release create` does not fire `release: published` for
# other workflows. Rebuild Pages so download.data.ts sees new zip/MSI assets.
REF=develop
case "$RELEASE_CHANNEL" in
beta) REF=beta ;;
stable) REF=stable ;;
esac
echo "Dispatching deploy-website.yml --ref $REF (channel=$RELEASE_CHANNEL)"
gh workflow run deploy-website.yml --ref "$REF"
# github-pages environment only allows deploy from develop (beta/stable are
# blocked by environment protection rules).
echo "Dispatching deploy-website.yml --ref develop (channel=$RELEASE_CHANNEL)"
gh workflow run deploy-website.yml --ref develop
Loading
Loading