Skip to content

fix(worktrack): restore the manifest text the model rewrite escaped #649

fix(worktrack): restore the manifest text the model rewrite escaped

fix(worktrack): restore the manifest text the model rewrite escaped #649

Workflow file for this run

# This workflow will build a .NET project
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
name: .NET
on:
push:
branches: [ "main" ]
tags: [ "v*" ]
pull_request:
branches: [ "main" ]
release:
types: [ published ]
# Opt every JavaScript-based action into the Node.js 24 runtime ahead of
# the 2026-09-16 Node.js 20 sunset, suppressing the runner deprecation
# annotation. Remove once the runner default flips to Node 24.
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
# Epic tier: the fast merge gate. Test projects build their single current
# TFM (net10.0) and the Fuzz category is excluded. The full net8/9/10
# matrix and the fuzzers run in release-tests below, which gates
# pack-publish on version tags and releases.
build-test:
runs-on: ubuntu-latest
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
env:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: Bifrost!CI!Test1234
ports:
- 1433:1433
options: >-
--health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Bifrost!CI!Test1234' -No -Q 'SELECT 1' || /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'Bifrost!CI!Test1234' -Q 'SELECT 1' || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 20
--health-start-period 30s
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: bifrost_ci_test
POSTGRES_DB: bifrost_ci
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 10
mysql:
# The default max_connections of 151 was exhausted by the parallel
# xunit fixtures (each test class opens its own DB), so bump to 500
# via the --max-connections server arg.
image: mysql:8.4
env:
MYSQL_ROOT_PASSWORD: bifrost_ci_test
MYSQL_DATABASE: bifrost_ci
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping -h localhost -uroot -pbifrost_ci_test"
--health-interval 10s
--health-timeout 5s
--health-retries 20
--health-start-period 20s
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
version: 11.1.1
- name: Setup Node
uses: actions/setup-node@v4
with:
# 24 to match react-package.yml; the workspace tooling uses node:sqlite
# (requires Node 22+), which errored under Node 20.
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install frontend deps
run: pnpm install --frozen-lockfile
- name: Build SPA workspace dependencies
# The desktop SPA imports built workspace packages (@standardbeagle/edit-db,
# @bifrostql/binary-client and their deps). Build them in topological order
# first so their dist/types exist when the SPA's tsc runs.
run: pnpm --filter "...@standardbeagle/edit-db" --filter "...@bifrostql/binary-client" build
- name: Build desktop UI SPA
# wwwroot is Vite output and gitignored, so CI must build it: the UI host
# tests serve index.html from it, and the .UI csproj copies wwwroot/** to
# the Release output during the dotnet build below. Runs before that build.
run: pnpm --dir src/BifrostQL.UI/frontend build
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 8.0.x
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 9.0.x
- name: Setup .NET 10.0
# Projects multi-target net10.0; pin the SDK instead of relying on
# whatever the runner image happens to preinstall.
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.x
- name: Cache NuGet packages
uses: actions/cache@v6
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', 'global.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Test Core
# Fuzz tests are excluded from the epic-tier merge gate; they run in
# the release-tests job that gates pack-publish.
run: dotnet test tests/BifrostQL.Core.Test/BifrostQL.Core.Test.csproj --no-build --verbosity normal --configuration Release --filter "Category!=Fuzz" --collect:"XPlat Code Coverage" --results-directory ./coverage/core
- name: Upload Core coverage
uses: actions/upload-artifact@v7
with:
name: core-coverage
path: coverage/core
- name: Test Server
run: dotnet test tests/BifrostQL.Server.Test/BifrostQL.Server.Test.csproj --no-build --verbosity normal --configuration Release
- name: Test Host
# In-memory ASP.NET host (Mvc.Testing) over the Sqlite dialect — no
# external service containers required.
run: dotnet test tests/BifrostQL.Host.Test/BifrostQL.Host.Test.csproj --no-build --verbosity normal --configuration Release
- name: Test UI
# Pure xunit logic tests for the desktop tool — no GUI/display needed.
run: dotnet test tests/BifrostQL.UI.Tests/BifrostQL.UI.Tests.csproj --no-build --verbosity normal --configuration Release
- name: Raise MySQL max_connections
# GH Actions services don't expose post-image server args, so the
# default 151 connection ceiling is lifted at runtime via SET GLOBAL.
# The parallel xunit fixtures otherwise blow past it with
# `Too many connections`.
run: mysql --protocol=TCP -h 127.0.0.1 -P 3306 -uroot -pbifrost_ci_test -e "SET GLOBAL max_connections=500;"
- name: Test Integration (Sqlite + SqlServer + Postgres + MySQL)
# Sqlite tests use in-memory shared cache and always run. The other
# three suites gate on their respective BIFROST_TEST_* env vars and
# exercise the dialect-specific SQL contract end-to-end against the
# service containers above.
env:
BIFROST_TEST_SQLSERVER: "Server=localhost,1433;Database=master;User Id=sa;Password=Bifrost!CI!Test1234;TrustServerCertificate=True;Encrypt=False"
BIFROST_TEST_POSTGRES: "Host=localhost;Port=5432;Database=bifrost_ci;Username=postgres;Password=bifrost_ci_test"
BIFROST_TEST_MYSQL: "Server=localhost;Port=3306;Database=bifrost_ci;User Id=root;Password=bifrost_ci_test;AllowPublicKeyRetrieval=True;SslMode=Preferred"
run: dotnet test tests/BifrostQL.Integration.Test/BifrostQL.Integration.Test.csproj --no-build --verbosity normal --configuration Release
# Release tier: the pre-release gate. Runs only on version tags and
# releases, restores the full net8/net9/net10 target matrix
# (-p:ReleaseTests=true), and runs the Fuzz category (pinned seeds —
# deterministic). pack-publish will not run until this passes.
release-tests:
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'release'
runs-on: ubuntu-latest
services:
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
env:
ACCEPT_EULA: Y
MSSQL_SA_PASSWORD: Bifrost!CI!Test1234
ports:
- 1433:1433
options: >-
--health-cmd "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P 'Bifrost!CI!Test1234' -No -Q 'SELECT 1' || /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'Bifrost!CI!Test1234' -Q 'SELECT 1' || exit 1"
--health-interval 10s
--health-timeout 5s
--health-retries 20
--health-start-period 30s
postgres:
image: postgres:16
env:
POSTGRES_PASSWORD: bifrost_ci_test
POSTGRES_DB: bifrost_ci
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 5s
--health-retries 10
mysql:
image: mysql:8.4
env:
MYSQL_ROOT_PASSWORD: bifrost_ci_test
MYSQL_DATABASE: bifrost_ci
ports:
- 3306:3306
options: >-
--health-cmd "mysqladmin ping -h localhost -uroot -pbifrost_ci_test"
--health-interval 10s
--health-timeout 5s
--health-retries 20
--health-start-period 20s
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
version: 11.1.1
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Install frontend deps
run: pnpm install --frozen-lockfile
- name: Build SPA workspace dependencies
run: pnpm --filter "...@standardbeagle/edit-db" --filter "...@bifrostql/binary-client" build
- name: Build desktop UI SPA
run: pnpm --dir src/BifrostQL.UI/frontend build
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 8.0.x
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 9.0.x
- name: Setup .NET 10.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.x
- name: Cache NuGet packages
uses: actions/cache@v6
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', 'global.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Restore dependencies
run: dotnet restore -p:ReleaseTests=true
- name: Build (full test matrix)
run: dotnet build --no-restore --configuration Release -p:ReleaseTests=true
- name: Raise MySQL max_connections
run: mysql --protocol=TCP -h 127.0.0.1 -P 3306 -uroot -pbifrost_ci_test -e "SET GLOBAL max_connections=500;"
- name: Test (full matrix, all engines, including Fuzz)
env:
BIFROST_TEST_SQLSERVER: "Server=localhost,1433;Database=master;User Id=sa;Password=Bifrost!CI!Test1234;TrustServerCertificate=True;Encrypt=False"
BIFROST_TEST_POSTGRES: "Host=localhost;Port=5432;Database=bifrost_ci;Username=postgres;Password=bifrost_ci_test"
BIFROST_TEST_MYSQL: "Server=localhost;Port=3306;Database=bifrost_ci;User Id=root;Password=bifrost_ci_test;AllowPublicKeyRetrieval=True;SslMode=Preferred"
run: dotnet test BifrostQL.sln --no-build --verbosity normal --configuration Release -p:ReleaseTests=true
pack-publish:
needs: [build-test, release-tests]
# Only cut/publish packages on a version tag push or a GitHub release —
# not on every push to main, which build-test already gates.
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
version: 11.1.1
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
cache-dependency-path: pnpm-lock.yaml
- name: Setup .NET 8.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 8.0.x
- name: Setup .NET 9.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 9.0.x
- name: Setup .NET 10.0
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.x
- name: Cache NuGet packages
uses: actions/cache@v6
with:
path: ~/.nuget/packages
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', 'global.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore --configuration Release
- name: Pack
run: |
dotnet pack "src/BifrostQL.Abstractions/BifrostQL.Abstractions.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
dotnet pack "src/BifrostQL.Core/BifrostQL.Core.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
dotnet pack "src/BifrostQL.Server/BifrostQL.Server.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
dotnet pack "src/data/BifrostQL.Ngsql/BifrostQL.Ngsql.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
dotnet pack "src/data/BifrostQL.SqlServer/BifrostQL.SqlServer.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
dotnet pack "src/data/BifrostQL.Sqlite/BifrostQL.Sqlite.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
dotnet pack "src/data/BifrostQL.MySql/BifrostQL.MySql.csproj" --configuration Release --no-build -p:PackageVersion=0.4.${{ github.run_number }}
- name: add source
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget add source --username standardbeagle --password "$REPO_NUGET" --store-password-in-clear-text --name github "https://nuget.pkg.github.com/standardbeagle/index.json"
else
echo "REPO_NUGET not set, skipping GitHub Packages source setup"
fi
- name: publish Abstractions to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/BifrostQL.Abstractions/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish Core to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/BifrostQL.Core/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish Server to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/BifrostQL.Server/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish Ngsql to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/data/BifrostQL.Ngsql/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish SqlServer to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/data/BifrostQL.SqlServer/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish Sqlite to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/data/BifrostQL.Sqlite/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish MySql to repo
env:
REPO_NUGET: ${{ secrets.REPO_NUGET }}
run: |
if [ -n "$REPO_NUGET" ]; then
dotnet nuget push "src/data/BifrostQL.MySql/bin/Release/*.nupkg" --source "github" -k "$REPO_NUGET" --skip-duplicate --no-symbols
else
echo "REPO_NUGET not set, skipping GitHub Packages publish"
fi
- name: publish Abstractions to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/BifrostQL.Abstractions/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: publish Core to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/BifrostQL.Core/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: publish Server to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/BifrostQL.Server/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: publish Ngsql to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/data/BifrostQL.Ngsql/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: publish SqlServer to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/data/BifrostQL.SqlServer/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: publish Sqlite to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/data/BifrostQL.Sqlite/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: publish MySql to nuget.org
env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
run: |
if [ -n "$NUGET_API_KEY" ]; then
dotnet nuget push "src/data/BifrostQL.MySql/bin/Release/*.nupkg" --source "nuget.org" -k "$NUGET_API_KEY" --skip-duplicate --no-symbols
else
echo "Skipping nuget.org publish: NUGET_API_KEY not set"
fi
- name: Install frontend deps
run: pnpm install --frozen-lockfile
- name: set editor version
run: pnpm --dir examples/edit-db version 0.4.${{ github.run_number }} --no-git-tag-version
- name: build editor
run: pnpm --dir examples/edit-db build
- name: publish npm package
run: |
echo "//registry.npmjs.org/:_authToken=${{secrets.NPM_TOKEN}}" > ~/.npmrc
pnpm --dir examples/edit-db publish --access public --no-git-checks