Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
54 changes: 33 additions & 21 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
@@ -1,28 +1,40 @@
name: .NET

on:
push:
branches: [ main ]
branches: [main]
pull_request:
branches: [ main ]

branches: [main]
workflow_dispatch:
permissions:
contents: read
jobs:
build:

test:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
dotnet: ['8.0.x', '10.0.x']
env:
DOTNET_ROLL_FORWARD: ${{ matrix.dotnet == '10.0.x' && 'LatestMajor' || 'LatestPatch' }}
LISTEN_API_TEST_RUNTIME: ${{ matrix.dotnet == '10.0.x' && '10' || '8' }}
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
working-directory: src
- name: Build
run: dotnet build PodcastAPI --no-restore
working-directory: src
- name: Test
run: dotnet test PodcastAPI.Tests --verbosity normal
working-directory: src
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet }}
- run: dotnet restore src/PodcastAPI.net.sln --locked-mode
- run: dotnet build src/PodcastAPI.net.sln --no-restore -c Release
- run: dotnet test src/PodcastAPI.Tests --no-build -c Release --filter 'TestCategory!=Integration'
- run: bash scripts/verify-package.sh
mock-integration:
runs-on: ubuntu-latest
env:
DOTNET_ROLL_FORWARD: LatestMajor
LISTEN_API_MOCK_INTEGRATION: '1'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- run: dotnet restore src/PodcastAPI.net.sln --locked-mode
- run: dotnet test src/PodcastAPI.Tests --no-restore -c Release --filter 'TestCategory=Integration'
9 changes: 9 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<Deterministic>true</Deterministic>
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
</PropertyGroup>
</Project>
13,509 changes: 687 additions & 12,822 deletions README.md

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions scripts/verify-package.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/.."

dotnet_sdk_verify_dir=$(mktemp -d)
trap 'rm -rf "$dotnet_sdk_verify_dir"' EXIT

dotnet pack src/PodcastAPI --no-restore -c Release -o "$dotnet_sdk_verify_dir/packages"
packages=("$dotnet_sdk_verify_dir"/packages/PodcastAPI.*.nupkg)
if [ "${#packages[@]}" -ne 1 ] || [ ! -f "${packages[0]}" ]; then
echo 'Expected one PodcastAPI NuGet package' >&2
exit 1
fi
package_name=$(basename "${packages[0]}")
package_version=${package_name#PodcastAPI.}
package_version=${package_version%.nupkg}
mkdir "$dotnet_sdk_verify_dir/consumer"
cat > "$dotnet_sdk_verify_dir/consumer/Consumer.csproj" <<XML
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup><PackageReference Include="PodcastAPI" Version="$package_version" /></ItemGroup>
</Project>
XML
cat > "$dotnet_sdk_verify_dir/consumer/NuGet.Config" <<XML
<configuration>
<packageSources>
<clear />
<add key="local" value="$dotnet_sdk_verify_dir/packages" />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
<packageSourceMapping>
<packageSource key="local"><package pattern="PodcastAPI" /></packageSource>
<packageSource key="nuget"><package pattern="*" /></packageSource>
</packageSourceMapping>
</configuration>
XML
# Compile every generated README example against the packed binary, not a project reference.
cp src/SampleApp/GeneratedExamples.cs "$dotnet_sdk_verify_dir/consumer/GeneratedExamples.cs"
cat > "$dotnet_sdk_verify_dir/consumer/Program.cs" <<'CS'
using System.Net;
using PodcastAPI;

using var http = new HttpClient(new OfflineHandler());
using var client = new Client(httpClient: http);
var response = await client.UpdatePlaylistItemNotes(new Dictionary<string, string>
{
["id"] = "playlist/encoded", ["item_id"] = "23", ["notes"] = "",
});
if (response.StatusCode != HttpStatusCode.OK || (int)response.ToJSON<dynamic>()!.id != 23)
throw new Exception("Packaged response did not deserialize");
Console.WriteLine("Packaged SDK and all README examples verified without API requests.");

sealed class OfflineHandler : HttpMessageHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken token)
{
if (request.Method != HttpMethod.Put ||
request.RequestUri!.AbsolutePath != "/api/v2/playlists/playlist%2Fencoded/items/23" ||
request.Headers.Contains("X-ListenAPI-Key") ||
await request.Content!.ReadAsStringAsync(token) != "notes=")
throw new Exception("Packaged request contract mismatch");
return new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("{\"id\":23}") };
}
}
CS
# A fresh cache and source mapping guarantee PodcastAPI is the newly packed local artifact.
NUGET_PACKAGES="$dotnet_sdk_verify_dir/cache" dotnet restore "$dotnet_sdk_verify_dir/consumer/Consumer.csproj"
NUGET_PACKAGES="$dotnet_sdk_verify_dir/cache" dotnet run --project "$dotnet_sdk_verify_dir/consumer/Consumer.csproj" --no-restore -c Release
Loading
Loading