Skip to content

Checkpoint functional query flows and current implementation stages #215

Checkpoint functional query flows and current implementation stages

Checkpoint functional query flows and current implementation stages #215

Workflow file for this run

name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
workflow_run:
workflows: [Benchmarks]
types: [completed]
permissions:
contents: read
concurrency:
group: keyload-ci-${{ github.event_name == 'workflow_run' && 'site' || github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
repository-checks:
if: github.event_name != 'workflow_run'
name: Check repository rules
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Download source code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Check repository rules
run: node scripts/Features/RepositoryGovernance/verify.mjs
analyzer-rules:
if: github.event_name != 'workflow_run'
name: Test code analyzers
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Download source code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
- name: Restore .NET packages
run: dotnet restore KeyLoad.slnx
- name: Build analyzer tests
run: |
dotnet build src/KeyLoad.AppHost --no-restore --configuration Release
dotnet build tests/KeyLoad.Analyzers.Tests --no-restore --configuration Release
- name: Run analyzer tests
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=analyzers --KeyLoadTests:ReportTrx=true
- name: Save analyzer test results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: analyzer-rule-evidence
path: |
TestResults/**
tests/KeyLoad.Analyzers.Tests/**/TestResults/**
artifacts/code-quality/**
if-no-files-found: error
verify:
if: github.event_name != 'workflow_run'
name: Build and test KeyLoad
needs: repository-checks
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 120
steps:
- name: Download source code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
- name: Restore .NET packages
run: dotnet restore KeyLoad.slnx
- name: Build KeyLoad
id: build
run: dotnet build KeyLoad.slnx --no-restore --configuration Release
- name: Verify the pinned native full-text package
run: |
node --input-type=module <<'JS'
import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import { execFileSync, spawnSync } from 'node:child_process';
const cache = execFileSync('dotnet', ['nuget', 'locals', 'global-packages', '--list'], { encoding: 'utf8' }).trim();
const prefix = 'global-packages: ';
if (!cache.startsWith(prefix) || cache.includes('\n')) throw new Error('Ambiguous NuGet package cache.');
const packagePath = path.join(cache.slice(prefix.length), 'zonetree.fulltextsearch', '1.0.9', 'zonetree.fulltextsearch.1.0.9.nupkg');
const digest = crypto.createHash('sha256').update(fs.readFileSync(packagePath)).digest('hex');
if (digest !== '7ea1fbb7aba0ad00391d78d2f414166b500335f5b1affe43c305d861b55719ff') throw new Error('Native FTS package differs from ADR-078.');
const verification = spawnSync('dotnet', ['nuget', 'verify', packagePath, '--all'], { encoding: 'utf8', maxBuffer: 1048576 });
fs.mkdirSync('artifacts/qualification', { recursive: true });
fs.writeFileSync('artifacts/qualification/native-full-text-package-signature.log', `Package SHA256: ${digest}\n${verification.stdout ?? ''}${verification.stderr ?? ''}`);
process.stdout.write(verification.stdout ?? '');
process.stderr.write(verification.stderr ?? '');
if (verification.error || verification.status !== 0) throw verification.error ?? new Error('Native FTS package signature verification failed.');
JS
- name: Check code formatting
run: dotnet format KeyLoad.slnx --verify-no-changes --no-restore
- name: Check repository rules
run: node scripts/Features/RepositoryGovernance/verify.mjs
- name: Test code analyzers
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=analyzers --KeyLoadTests:ReportTrx=true
- name: Test prompt termination on Aspire resource failures
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=comparison '--KeyLoadTests:Filter=/*/*/AspireFailure*/*' --KeyLoadTests:ResultsDirectory=TestResults/aspire-failure --KeyLoadTests:ReportTrx=true
- name: Test Aspire recovery prerequisite ownership
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=comparison '--KeyLoadTests:Filter=/*/*/PriorProbePrerequisiteTests/*' --KeyLoadTests:ResultsDirectory=TestResults/recovery-prerequisites --KeyLoadTests:ReportTrx=true
- name: Test live benchmark progress capture
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=comparison '--KeyLoadTests:Filter=/*/*/ComparisonProgress*/*' --KeyLoadTests:ResultsDirectory=TestResults/live-benchmark-progress --KeyLoadTests:ReportTrx=true
- name: Test live benchmark process entry
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=unit '--KeyLoadTests:Filter=/*/*/NativeBenchmarkProgressEntryTests/*' --KeyLoadTests:ResultsDirectory=TestResults/live-benchmark-entry --KeyLoadTests:ReportTrx=true
- name: Test benchmark phase and attempt counters
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=unit '--KeyLoadTests:Filter=/*/*/ComparisonLiveProgress*/*' --KeyLoadTests:ResultsDirectory=TestResults/live-benchmark-counters --KeyLoadTests:ReportTrx=true
- name: Test Aspire workflow entry contracts
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=unit '--KeyLoadTests:Filter=/*/*/WorkflowLayoutAspireEntryTests/*' --KeyLoadTests:ResultsDirectory=TestResults/live-benchmark-workflow --KeyLoadTests:ReportTrx=true
- name: Run unit tests
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=unit --KeyLoadTests:ReportTrx=true
- name: Run unit tests without CPU intrinsics
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=unit-scalar --KeyLoadTests:ReportTrx=true
- name: Test recovery after process crashes
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=recovery --KeyLoadTests:ReportTrx=true
- name: Save test results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: test-results-${{ matrix.os }}
path: |
**/TestResults/**
artifacts/qualification/**
if-no-files-found: ignore
- name: Save build diagnostics
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: code-quality-${{ matrix.os }}
path: artifacts/code-quality/**
if-no-files-found: error
docker-rf3:
if: github.event_name != 'workflow_run'
name: Test three-node database
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Download source code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up .NET
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0
with:
global-json-file: global.json
- name: Check Docker
run: docker version
- name: Build KeyLoad server and benchmark Docker images
id: images
run: node scripts/Features/BenchmarkComparisons/prepare-images.mjs
- name: Build the genuine previous KeyLoad server image
id: prior-images
run: node scripts/Features/StorageRecovery/prepare-native5-server-image.mjs
- name: Build the genuine epoch-six RPC1 KeyLoad server image
id: rpc1-images
run: node scripts/Features/ClusterRouting/prepare-rpc1-server-image.mjs
- name: Build the genuine epoch-seven interface-three KeyLoad server image
id: interface3-images
run: node scripts/Features/ClusterRouting/prepare-interface3-server-image.mjs
- name: Configure Docker image references
shell: bash
env:
KEYLOAD_SERVER_IMAGE: ${{ steps.images.outputs.server-image }}
KEYLOAD_RUNNER_IMAGE: ${{ steps.images.outputs.load-generator-image }}
KEYLOAD_PRIOR_SERVER_IMAGE: ${{ steps.prior-images.outputs.prior-server-image }}
KEYLOAD_PRIOR_IMAGE_RECEIPT: ${{ steps.prior-images.outputs.prior-image-receipt }}
KEYLOAD_PRIOR_SERVER_MANIFEST: ${{ steps.prior-images.outputs.prior-server-manifest }}
KEYLOAD_RPC1_SERVER_IMAGE: ${{ steps.rpc1-images.outputs.KEYLOAD_RPC1_SERVER_IMAGE }}
KEYLOAD_RPC1_IMAGE_RECEIPT: ${{ steps.rpc1-images.outputs.KEYLOAD_RPC1_IMAGE_RECEIPT }}
KEYLOAD_RPC1_SERVER_MANIFEST: ${{ steps.rpc1-images.outputs.KEYLOAD_RPC1_SERVER_MANIFEST }}
KEYLOAD_INTERFACE3_SERVER_IMAGE: ${{ steps.interface3-images.outputs.KEYLOAD_INTERFACE3_SERVER_IMAGE }}
KEYLOAD_INTERFACE3_IMAGE_RECEIPT: ${{ steps.interface3-images.outputs.KEYLOAD_INTERFACE3_IMAGE_RECEIPT }}
KEYLOAD_INTERFACE3_SERVER_MANIFEST: ${{ steps.interface3-images.outputs.KEYLOAD_INTERFACE3_SERVER_MANIFEST }}
KEYLOAD_INTERFACE3_SERVER_INVENTORY: ${{ steps.interface3-images.outputs.KEYLOAD_INTERFACE3_SERVER_INVENTORY }}
KEYLOAD_INTERFACE3_SERVER_ARCHIVE: ${{ steps.interface3-images.outputs.KEYLOAD_INTERFACE3_SERVER_ARCHIVE }}
run: |
test -n "$KEYLOAD_SERVER_IMAGE" && test -n "$KEYLOAD_RUNNER_IMAGE"
test -n "$KEYLOAD_PRIOR_SERVER_IMAGE" && test -n "$KEYLOAD_PRIOR_IMAGE_RECEIPT" && test -n "$KEYLOAD_PRIOR_SERVER_MANIFEST"
test -n "$KEYLOAD_RPC1_SERVER_IMAGE" && test -n "$KEYLOAD_RPC1_IMAGE_RECEIPT" && test -n "$KEYLOAD_RPC1_SERVER_MANIFEST"
test -n "$KEYLOAD_INTERFACE3_SERVER_IMAGE" && test -n "$KEYLOAD_INTERFACE3_IMAGE_RECEIPT" && test -n "$KEYLOAD_INTERFACE3_SERVER_MANIFEST"
test -n "$KEYLOAD_INTERFACE3_SERVER_INVENTORY" && test -n "$KEYLOAD_INTERFACE3_SERVER_ARCHIVE"
printf 'KeyLoad__ContainerImages__Server=%s\nBenchmarks__ContainerImages__LoadGenerator=%s\nKEYLOAD_IMAGE_RECEIPT=%s\n' "$KEYLOAD_SERVER_IMAGE" "$KEYLOAD_RUNNER_IMAGE" "$RUNNER_TEMP/keyload-images/image-receipt.json" >> "$GITHUB_ENV"
printf 'KEYLOAD_PRIOR_SERVER_IMAGE=%s\nKEYLOAD_PRIOR_IMAGE_RECEIPT=%s\nKEYLOAD_PRIOR_SERVER_MANIFEST=%s\n' "$KEYLOAD_PRIOR_SERVER_IMAGE" "$KEYLOAD_PRIOR_IMAGE_RECEIPT" "$KEYLOAD_PRIOR_SERVER_MANIFEST" >> "$GITHUB_ENV"
printf 'KEYLOAD_RPC1_SERVER_IMAGE=%s\nKEYLOAD_RPC1_IMAGE_RECEIPT=%s\nKEYLOAD_RPC1_SERVER_MANIFEST=%s\n' "$KEYLOAD_RPC1_SERVER_IMAGE" "$KEYLOAD_RPC1_IMAGE_RECEIPT" "$KEYLOAD_RPC1_SERVER_MANIFEST" >> "$GITHUB_ENV"
printf 'KEYLOAD_INTERFACE3_SERVER_IMAGE=%s\nKEYLOAD_INTERFACE3_IMAGE_RECEIPT=%s\nKEYLOAD_INTERFACE3_SERVER_MANIFEST=%s\nKEYLOAD_INTERFACE3_SERVER_INVENTORY=%s\nKEYLOAD_INTERFACE3_SERVER_ARCHIVE=%s\n' "$KEYLOAD_INTERFACE3_SERVER_IMAGE" "$KEYLOAD_INTERFACE3_IMAGE_RECEIPT" "$KEYLOAD_INTERFACE3_SERVER_MANIFEST" "$KEYLOAD_INTERFACE3_SERVER_INVENTORY" "$KEYLOAD_INTERFACE3_SERVER_ARCHIVE" >> "$GITHUB_ENV"
- name: Find Chrome for admin tests
shell: bash
run: |
admin_chrome=$(command -v google-chrome || command -v google-chrome-stable || command -v chromium || command -v chromium-browser)
test -n "$admin_chrome" && test -x "$admin_chrome"
"$admin_chrome" --version
printf 'KEYLOAD_ADMIN_CHROME_PATH=%s\n' "$admin_chrome" >> "$GITHUB_ENV"
- name: Restore .NET packages
run: dotnet restore KeyLoad.slnx
- name: Build three-node database tests
run: dotnet build tests/KeyLoad.IntegrationTests --no-restore --configuration Release
- name: Test three-node database with .NET and MCP clients
run: dotnet run --project src/KeyLoad.AppHost --no-build --no-restore --configuration Release -- --KeyLoadTests:Suite=rf3 --KeyLoadTests:ReportTrx=true
- name: Clean up Docker registry
if: ${{ always() && (steps.images.outcome == 'success' || steps.images.outcome == 'failure') }}
run: node scripts/Features/BenchmarkComparisons/cleanup-images.mjs
- name: Save three-node Docker image logs
if: ${{ always() && (steps.images.outcome == 'success' || steps.images.outcome == 'failure') }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: docker-rf3-image-evidence
path: ${{ runner.temp }}/keyload-images/**
if-no-files-found: error
- name: Save three-node database test results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: docker-rf3-qualification
path: |
TestResults/**
tests/KeyLoad.IntegrationTests/**/TestResults/**
artifacts/qualification/**
if-no-files-found: error
- name: Save three-node build diagnostics
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: code-quality-docker-rf3
path: artifacts/code-quality/**
if-no-files-found: error
qualify:
name: Check website
concurrency:
group: keyload-site-qualification
cancel-in-progress: false
if: >-
github.repository == 'managedcode/KeyLoad' && github.event.repository.id == 477801965 &&
((github.ref == 'refs/heads/main' &&
(github.event_name == 'push' || github.event_name == 'workflow_dispatch')) ||
(github.event_name == 'workflow_run' &&
github.event.workflow_run.head_repository.id == 477801965 &&
github.event.workflow_run.head_branch == 'main' &&
github.event.workflow_run.name == 'Benchmarks' &&
github.event.workflow_run.path == '.github/workflows/benchmarks.yml' &&
github.event.workflow_run.status == 'completed' &&
(github.event.workflow_run.event == 'push' || github.event.workflow_run.event == 'workflow_dispatch') &&
(github.event.workflow_run.conclusion == 'success' || github.event.workflow_run.conclusion == 'failure')))
runs-on: ubuntu-latest
timeout-minutes: 180
permissions: {contents: read, actions: read}
outputs:
mode: ${{ steps.qualification.outputs.mode }}
site_revision: ${{ steps.qualification.outputs.site_revision }}
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
steps:
- name: Download source code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.workflow_sha }}
path: control
persist-credentials: false
- name: Run website checks
id: qualification
uses: ./control/.github/workflows/Features/BenchmarkComparisons/QualifySite
deploy:
name: Publish website
concurrency:
group: keyload-site-deployment
cancel-in-progress: false
needs: qualify
if: ${{ always() && !cancelled() && needs.qualify.result == 'success' && needs.qualify.outputs.mode == 'publish' }}
runs-on: ubuntu-latest
timeout-minutes: 90
permissions: {contents: read, actions: read, pages: write, id-token: write}
environment: {name: github-pages, url: '${{ steps.publication.outputs.page_url }}'}
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
QUALIFIED_REVISION: ${{ needs.qualify.outputs.site_revision }}
CONTROL_REVISION: ${{ github.workflow_sha }}
steps:
- name: Download source code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.workflow_sha }}
path: control
persist-credentials: false
- name: Publish website
id: publication
uses: ./control/.github/workflows/Features/BenchmarkComparisons/DeploySite