diff --git a/README.md b/README.md index aa24b7e..a464bf5 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ steps: license: # Optional package license purl: # Optional package purl cpe23: # Optional package cpe23 - relationships: # Relationships + relationships: # Optional relationships - type: # Relationship type element: # Related element comment: # Optional comment @@ -189,7 +189,7 @@ steps: to: # Destination SPDX file name package: # Package ID recursive: true # Optional recursive flag - relationships: # Relationships + relationships: # Optional relationships - type: # Relationship type element: # Related element comment: # Optional comment diff --git a/src/DemaConsulting.SpdxTool/Commands/AddPackage.cs b/src/DemaConsulting.SpdxTool/Commands/AddPackage.cs index fc6de33..2c24c83 100644 --- a/src/DemaConsulting.SpdxTool/Commands/AddPackage.cs +++ b/src/DemaConsulting.SpdxTool/Commands/AddPackage.cs @@ -44,7 +44,7 @@ public class AddPackage : Command " license: # Optional package license", " purl: # Optional package purl", " cpe23: # Optional package cpe23", - " relationships: # Relationships", + " relationships: # Optional relationships", " - type: # Relationship type", " element: # Related element", " comment: # Optional comment", @@ -89,8 +89,7 @@ public override void Run(YamlMappingNode step, Dictionary variab var package = ParsePackage("add-package", packageMap, variables); // Parse the relationships - var relationshipsSequence = GetMapSequence(inputs, "relationships") ?? - throw new YamlException(step.Start, step.End, "'add-package' missing 'relationships' input"); + var relationshipsSequence = GetMapSequence(inputs, "relationships"); var relationships = AddRelationship.Parse("add-package", package.Id, relationshipsSequence, variables); // Add the package diff --git a/src/DemaConsulting.SpdxTool/Commands/AddRelationship.cs b/src/DemaConsulting.SpdxTool/Commands/AddRelationship.cs index b02d648..c7bedff 100644 --- a/src/DemaConsulting.SpdxTool/Commands/AddRelationship.cs +++ b/src/DemaConsulting.SpdxTool/Commands/AddRelationship.cs @@ -161,9 +161,13 @@ public static void Add(SpdxDocument doc, SpdxRelationship relationship) public static SpdxRelationship[] Parse( string command, string packageId, - YamlSequenceNode relationships, + YamlSequenceNode? relationships, Dictionary variables) { + // Handle no relationships + if (relationships == null) + return Array.Empty(); + // Parse each relationship return relationships.Children.Select(node => { diff --git a/src/DemaConsulting.SpdxTool/Commands/CopyPackage.cs b/src/DemaConsulting.SpdxTool/Commands/CopyPackage.cs index d5effeb..864f55a 100644 --- a/src/DemaConsulting.SpdxTool/Commands/CopyPackage.cs +++ b/src/DemaConsulting.SpdxTool/Commands/CopyPackage.cs @@ -36,7 +36,7 @@ public class CopyPackage : Command " to: # Destination SPDX file name", " package: # Package ID", " recursive: true # Optional recursive flag", - " relationships: # Relationships", + " relationships: # Optional relationships", " - type: # Relationship type", " element: # Related element", " comment: # Optional comment", @@ -109,8 +109,7 @@ public override void Run(YamlMappingNode step, Dictionary variab throw new YamlException(step.Start, step.End, "'copy-package' invalid 'recursive' input"); // Parse the relationships - var relationshipsSequence = GetMapSequence(inputs, "relationships") ?? - throw new YamlException(step.Start, step.End, "'copy-package' missing 'relationships' input"); + var relationshipsSequence = GetMapSequence(inputs, "relationships"); var relationships = AddRelationship.Parse("add-package", packageId, relationshipsSequence, variables); // Copy the package diff --git a/test/DemaConsulting.SpdxTool.Tests/TestAddPackage.cs b/test/DemaConsulting.SpdxTool.Tests/TestAddPackage.cs index f511472..4bb3bd8 100644 --- a/test/DemaConsulting.SpdxTool.Tests/TestAddPackage.cs +++ b/test/DemaConsulting.SpdxTool.Tests/TestAddPackage.cs @@ -109,6 +109,73 @@ public void AddPackageSimple() } } + [TestMethod] + public void AddPackageNoRelationship() + { + // SPDX contents + const string spdxContents = "{\r\n" + + " \"files\": [],\r\n" + + " \"packages\": [],\r\n" + + " \"relationships\": [],\r\n" + + " \"spdxVersion\": \"SPDX-2.2\",\r\n" + + " \"dataLicense\": \"CC0-1.0\",\r\n" + + " \"SPDXID\": \"SPDXRef-DOCUMENT\",\r\n" + + " \"name\": \"Test Document\",\r\n" + + " \"documentNamespace\": \"https://sbom.spdx.org\",\r\n" + + " \"creationInfo\": {\r\n" + + " \"created\": \"2021-10-01T00:00:00Z\",\r\n" + + " \"creators\": [ \"Person: Malcolm Nixon\" ]\r\n" + + " },\r\n" + + " \"documentDescribes\": []\r\n" + + "}"; + + // Workflow contents + const string workflowContents = "steps:\n" + + "- command: add-package\n" + + " inputs:\n" + + " spdx: spdx.json\n" + + " package:\n" + + " id: SPDXRef-Package-1\n" + + " name: Test Package 1\n" + + " version: 1.0.0\n" + + " download: https://dotnet.microsoft.com/download\n" + + " purl: pkg:nuget/BogusPackage@1.0.0\n"; + + try + { + // Write the SPDX files + File.WriteAllText("spdx.json", spdxContents); + File.WriteAllText("workflow.yaml", workflowContents); + + // Run the command + var exitCode = Runner.Run( + out _, + "dotnet", + "DemaConsulting.SpdxTool.dll", + "run-workflow", + "workflow.yaml"); + + // Verify success + Assert.AreEqual(0, exitCode); + + // Read the SPDX document + Assert.IsTrue(File.Exists("spdx.json")); + var doc = Spdx2JsonDeserializer.Deserialize(File.ReadAllText("spdx.json")); + + // Verify package present + Assert.AreEqual(1, doc.Packages.Length); + Assert.AreEqual("SPDXRef-Package-1", doc.Packages[0].Id); + + // Verify no relationships + Assert.AreEqual(0, doc.Relationships.Length); + } + finally + { + File.Delete("spdx.json"); + File.Delete("workflow.yaml"); + } + } + [TestMethod] public void AddPackageFromQuery() {