Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1112c1b
retry an attempt the timeout rejected instead of failing the call
pokornyd Aug 11, 2026
818a667
bound a request when the default resilience pipeline is absent
pokornyd Aug 11, 2026
b85a663
keep polymorphic element data through the distributed cache
pokornyd Aug 11, 2026
76f3593
correct the hybrid cache's account of the memory tier
pokornyd Aug 11, 2026
2ffb5a2
correct the rc.1 note about the hybrid memory tier
pokornyd Aug 11, 2026
7e215d0
keep the sdk serializer out of the application's json options
pokornyd Aug 11, 2026
350e8cd
drop the delivery usings from the generated base record
pokornyd Aug 11, 2026
937785a
validate arguments against the mode that is running
pokornyd Aug 11, 2026
9779ddb
scope mode-specific options to the mode that is running
pokornyd Aug 11, 2026
fee85f5
document the error handling the sdk actually performs
pokornyd Aug 11, 2026
270c0c2
delimit the doc sections so they publish the sample alone
pokornyd Aug 11, 2026
b5de6b7
scope cache keys to the environment and stop leaking the marker attri…
pokornyd Aug 11, 2026
5efaf1e
resolve rich text tags in registration order like every other resolver
pokornyd Aug 11, 2026
b40231d
verify the signature the sender sent and settle header precedence
pokornyd Aug 11, 2026
89a8848
require the patch reference where the api demands one
pokornyd Aug 11, 2026
56bf6af
reserve codename identifiers only where they are emitted
pokornyd Aug 11, 2026
510496c
sharpen the api gate and keep source attribution across releases
pokornyd Aug 11, 2026
7d18fd5
record the actual trade-off behind the caching internals
pokornyd Aug 11, 2026
c8f5e84
carry dependency keys, existing queries and options through unchanged
pokornyd Aug 11, 2026
b7307c3
align factories, samples and docs with what the code does
pokornyd Aug 11, 2026
ad4fcb5
make the import samples assert the result they teach
pokornyd Aug 11, 2026
6e7b165
give the caching registrations a name of their own
pokornyd Aug 11, 2026
83fbeb4
clear the cleanup backlog across the products
pokornyd Aug 11, 2026
c611f29
finish the cleanup pass and sharpen the printer further
pokornyd Aug 12, 2026
ba7cd0c
require the client name the sync options accessor reads
pokornyd Aug 12, 2026
cd071a2
say what the release ordering is actually for
pokornyd Aug 12, 2026
e7fc4bf
carry the dependency keys past the first dynamic page
pokornyd Aug 12, 2026
c4b9e21
stop listing the delivery options by hand when building them
pokornyd Aug 12, 2026
fee0da4
give the scheduling samples an unambiguous instant
pokornyd Aug 12, 2026
8c30602
say what the options copy guards
pokornyd Aug 12, 2026
bd1b4e5
hold the display time zones to IANA names
pokornyd Aug 12, 2026
f6663da
say what the delivery display timezone is and is not
pokornyd Aug 12, 2026
3de78f1
put the published version next to each product
pokornyd Aug 12, 2026
925b0b1
show the prerelease line in the product versions
pokornyd Aug 12, 2026
27ffe91
lead with what the repo is rather than that it moved
pokornyd Aug 12, 2026
7f9502a
trim the product table to the way in
pokornyd Aug 12, 2026
c313ae9
prepare releases
github-actions[bot] Aug 12, 2026
7f81982
comment cleanup
pokornyd Aug 12, 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
69 changes: 20 additions & 49 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true


jobs:
build:
name: Build & test (${{ matrix.os }})
Expand All @@ -28,34 +27,23 @@ jobs:
uses: actions/setup-dotnet@v6
with:
global-json-file: global.json
# UseProjectReferences is passed explicitly on every leg rather than inherited from the
# default in Directory.Build.targets, so that changing that default can never silently
# change what any job builds.
# Explicit on every leg, so the default in Directory.Build.targets cannot silently
# change what a job builds.
- name: Restore dependencies
run: dotnet restore /p:UseProjectReferences=false
- name: Build
run: dotnet build --no-restore /p:UseProjectReferences=false /p:ContinuousIntegrationBuild=true
# Coverage is collected and ENFORCED here: each test project sets its own
# Threshold/ThresholdType and coverlet fails the run if coverage drops below it.
# A repo-wide number is not possible - coverage legitimately differs by an order
# of magnitude between a thin CLI entry point and a library.
#
# Linux only: the Codecov uploads below are Linux-only, so Windows coverage was
# computed and discarded - while coverlet.msbuild's GenerateCoverageResult has a
# timing race on Windows (it can read the hits file before the exiting test host
# finishes flushing it, failing the build with "Unable to read beyond the end of
# the stream" even though every test passed). The Windows leg's job is proving
# build + tests on Windows, so it runs without instrumentation.
# Coverage is enforced per test project via its own coverlet threshold. Linux only: the
# uploads below are Linux-only, and coverlet races the exiting test host on Windows.
- name: Test
if: runner.os == 'Linux'
run: dotnet test --no-build --verbosity normal /p:UseProjectReferences=false /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
- name: Test (no coverage)
if: runner.os == 'Windows'
run: dotnet test --no-build --verbosity normal /p:UseProjectReferences=false

# Uploaded per product with its own flag. Without flags every product's coverage
# would merge into one repo-wide percentage, which is meaningless across a client
# library and a CLI. Each product added to the repo needs its own step here.
# One flag per product - a merged repo-wide percentage across a library and a CLI
# would be meaningless. A new product needs its own step here.
- name: Codecov (aspnetcore)
if: runner.os == 'Linux'
uses: codecov/codecov-action@v7
Expand Down Expand Up @@ -106,15 +94,9 @@ jobs:
project-references:
name: Build against repo source
runs-on: ubuntu-latest
# Early-warning leg (§7). The default `build` job compiles every product against the
# PUBLISHED Kontent.Ai.* packages, which is what consumers actually get. This one flips
# those to ProjectReferences so a breaking change in one product fails in the PR that
# makes it, rather than months later when a consumer next updates.
#
# Blocking. It ran non-blocking through the migration of all five products and stayed
# green, so it now fails the build like any other leg. Mark it required in branch
# protection too - removing continue-on-error fails the RUN, but only a required
# check blocks the MERGE.
# Early-warning leg: the `build` job compiles against published packages, this one against
# in-repo sources, so a sibling breaking change fails in the PR that makes it. Blocking -
# mark it required in branch protection, since only a required check blocks the merge.
steps:
- uses: actions/checkout@v7
with:
Expand Down Expand Up @@ -145,16 +127,12 @@ jobs:
uses: actions/setup-dotnet@v6
with:
global-json-file: global.json
# Explicitly package mode: this job packs, and packing is only ever valid against the
# dependency floors in Directory.Packages.props. Directory.Build.targets refuses to pack
# in source mode outright; this keeps the job from depending on that refusal.
# Explicit package mode: packing is only ever valid against the declared floors.
- name: Restore dependencies
run: dotnet restore /p:UseProjectReferences=false
- name: Build
run: dotnet build --configuration Release --no-restore /p:UseProjectReferences=false /p:ContinuousIntegrationBuild=true
# Packs every product listed in eng/products.json and asserts each one produced
# the packages it claims to. Adding a product to products.json is enough; this
# step needs no edit.
# Driven by eng/products.json, so a new product needs no edit here.
- name: Pack and validate every product
shell: bash
run: |
Expand Down Expand Up @@ -223,8 +201,7 @@ jobs:
run: dotnet restore /p:UseProjectReferences=false
- name: Build
run: dotnet build --no-restore /p:UseProjectReferences=false /p:ContinuousIntegrationBuild=true
# These tests are skipped in the normal run unless KONTENT_SDK_RUN_REDIS_TESTS is set,
# so this job is the only thing that exercises them.
# Skipped everywhere else unless KONTENT_SDK_RUN_REDIS_TESTS is set.
- name: Redis integration tests
run: dotnet test src/delivery/Kontent.Ai.Delivery.Tests/Kontent.Ai.Delivery.Tests.csproj --no-build --filter "FullyQualifiedName~RedisCacheIntegrationTests" /p:UseProjectReferences=false
env:
Expand All @@ -235,11 +212,8 @@ jobs:
name: Package smoke tests
runs-on: ubuntu-latest
timeout-minutes: 30
# Pack validation proves the .nupkg files exist and contain the expected paths. This job proves a
# consumer can actually install and use them, which is a different question: it packs into a local
# feed and restores from it, so a broken nuspec dependency, a missing target framework, an analyzer
# packed to the wrong path or a .NET tool with no working entry point fails here rather than after
# publishing. Each fixture covers a different PACKAGE SHAPE, because they fail in different ways.
# Pack validation proves the packages exist; this proves a consumer can install and use them,
# by restoring from a local feed. One fixture per package shape - they fail in different ways.
env:
SMOKE_VERSION: 0.0.0-smoke.${{ github.run_number }}
SMOKE_FEED: ${{ github.workspace }}/artifacts/smoke-feed
Expand All @@ -257,7 +231,6 @@ jobs:
- name: Build
run: dotnet build --configuration Release --no-restore /p:UseProjectReferences=false

# Same product list as pack validation, so a new product is covered by editing products.json only.
- name: Pack into a local feed
shell: bash
run: |
Expand All @@ -269,26 +242,24 @@ jobs:
done
ls -1 "$SMOKE_FEED"

# Plain class libraries: restore from the nuspec, then resolve each client through DI.
# Resolves each client through DI.
- name: Library consumer
working-directory: eng/smoke/library
run: dotnet run --configuration Release /p:KontentVersion=${{ env.SMOKE_VERSION }}

# Analyzer package. Roslyn silently skips a generator packed to the wrong path or built against a
# newer compiler than the SDK provides, so this fixture only compiles if the generator ran.
# Roslyn silently skips a generator packed to the wrong path, so this fixture only
# compiles if the generator actually ran.
- name: Source generator consumer
working-directory: eng/smoke/sourcegen
run: dotnet run --configuration Release /p:KontentVersion=${{ env.SMOKE_VERSION }}

# Web SDK package: starts a real host rather than just compiling.
# Starts a real host rather than just compiling.
- name: ASP.NET Core consumer
working-directory: eng/smoke/aspnetcore
run: dotnet run --configuration Release /p:KontentVersion=${{ env.SMOKE_VERSION }}

# .NET tool: install it the way a user would, then run it. The tool exits non-zero without an
# environment id, so success is asserted on its OWN validation message appearing - that only
# happens if the package layout, entry point and runtime resolution all worked. A tool that
# failed to install or launch produces a host error instead.
# Success is asserted on the tool's own validation message: a package that failed to
# install or launch produces a host error instead.
- name: Model generator tool
shell: bash
run: |
Expand Down
18 changes: 5 additions & 13 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,21 @@ on:
schedule:
- cron: '0 18 * * 1'


jobs:
analyze:
name: Analyze C#
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
persist-credentials: false
fetch-depth: 0

# Initializes the CodeQL tools for scanning.
#
# build-mode: none extracts C# straight from source, so this workflow no longer compiles
# the repo - ci.yml already builds it on two legs, and a third full build bought nothing.
# It is also what makes the run eligible for an overlay-base database, which is CodeQL's
# incremental cache for pull-request scans; without it every run built a full database.
#
# Trade-off: buildless extraction does not see generated code, so the output of
# Kontent.Ai.Delivery.SourceGeneration is not analyzed. That output is generated model
# records - no I/O, no user input, nothing the security queries would flag.

# build-mode: none - ci.yml already builds the repo, and buildless extraction is what makes
# a run eligible for incremental overlay-base databases. It does not see generated code;
# the source generator only emits model records.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
Expand Down
22 changes: 5 additions & 17 deletions .github/workflows/dependency-floors.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
name: Dependency floors

# Reports how far each cross-product dependency floor in Directory.Packages.props has fallen
# behind nuget.org.
#
# Not a CI step, deliberately. Drift is a function of TIME - of a sibling being released
# elsewhere - not of anything in a pull request's diff, so running it per PR would put the same
# unchanging notice on every unrelated review and query nuget.org on every push. And it must
# not gate a merge: a floor is meant to lag, and raising one forces every downstream consumer
# to upgrade. Reporting is the whole job.
#
# The report also rides along in every "Prepare release" PR, which is where the information is
# actually actionable. This scheduled run is the ambient one, so a floor cannot go stale
# indefinitely just because nobody prepared a release.
# Reports how far each cross-product floor in Directory.Packages.props lags nuget.org.
# Deliberately not a CI gate - a floor is meant to lag, and drift tracks time, not any PR's
# diff. Prepare release carries the same report; this is the ambient one.
on:
schedule:
- cron: '0 6 1 * *'
Expand All @@ -34,14 +25,11 @@ jobs:
with:
global-json-file: global.json

# Built first so that `dotnet run` below emits only the report. A cold build writes its
# diagnostics to stdout, which would otherwise land in the middle of the job summary.
# Built first so the run below emits only the report, not cold-build diagnostics.
- name: Build the script
run: dotnet build eng/scripts/dependency-floors.cs

# The script exits non-zero only when a floor names a version that is not on nuget.org -
# that breaks every restore in the repo, so it should fail loudly. Merely being behind
# exits 0.
# Non-zero only when a floor names a version missing from nuget.org. Merely lagging exits 0.
- name: Report
run: |
set -euo pipefail
Expand Down
27 changes: 7 additions & 20 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,7 @@
name: Prepare release

# Bumps one or more products' versions and promotes their changelogs, then opens a single PR.
# Run it from Actions -> Prepare release -> Run workflow.
#
# Every product has its own dropdown, defaulting to `none`. Pick a bump for each product you
# want in this batch and leave the rest alone; one PR covers all of them.
#
# This does NOT publish anything. Merging the PR, then creating one GitHub Release per product
# tagged <product>-v<version>, is what triggers release.yml. Releases stay separate so a
# product can be published or abandoned without affecting the others.
# Bumps the selected products' versions and promotes their changelogs, then opens one PR.
# Publishes nothing - Publish batch does that once this PR is merged.
on:
workflow_dispatch:
inputs:
Expand Down Expand Up @@ -58,8 +51,7 @@ on:
type: string
required: false

# Two concurrent runs would open competing version PRs from the same base. Queue rather than
# cancel: a cancelled run can leave a pushed branch behind with no PR.
# Queue rather than cancel: a cancelled run can leave a pushed branch behind with no PR.
concurrency:
group: prepare-release
cancel-in-progress: false
Expand All @@ -79,8 +71,7 @@ jobs:
with:
global-json-file: global.json

# Inputs are user-supplied strings, so they are passed as environment variables and
# quoted - never interpolated into the shell command itself.
# Inputs are user-supplied: passed as quoted env vars, never interpolated into the shell.
- name: Bump versions and promote changelogs
id: bump
env:
Expand Down Expand Up @@ -141,11 +132,8 @@ jobs:
echo "Prepared:"
cat /tmp/summary.txt

# Folded into the PR body below. Preparing a release is the moment someone is already
# deciding what version each product should be on, so it is the one place a stale
# cross-product floor is actually actionable. Never fatal here: a floor is meant to lag,
# and the scheduled Dependency floors workflow is what fails loudly if one names a
# version that is not on NuGet at all.
# Folded into the PR body - the one place a stale floor is actionable. Never fatal:
# the scheduled Dependency floors workflow is what fails on a truly broken floor.
- name: Report cross-product dependency floors
run: |
set -uo pipefail
Expand All @@ -160,8 +148,7 @@ jobs:
run: |
set -euo pipefail

# One branch per batch. Dated rather than versioned: a batch has no single version,
# and the run number keeps same-day batches distinct.
# Dated rather than versioned: a batch has no single version.
BRANCH="release/batch-$(date -u +%Y-%m-%d)-${GITHUB_RUN_NUMBER}"

git config user.name "github-actions[bot]"
Expand Down
Loading