From 3b97cb7c368b8843b3de4192ea2515125a54b00e Mon Sep 17 00:00:00 2001
From: Jamie Magee <jamie.magee@gmail.com>
Date: Mon, 17 Oct 2022 23:27:03 -0700
Subject: [PATCH] fix(datasource/dotnet): account for nullable releases
 (#18292)

---
 lib/modules/datasource/dotnet/index.ts  | 29 ++++++++++++++++++-------
 lib/modules/datasource/dotnet/readme.md |  1 +
 lib/modules/datasource/dotnet/schema.ts |  9 ++++----
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/lib/modules/datasource/dotnet/index.ts b/lib/modules/datasource/dotnet/index.ts
index 35ea957eb3..4b10903730 100644
--- a/lib/modules/datasource/dotnet/index.ts
+++ b/lib/modules/datasource/dotnet/index.ts
@@ -1,8 +1,10 @@
+import is from '@sindresorhus/is';
 import { cache } from '../../../util/cache/package/decorator';
 import type { HttpResponse } from '../../../util/http/types';
 import { Datasource } from '../datasource';
 import type { GetReleasesConfig, Release, ReleaseResult } from '../types';
 import {
+  DotnetRelease,
   DotnetReleases,
   DotnetReleasesIndex,
   DotnetReleasesIndexSchema,
@@ -71,7 +73,8 @@ export class DotnetDatasource extends Datasource {
 
   @cache({
     namespace: `datasource-${DotnetDatasource.id}`,
-    key: (releaseUrl: string) => releaseUrl,
+    key: (releaseUrl: string, packageName: string) =>
+      `${releaseUrl}:${packageName}`,
     ttlMinutes: 1440,
   })
   async getChannelReleases(
@@ -91,13 +94,23 @@ export class DotnetDatasource extends Datasource {
     if (body) {
       const type = DotnetDatasource.getType(packageName);
       const { releases: releases } = body;
-      result = releases.map((release) => {
-        return {
-          version: release[type].version,
-          releaseTimestamp: release['release-date'],
-          changelogUrl: release['release-notes'],
-        };
-      });
+      result = releases
+        .filter(
+          (
+            release
+          ): release is {
+            [P in keyof DotnetRelease]: NonNullable<DotnetRelease[P]>;
+          } => {
+            return !is.nullOrUndefined(release[type]);
+          }
+        )
+        .map((release) => {
+          return {
+            version: release[type].version,
+            releaseTimestamp: release['release-date'],
+            changelogUrl: release['release-notes'],
+          };
+        });
     }
 
     return result;
diff --git a/lib/modules/datasource/dotnet/readme.md b/lib/modules/datasource/dotnet/readme.md
index 19fcb5f560..c0277d6735 100644
--- a/lib/modules/datasource/dotnet/readme.md
+++ b/lib/modules/datasource/dotnet/readme.md
@@ -1 +1,2 @@
 This datasource returns releases of the .NET Runtime and SDK.
+It only accepts dependencies with the name `dotnet-sdk` or `dotnet-runtime`.
diff --git a/lib/modules/datasource/dotnet/schema.ts b/lib/modules/datasource/dotnet/schema.ts
index 878e742ba3..3ae3a118c6 100644
--- a/lib/modules/datasource/dotnet/schema.ts
+++ b/lib/modules/datasource/dotnet/schema.ts
@@ -29,13 +29,13 @@ const ReleaseDetails = z.object({
   version: z.string(),
   'version-display': z.string(),
 });
-const Release = z.object({
+const ReleaseSchema = z.object({
   'release-date': z.date(),
   'release-version': z.string(),
   security: z.boolean(),
   'release-notes': z.string(),
-  runtime: ReleaseDetails,
-  sdk: ReleaseDetails,
+  runtime: z.nullable(ReleaseDetails),
+  sdk: z.nullable(ReleaseDetails),
 });
 export const DotnetReleasesSchema = z.object({
   'channel-version': z.string(),
@@ -44,8 +44,9 @@ export const DotnetReleasesSchema = z.object({
   'latest-runtime': z.string(),
   'latest-sdk': z.string(),
   'support-phase': SupportPhase,
-  releases: z.array(Release),
+  releases: z.array(ReleaseSchema),
 });
 
 export type DotnetReleasesIndex = z.infer<typeof DotnetReleasesIndexSchema>;
 export type DotnetReleases = z.infer<typeof DotnetReleasesSchema>;
+export type DotnetRelease = z.infer<typeof ReleaseSchema>;
-- 
GitLab