diff --git a/src/PackageRegistryService/API/Handlers/DownloadsHandlers.cs b/src/PackageRegistryService/API/Handlers/DownloadsHandlers.cs index 02814b6..abe0bee 100644 --- a/src/PackageRegistryService/API/Handlers/DownloadsHandlers.cs +++ b/src/PackageRegistryService/API/Handlers/DownloadsHandlers.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.EntityFrameworkCore; using PackageRegistryService.Models; +using static AVPRIndex.Domain; namespace PackageRegistryService.API.Handlers { @@ -27,24 +28,14 @@ await database.Downloads public static async Task, NotFound, Ok>> GetDownloadsByNameAndVersion(string name, string version, ValidationPackageDb database) { - var splt = version.Split('.'); - if (splt.Length != 3) + var semVerOpt = SemVer.tryParse(version); + if (semVerOpt is null) { - return TypedResults.BadRequest("version was not a of valid format MAJOR.MINOR.REVISION"); + return TypedResults.BadRequest($"{version} is not a valid semantic version."); } + var semVer = semVerOpt.Value; - int major; int minor; int revision; - - if ( - !int.TryParse(splt[0], out major) - || !int.TryParse(splt[1], out minor) - || !int.TryParse(splt[2], out revision) - ) - { - return TypedResults.BadRequest("version was not a of valid format MAJOR.MINOR.REVISION"); - } - - var downloads = await database.Downloads.FindAsync(name, major, minor, revision); + var downloads = await database.Downloads.FindAsync(name, semVer.Major, semVer.Minor, semVer.Patch, semVer.PreRelease, semVer.BuildMetadata); return downloads is null ? TypedResults.NotFound($"No download stats for package '{name}' version '{version}' available.") diff --git a/src/PackageRegistryService/API/Handlers/PackageHandlers.cs b/src/PackageRegistryService/API/Handlers/PackageHandlers.cs index c425068..aff6e60 100644 --- a/src/PackageRegistryService/API/Handlers/PackageHandlers.cs +++ b/src/PackageRegistryService/API/Handlers/PackageHandlers.cs @@ -2,6 +2,8 @@ using PackageRegistryService.Models; using Microsoft.EntityFrameworkCore; using PackageRegistryService.Pages.Components; +using AVPRIndex; +using static AVPRIndex.Domain; namespace PackageRegistryService.API.Handlers { @@ -27,7 +29,7 @@ public static async Task, Conflict>> Get public static async Task, NotFound, Conflict>> GetLatestPackageByName(string name, ValidationPackageDb database) { var package = await database.ValidationPackages - .Where(p => p.Name == name) + .Where(p => p.Name == name && p.BuildMetadataVersionSuffix == "" && p.BuildMetadataVersionSuffix == "") // only serve stable package versions here .OrderByDescending(p => p.MajorVersion) .ThenByDescending(p => p.MinorVersion) .ThenByDescending(p => p.PatchVersion) @@ -51,24 +53,14 @@ public static async Task, NotFound, Confli public static async Task, NotFound, Conflict, Ok>> GetPackageByNameAndVersion(string name, string version, ValidationPackageDb database) { - var splt = version.Split('.'); - if (splt.Length != 3) + var semVerOpt = SemVer.tryParse(version); + if (semVerOpt is null) { - return TypedResults.BadRequest("version was not a of valid format MAJOR.MINOR.REVISION"); + return TypedResults.BadRequest($"{version} is not a valid semantic version."); } + var semVer = semVerOpt.Value; - int major; int minor; int revision; - - if ( - !int.TryParse(splt[0], out major) - || !int.TryParse(splt[1], out minor) - || !int.TryParse(splt[2], out revision) - ) - { - return TypedResults.BadRequest("version was not a of valid format MAJOR.MINOR.REVISION"); - } - - var package = await database.ValidationPackages.FindAsync(name, major, minor, revision); + var package = await database.ValidationPackages.FindAsync(name, semVer.Major, semVer.Minor, semVer.Patch, semVer.PreRelease, semVer.BuildMetadata); if (package is null) { @@ -88,7 +80,7 @@ public static async Task, NotFound, Conflict< public static async Task, Conflict, UnauthorizedHttpResult, UnprocessableEntity>> CreatePackage(ValidationPackage package, ValidationPackageDb database) { - var existing = await database.ValidationPackages.FindAsync(package.Name, package.MajorVersion, package.MinorVersion, package.PatchVersion); + var existing = await database.ValidationPackages.FindAsync(package.Name, package.MajorVersion, package.MinorVersion, package.PatchVersion, package.PreReleaseVersionSuffix, package.BuildMetadataVersionSuffix); if (existing != null) { return TypedResults.Conflict(); diff --git a/src/PackageRegistryService/API/Handlers/VerificationHandlers.cs b/src/PackageRegistryService/API/Handlers/VerificationHandlers.cs index b9ccd52..db98da5 100644 --- a/src/PackageRegistryService/API/Handlers/VerificationHandlers.cs +++ b/src/PackageRegistryService/API/Handlers/VerificationHandlers.cs @@ -14,7 +14,9 @@ public static async Task> Verify(Pack hashedPackage.PackageName, hashedPackage.PackageMajorVersion, hashedPackage.PackageMinorVersion, - hashedPackage.PackagePatchVersion + hashedPackage.PackagePatchVersion, + hashedPackage.PackagePreReleaseVersionSuffix, + hashedPackage.PackageBuildMetadataVersionSuffix ); var existingPackage = await @@ -22,7 +24,9 @@ public static async Task> Verify(Pack hashedPackage.PackageName, hashedPackage.PackageMajorVersion, hashedPackage.PackageMinorVersion, - hashedPackage.PackagePatchVersion + hashedPackage.PackagePatchVersion, + hashedPackage.PackagePreReleaseVersionSuffix, + hashedPackage.PackageBuildMetadataVersionSuffix ); if (existingHash is null || existingPackage is null) diff --git a/src/PackageRegistryService/Data/DataInitializer.cs b/src/PackageRegistryService/Data/DataInitializer.cs index 1a6f7da..d3c08a7 100644 --- a/src/PackageRegistryService/Data/DataInitializer.cs +++ b/src/PackageRegistryService/Data/DataInitializer.cs @@ -45,6 +45,8 @@ public static void SeedData(ValidationPackageDb context) MajorVersion = i.Metadata.MajorVersion, MinorVersion = i.Metadata.MinorVersion, PatchVersion = i.Metadata.PatchVersion, + PreReleaseVersionSuffix = i.Metadata.PreReleaseVersionSuffix, + BuildMetadataVersionSuffix= i.Metadata.BuildMetadataVersionSuffix, PackageContent = Encoding.UTF8.GetBytes(content), ReleaseDate = new(i.LastUpdated.Year, i.LastUpdated.Month, i.LastUpdated.Day), Tags = i.Metadata.Tags, @@ -78,6 +80,8 @@ public static void SeedData(ValidationPackageDb context) PackageMajorVersion = i.Metadata.MajorVersion, PackageMinorVersion = i.Metadata.MinorVersion, PackagePatchVersion = i.Metadata.PatchVersion, + PackagePreReleaseVersionSuffix = i.Metadata.PreReleaseVersionSuffix, + PackageBuildMetadataVersionSuffix = i.Metadata.BuildMetadataVersionSuffix, Hash = hash, }; }); @@ -94,6 +98,8 @@ public static void SeedData(ValidationPackageDb context) PackageMajorVersion = i.Metadata.MajorVersion, PackageMinorVersion = i.Metadata.MinorVersion, PackagePatchVersion = i.Metadata.PatchVersion, + PackagePreReleaseVersionSuffix = i.Metadata.PreReleaseVersionSuffix, + PackageBuildMetadataVersionSuffix = i.Metadata.BuildMetadataVersionSuffix, Downloads = 0 }; }); diff --git a/src/PackageRegistryService/Migrations/20240621105252_FullSemVer.Designer.cs b/src/PackageRegistryService/Migrations/20240621105252_FullSemVer.Designer.cs new file mode 100644 index 0000000..d3bccec --- /dev/null +++ b/src/PackageRegistryService/Migrations/20240621105252_FullSemVer.Designer.cs @@ -0,0 +1,229 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using PackageRegistryService.Models; + +#nullable disable + +namespace PackageRegistryService.Migrations +{ + [DbContext(typeof(ValidationPackageDb))] + [Migration("20240621105252_FullSemVer")] + partial class FullSemVer + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("PackageRegistryService.Models.PackageContentHash", b => + { + b.Property("PackageName") + .HasColumnType("text"); + + b.Property("PackageMajorVersion") + .HasColumnType("integer"); + + b.Property("PackageMinorVersion") + .HasColumnType("integer"); + + b.Property("PackagePatchVersion") + .HasColumnType("integer"); + + b.Property("PackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b.Property("PackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + + b.Property("Hash") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion", "PackagePreReleaseVersionSuffix", "PackageBuildMetadataVersionSuffix"); + + b.ToTable("Hashes"); + }); + + modelBuilder.Entity("PackageRegistryService.Models.PackageDownloads", b => + { + b.Property("PackageName") + .HasColumnType("text"); + + b.Property("PackageMajorVersion") + .HasColumnType("integer"); + + b.Property("PackageMinorVersion") + .HasColumnType("integer"); + + b.Property("PackagePatchVersion") + .HasColumnType("integer"); + + b.Property("PackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b.Property("PackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + + b.Property("Downloads") + .HasColumnType("integer"); + + b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion", "PackagePreReleaseVersionSuffix", "PackageBuildMetadataVersionSuffix"); + + b.ToTable("Downloads"); + }); + + modelBuilder.Entity("PackageRegistryService.Models.ValidationPackage", b => + { + b.Property("Name") + .HasColumnType("text"); + + b.Property("MajorVersion") + .HasColumnType("integer"); + + b.Property("MinorVersion") + .HasColumnType("integer"); + + b.Property("PatchVersion") + .HasColumnType("integer"); + + b.Property("PreReleaseVersionSuffix") + .HasColumnType("text"); + + b.Property("BuildMetadataVersionSuffix") + .HasColumnType("text"); + + b.Property("CQCHookEndpoint") + .HasColumnType("text"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text"); + + b.Property("PackageContent") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("ReleaseDate") + .HasColumnType("date"); + + b.Property("ReleaseNotes") + .HasColumnType("text"); + + b.Property("Summary") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Name", "MajorVersion", "MinorVersion", "PatchVersion", "PreReleaseVersionSuffix", "BuildMetadataVersionSuffix"); + + b.ToTable("ValidationPackages"); + }); + + modelBuilder.Entity("PackageRegistryService.Models.ValidationPackage", b => + { + b.OwnsMany("AVPRIndex.Domain+Author", "Authors", b1 => + { + b1.Property("ValidationPackageName") + .HasColumnType("text"); + + b1.Property("ValidationPackageMajorVersion") + .HasColumnType("integer"); + + b1.Property("ValidationPackageMinorVersion") + .HasColumnType("integer"); + + b1.Property("ValidationPackagePatchVersion") + .HasColumnType("integer"); + + b1.Property("ValidationPackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b1.Property("ValidationPackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + b1.Property("Affiliation") + .HasColumnType("text"); + + b1.Property("AffiliationLink") + .HasColumnType("text"); + + b1.Property("Email") + .HasColumnType("text"); + + b1.Property("FullName") + .HasColumnType("text"); + + b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix", "Id"); + + b1.ToTable("ValidationPackages"); + + b1.ToJson("Authors"); + + b1.WithOwner() + .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix"); + }); + + b.OwnsMany("AVPRIndex.Domain+OntologyAnnotation", "Tags", b1 => + { + b1.Property("ValidationPackageName") + .HasColumnType("text"); + + b1.Property("ValidationPackageMajorVersion") + .HasColumnType("integer"); + + b1.Property("ValidationPackageMinorVersion") + .HasColumnType("integer"); + + b1.Property("ValidationPackagePatchVersion") + .HasColumnType("integer"); + + b1.Property("ValidationPackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b1.Property("ValidationPackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + b1.Property("Name") + .HasColumnType("text"); + + b1.Property("TermAccessionNumber") + .HasColumnType("text"); + + b1.Property("TermSourceREF") + .HasColumnType("text"); + + b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix", "Id"); + + b1.ToTable("ValidationPackages"); + + b1.ToJson("Tags"); + + b1.WithOwner() + .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix"); + }); + + b.Navigation("Authors"); + + b.Navigation("Tags"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/PackageRegistryService/Migrations/20240621105252_FullSemVer.cs b/src/PackageRegistryService/Migrations/20240621105252_FullSemVer.cs new file mode 100644 index 0000000..74b7726 --- /dev/null +++ b/src/PackageRegistryService/Migrations/20240621105252_FullSemVer.cs @@ -0,0 +1,138 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PackageRegistryService.Migrations +{ + /// + public partial class FullSemVer : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_ValidationPackages", + table: "ValidationPackages"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Hashes", + table: "Hashes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Downloads", + table: "Downloads"); + + migrationBuilder.AddColumn( + name: "PreReleaseVersionSuffix", + table: "ValidationPackages", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "BuildMetadataVersionSuffix", + table: "ValidationPackages", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "PackagePreReleaseVersionSuffix", + table: "Hashes", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "PackageBuildMetadataVersionSuffix", + table: "Hashes", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "PackagePreReleaseVersionSuffix", + table: "Downloads", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "PackageBuildMetadataVersionSuffix", + table: "Downloads", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddPrimaryKey( + name: "PK_ValidationPackages", + table: "ValidationPackages", + columns: new[] { "Name", "MajorVersion", "MinorVersion", "PatchVersion", "PreReleaseVersionSuffix", "BuildMetadataVersionSuffix" }); + + migrationBuilder.AddPrimaryKey( + name: "PK_Hashes", + table: "Hashes", + columns: new[] { "PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion", "PackagePreReleaseVersionSuffix", "PackageBuildMetadataVersionSuffix" }); + + migrationBuilder.AddPrimaryKey( + name: "PK_Downloads", + table: "Downloads", + columns: new[] { "PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion", "PackagePreReleaseVersionSuffix", "PackageBuildMetadataVersionSuffix" }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropPrimaryKey( + name: "PK_ValidationPackages", + table: "ValidationPackages"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Hashes", + table: "Hashes"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Downloads", + table: "Downloads"); + + migrationBuilder.DropColumn( + name: "PreReleaseVersionSuffix", + table: "ValidationPackages"); + + migrationBuilder.DropColumn( + name: "BuildMetadataVersionSuffix", + table: "ValidationPackages"); + + migrationBuilder.DropColumn( + name: "PackagePreReleaseVersionSuffix", + table: "Hashes"); + + migrationBuilder.DropColumn( + name: "PackageBuildMetadataVersionSuffix", + table: "Hashes"); + + migrationBuilder.DropColumn( + name: "PackagePreReleaseVersionSuffix", + table: "Downloads"); + + migrationBuilder.DropColumn( + name: "PackageBuildMetadataVersionSuffix", + table: "Downloads"); + + migrationBuilder.AddPrimaryKey( + name: "PK_ValidationPackages", + table: "ValidationPackages", + columns: new[] { "Name", "MajorVersion", "MinorVersion", "PatchVersion" }); + + migrationBuilder.AddPrimaryKey( + name: "PK_Hashes", + table: "Hashes", + columns: new[] { "PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion" }); + + migrationBuilder.AddPrimaryKey( + name: "PK_Downloads", + table: "Downloads", + columns: new[] { "PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion" }); + } + } +} diff --git a/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs b/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs index 365d409..d196a9f 100644 --- a/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs +++ b/src/PackageRegistryService/Migrations/ValidationPackageDbModelSnapshot.cs @@ -36,11 +36,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PackagePatchVersion") .HasColumnType("integer"); + b.Property("PackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b.Property("PackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + b.Property("Hash") .IsRequired() .HasColumnType("text"); - b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion"); + b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion", "PackagePreReleaseVersionSuffix", "PackageBuildMetadataVersionSuffix"); b.ToTable("Hashes"); }); @@ -59,10 +65,16 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PackagePatchVersion") .HasColumnType("integer"); + b.Property("PackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b.Property("PackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + b.Property("Downloads") .HasColumnType("integer"); - b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion"); + b.HasKey("PackageName", "PackageMajorVersion", "PackageMinorVersion", "PackagePatchVersion", "PackagePreReleaseVersionSuffix", "PackageBuildMetadataVersionSuffix"); b.ToTable("Downloads"); }); @@ -81,6 +93,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PatchVersion") .HasColumnType("integer"); + b.Property("PreReleaseVersionSuffix") + .HasColumnType("text"); + + b.Property("BuildMetadataVersionSuffix") + .HasColumnType("text"); + b.Property("CQCHookEndpoint") .HasColumnType("text"); @@ -102,7 +120,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); - b.HasKey("Name", "MajorVersion", "MinorVersion", "PatchVersion"); + b.HasKey("Name", "MajorVersion", "MinorVersion", "PatchVersion", "PreReleaseVersionSuffix", "BuildMetadataVersionSuffix"); b.ToTable("ValidationPackages"); }); @@ -123,6 +141,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.Property("ValidationPackagePatchVersion") .HasColumnType("integer"); + b1.Property("ValidationPackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b1.Property("ValidationPackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + b1.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("integer"); @@ -139,14 +163,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.Property("FullName") .HasColumnType("text"); - b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "Id"); + b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix", "Id"); b1.ToTable("ValidationPackages"); b1.ToJson("Authors"); b1.WithOwner() - .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion"); + .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix"); }); b.OwnsMany("AVPRIndex.Domain+OntologyAnnotation", "Tags", b1 => @@ -163,6 +187,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.Property("ValidationPackagePatchVersion") .HasColumnType("integer"); + b1.Property("ValidationPackagePreReleaseVersionSuffix") + .HasColumnType("text"); + + b1.Property("ValidationPackageBuildMetadataVersionSuffix") + .HasColumnType("text"); + b1.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("integer"); @@ -176,14 +206,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) b1.Property("TermSourceREF") .HasColumnType("text"); - b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "Id"); + b1.HasKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix", "Id"); b1.ToTable("ValidationPackages"); b1.ToJson("Tags"); b1.WithOwner() - .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion"); + .HasForeignKey("ValidationPackageName", "ValidationPackageMajorVersion", "ValidationPackageMinorVersion", "ValidationPackagePatchVersion", "ValidationPackagePreReleaseVersionSuffix", "ValidationPackageBuildMetadataVersionSuffix"); }); b.Navigation("Authors"); diff --git a/src/PackageRegistryService/Models/PackageContentHash.cs b/src/PackageRegistryService/Models/PackageContentHash.cs index 746a41b..6e8f175 100644 --- a/src/PackageRegistryService/Models/PackageContentHash.cs +++ b/src/PackageRegistryService/Models/PackageContentHash.cs @@ -3,33 +3,45 @@ namespace PackageRegistryService.Models { - [PrimaryKey(nameof(PackageName), nameof(PackageMajorVersion), nameof(PackageMinorVersion), nameof(PackagePatchVersion))] + [PrimaryKey(nameof(PackageName), nameof(PackageMajorVersion), nameof(PackageMinorVersion), nameof(PackagePatchVersion), nameof(PackagePreReleaseVersionSuffix), nameof(PackageBuildMetadataVersionSuffix))] public class PackageContentHash { /// /// The name of the validation package. /// /// MyPackage - [Key] public required string PackageName { get; set; } + /// /// SemVer major version of the validation package. /// /// 1 - [Key] public required int PackageMajorVersion { get; set; } + /// /// SemVer minor version of the validation package. /// /// 0 - [Key] public required int PackageMinorVersion { get; set; } + /// /// SemVer patch version of the validationpackage. /// /// 0 - public required int PackagePatchVersion { get; set; } + + /// + /// SemVer prerelease version of the validationpackage. + /// + /// alpha.1 + public required string PackagePreReleaseVersionSuffix { get; set; } + + /// + /// SemVer buildmetadata of the validationpackage. + /// + /// 0 + public required string PackageBuildMetadataVersionSuffix { get; set; } + /// /// MD5 hash hex string of the package content. /// diff --git a/src/PackageRegistryService/Models/PackageDownloads.cs b/src/PackageRegistryService/Models/PackageDownloads.cs index 607a6cd..a4bea9e 100644 --- a/src/PackageRegistryService/Models/PackageDownloads.cs +++ b/src/PackageRegistryService/Models/PackageDownloads.cs @@ -4,33 +4,46 @@ namespace PackageRegistryService.Models { - [PrimaryKey(nameof(PackageName), nameof(PackageMajorVersion), nameof(PackageMinorVersion), nameof(PackagePatchVersion))] + [PrimaryKey(nameof(PackageName), nameof(PackageMajorVersion), nameof(PackageMinorVersion), nameof(PackagePatchVersion), nameof(PackagePreReleaseVersionSuffix), nameof(PackageBuildMetadataVersionSuffix))] public class PackageDownloads { /// /// The name of the validation package. /// /// MyPackage - [Key] public required string PackageName { get; set; } + /// /// SemVer major version of the validation package. /// /// 1 - [Key] public required int PackageMajorVersion { get; set; } + /// /// SemVer minor version of the validation package. /// /// 0 - [Key] public required int PackageMinorVersion { get; set; } + /// /// SemVer patch version of the validationpackage. /// /// 0 public required int PackagePatchVersion { get; set; } + + /// + /// SemVer prerelease version of the validationpackage. + /// + /// alpha.1 + public required string PackagePreReleaseVersionSuffix { get; set; } + + /// + /// SemVer buildmetadata of the validationpackage. + /// + /// 0 + public required string PackageBuildMetadataVersionSuffix { get; set; } + /// /// Number of downloads for the package. /// diff --git a/src/PackageRegistryService/Models/ValidationPackage.cs b/src/PackageRegistryService/Models/ValidationPackage.cs index 1fbf8c2..1a48c5c 100644 --- a/src/PackageRegistryService/Models/ValidationPackage.cs +++ b/src/PackageRegistryService/Models/ValidationPackage.cs @@ -4,27 +4,29 @@ using System.ComponentModel.DataAnnotations; using System.Text; using System.Security.Cryptography; - +using AVPRIndex; +using static AVPRIndex.Domain; namespace PackageRegistryService.Models { /// /// /// - [PrimaryKey(nameof(Name), nameof(MajorVersion), nameof(MinorVersion), nameof(PatchVersion))] + [PrimaryKey(nameof(Name), nameof(MajorVersion), nameof(MinorVersion), nameof(PatchVersion), nameof(PreReleaseVersionSuffix), nameof(BuildMetadataVersionSuffix))] public class ValidationPackage { /// /// The name of the validation package. /// /// MyPackage - [Key] public required string Name { get; set; } + /// /// Single sentence validation package description. /// /// MyPackage does the thing public required string Summary { get; set; } + /// /// Free text validation package description. /// @@ -34,59 +36,90 @@ public class ValidationPackage /// It does it very fast, it does it very swell. /// public required string Description { get; set; } + /// /// SemVer major version of the validation package. /// /// 1 - [Key] public required int MajorVersion { get; set; } + /// /// SemVer minor version of the validation package. /// /// 0 - [Key] public required int MinorVersion { get; set; } + /// /// SemVer patch version of the validationpackage. /// /// 0 - public required int PatchVersion { get; set; } + + /// + /// SemVer prerelease version of the validationpackage. + /// + /// alpha.1 + public string PreReleaseVersionSuffix { get; set; } = ""; + + /// + /// SemVer buildmetadata of the validationpackage. + /// + /// 0 + public string BuildMetadataVersionSuffix { get; set; } = ""; + /// /// base64 encoded binary content of the validation package. /// /// aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1kUXc0dzlXZ1hjUQ== public required byte[] PackageContent { get; set; } + /// /// /// public required DateOnly ReleaseDate { get; set; } + /// /// /// public ICollection? Tags { get; set; } + /// /// /// public string? ReleaseNotes { get; set; } + /// /// /// public string? CQCHookEndpoint { get; set; } + /// /// /// public ICollection? Authors { get; set; } // https://www.learnentityframeworkcore.com/relationships#navigation-properties + /// /// /// /// A string containing the semantic version of the validation package - public string GetSemanticVersionString() => $"{MajorVersion}.{MinorVersion}.{PatchVersion}"; + public string GetSemanticVersionString() + { + SemVer semVer = new SemVer { + Major = MajorVersion, + Minor = MinorVersion, + Patch = PatchVersion, + PreRelease = PreReleaseVersionSuffix, + BuildMetadata = BuildMetadataVersionSuffix + }; + return SemVer.toString(semVer); + } + /// /// Converts the binary content of the validation package to a string by converting it to base64 and then decoding it as UTF8. /// /// A string containing the package content public string GetPackageScriptContent() => Encoding.UTF8.GetString(Convert.FromBase64String(Convert.ToBase64String(PackageContent))); + /// /// Returns the md5 hash of the package content. /// @@ -95,6 +128,7 @@ public string GetPackageContentHash() { return AVPRIndex.Hash.hashContent(PackageContent); } + /// /// Returns whether the package content CR characters - meaning its is has not been unified to only use LF. /// diff --git a/src/PackageRegistryService/Models/ValidationPackageDb.cs b/src/PackageRegistryService/Models/ValidationPackageDb.cs index 82b032a..3a47bd7 100644 --- a/src/PackageRegistryService/Models/ValidationPackageDb.cs +++ b/src/PackageRegistryService/Models/ValidationPackageDb.cs @@ -7,8 +7,7 @@ public class ValidationPackageDb : DbContext { - public ValidationPackageDb(DbContextOptions options) - : base(options) { } + public ValidationPackageDb(DbContextOptions options) : base(options) { } public DbSet ValidationPackages => Set(); public DbSet Hashes => Set(); @@ -41,7 +40,7 @@ public static bool ValidatePackageContent(ValidationPackage package, ValidationP } public static bool CreatePackageContentHash(ValidationPackage package, ValidationPackageDb database) { - var result = database.Hashes.SingleOrDefault(d => d.PackageName == package.Name && d.PackageMajorVersion == package.MajorVersion && d.PackageMinorVersion == package.MinorVersion && d.PackagePatchVersion == package.PatchVersion); + var result = database.Hashes.SingleOrDefault(d => d.PackageName == package.Name && d.PackageMajorVersion == package.MajorVersion && d.PackageMinorVersion == package.MinorVersion && d.PackagePatchVersion == package.PatchVersion && d.PackagePreReleaseVersionSuffix == package.PreReleaseVersionSuffix && d.PackageBuildMetadataVersionSuffix == package.BuildMetadataVersionSuffix); if (result != null) { @@ -55,6 +54,8 @@ public static bool CreatePackageContentHash(ValidationPackage package, Validatio PackageMajorVersion = package.MajorVersion, PackageMinorVersion = package.MinorVersion, PackagePatchVersion = package.PatchVersion, + PackagePreReleaseVersionSuffix = package.PreReleaseVersionSuffix, + PackageBuildMetadataVersionSuffix = package.BuildMetadataVersionSuffix, Hash = package.GetPackageContentHash() }; database.Hashes.Add(h); @@ -63,8 +64,8 @@ public static bool CreatePackageContentHash(ValidationPackage package, Validatio } public static void IncrementDownloadCount(ValidationPackage package, ValidationPackageDb database) { - var result = database.Downloads.SingleOrDefault(d => d.PackageName == package.Name && d.PackageMajorVersion == package.MajorVersion && d.PackageMinorVersion == package.MinorVersion && d.PackagePatchVersion == package.PatchVersion); - + var result = database.Downloads.SingleOrDefault(d => d.PackageName == package.Name && d.PackageMajorVersion == package.MajorVersion && d.PackageMinorVersion == package.MinorVersion && d.PackagePatchVersion == package.PatchVersion && d.PackagePreReleaseVersionSuffix == package.PreReleaseVersionSuffix && d.PackageBuildMetadataVersionSuffix == package.BuildMetadataVersionSuffix); + if (result != null) { result.Downloads += 1; // increment download count for each package @@ -77,6 +78,8 @@ public static void IncrementDownloadCount(ValidationPackage package, ValidationP PackageMajorVersion = package.MajorVersion, PackageMinorVersion = package.MinorVersion, PackagePatchVersion = package.PatchVersion, + PackagePreReleaseVersionSuffix = package.PreReleaseVersionSuffix, + PackageBuildMetadataVersionSuffix = package.BuildMetadataVersionSuffix, Downloads = 1 }; database.Downloads.Add(d);