fix(worktrack): restore the manifest text the model rewrite escaped #649
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 |