Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API changes to support SPDX 3.0 #924

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

Conversation

pragnya17
Copy link
Contributor

  1. Update the validation/parsing and generation workflows to reflect the different SPDX 3.0 defined entities.
  2. Add a cmd line parameter for different compliance standards. For example, parse SbomFileExample.txt -complianceStandard NTIA
  3. Make sure there are no duplicate spdx elements
  4. Unit testing command line API changes, workflows, utility methods

@pragnya17 pragnya17 requested a review from a team as a code owner February 7, 2025 18:54
Copy link

github-actions bot commented Feb 7, 2025

This PR changes files in the API project. Does it change any of the API interfaces in any way? Please note that this includes the following types of changes:

  • Changing the signature of an existing interface method
  • Adding a new method to an existing interface
  • Adding a required data member to a class that an existing interface method consumes

Because any of these changes can potentially break a downstream consumer with customized interface implementations, these changes need to be treated as breaking changes. Please do one of the following:

Option 1 - Publish this as a breaking change

  1. Update the documentation to show the new functionality
  2. Bump the major version in the next release
  3. Be sure to highlight the breaking changes in the release notes

Option 2 - Refactor the changes to be non-breaking

  1. Review this commit, which adds a new interface in a backward-compatible way
  2. Refactor the change to follow this pattern so that existing interfaces are left completely intact
  3. Bump the minor version in the next release

Copy link

github-actions bot commented Feb 7, 2025

This PR changes files in the API project. Does it change any of the API interfaces in any way? Please note that this includes the following types of changes:

  • Changing the signature of an existing interface method
  • Adding a new method to an existing interface
  • Adding a required data member to a class that an existing interface method consumes

Because any of these changes can potentially break a downstream consumer with customized interface implementations, these changes need to be treated as breaking changes. Please do one of the following:

Option 1 - Publish this as a breaking change

  1. Update the documentation to show the new functionality
  2. Bump the major version in the next release
  3. Be sure to highlight the breaking changes in the release notes

Option 2 - Refactor the changes to be non-breaking

  1. Review this commit, which adds a new interface in a backward-compatible way
  2. Refactor the change to follow this pattern so that existing interfaces are left completely intact
  3. Bump the minor version in the next release

Copy link

github-actions bot commented Feb 7, 2025

This PR changes files in the API project. Does it change any of the API interfaces in any way? Please note that this includes the following types of changes:

  • Changing the signature of an existing interface method
  • Adding a new method to an existing interface
  • Adding a required data member to a class that an existing interface method consumes

Because any of these changes can potentially break a downstream consumer with customized interface implementations, these changes need to be treated as breaking changes. Please do one of the following:

Option 1 - Publish this as a breaking change

  1. Update the documentation to show the new functionality
  2. Bump the major version in the next release
  3. Be sure to highlight the breaking changes in the release notes

Option 2 - Refactor the changes to be non-breaking

  1. Review this commit, which adds a new interface in a backward-compatible way
  2. Refactor the change to follow this pattern so that existing interfaces are left completely intact
  3. Bump the minor version in the next release

Copy link

github-actions bot commented Feb 7, 2025

This PR changes files in the API project. Does it change any of the API interfaces in any way? Please note that this includes the following types of changes:

  • Changing the signature of an existing interface method
  • Adding a new method to an existing interface
  • Adding a required data member to a class that an existing interface method consumes

Because any of these changes can potentially break a downstream consumer with customized interface implementations, these changes need to be treated as breaking changes. Please do one of the following:

Option 1 - Publish this as a breaking change

  1. Update the documentation to show the new functionality
  2. Bump the major version in the next release
  3. Be sure to highlight the breaking changes in the release notes

Option 2 - Refactor the changes to be non-breaking

  1. Review this commit, which adds a new interface in a backward-compatible way
  2. Refactor the change to follow this pattern so that existing interfaces are left completely intact
  3. Bump the minor version in the next release

var directory = Path.GetDirectoryName(spdxSbomConfig.ManifestJsonFilePath);
directory = fileSystemUtils.GetFullPath(directory);
if (!string.IsNullOrEmpty(directory))
if (sbomConfigs.TryGet(supportedSpdxManifest, out var spdxSbomConfig))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably we can only match 1 config--should we break out of the loop after the first match?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure if the customer was allowed to pass in multiple manifests. Seems like the conclusion is that there is only matching manifest based on your comment and what I've seen in the rest of the code, so I'll add a break statement after a successful match


namespace Microsoft.Sbom.Api.Workflows.Helpers;

public interface IJsonSerializationStrategy
Copy link
Contributor

@DaveTryon DaveTryon Feb 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not seeing this interface in any test classes. Is that a gap we should address?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is tested in the workflow tests where there are UTs to switch to different serialization strategies based on the manifest version. So I don't think that there's necessarily a gap here.

private readonly IEnumerable<ISourcesProvider> sourcesProviders;

private readonly IRecorder recorder;

public ISbomConfig SbomConfig { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can SbomConfig and SpdxManifestVersion be set more than once? Not for this PR, but a small follow-up PR could easily add a class that makes these write-once

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No they should only be write-once, I will create a work item to make sure this change gets taken up in a separate PR.

}

public IEnumerable<string> Contexts => ((IEnumerable<string>)this.Result!).Select(r => r);
public IEnumerable<object> Contexts { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

object can literally be anything. Is there a way to improve the type safety?

@@ -187,7 +187,11 @@ private class PinnedIFileTypeUtils : IFileTypeUtils

private class PinnedIJsonArrayGenerator : IJsonArrayGenerator<PinnedIJsonArrayGenerator>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With these changes, we are intentionally doing away with the Version 3 interface, so this file should be in a different folder--calling it Version_4_0 would be consistent with the previous naming

@pragnya17
Copy link
Contributor Author

/azp run

/// <exception cref="ParserException"></exception>
public void ValidateSbomDocCreationForNTIA(List<Element> elementsList)
{
var spdxDocumentElements = elementsList.Where(element => element is SpdxDocument);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where returns an IEnumerable, which has some benefits, but the first thing that happens is to call Count(), which walks the entire list. Would the code to simpler if you made spdxDocumentElements a List by appending .ToList() on line 339?


metadata.SpdxVersion = spdxCreationInfoElement?.SpecVersion;

return metadata;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can set multiple properties of SpdxMetadata to null, when they're not declared as nullable in SpdxMetadata. .NET 8.0 assumes non-nullable types unless we explicitly tell it otherwise

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If result has null values then SpdxMetadata should also have those values set to null, so this is intentional

@@ -100,4 +102,25 @@ public async Task When_GenerateSbomAsync_WithNoRecordedErrors_Then_EmptyEntityEr
mockRecorder.Verify();
mockWorkflow.Verify();
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code coverage for the generator hits most of the happy paths, but leaves a lot of error cases untouched. Should we try to cover more of the error paths?

@@ -379,4 +464,143 @@ public async Task SbomParserBasedValidationWorkflowTests_ReturnsSuccessAndValida
fileSystemMock.VerifyAll();
osUtilsMock.VerifyAll();
}

[TestMethod]
public async Task SbomParserBasedValidationWorkflowTests_SetsComplianceStandard_Succeeds()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code smell: If we need to have > 100 lines of code to run a 2 line test, we probably have some fundamental problems with our interface story

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I am setting the compliance standard in the workflow (when the parser gets created), all of these mocks are created in order to run the workflow which will set the compliance standard that I am asserting for.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I can create a work item to take this issue up in a separate PR? I think it would involve some extensive rewriting of interfaces

Copy link

This PR changes files in the API project. Does it change any of the API interfaces in any way? Please note that this includes the following types of changes:

  • Changing the signature of an existing interface method
  • Adding a new method to an existing interface
  • Adding a required data member to a class that an existing interface method consumes

Because any of these changes can potentially break a downstream consumer with customized interface implementations, these changes need to be treated as breaking changes. Please do one of the following:

Option 1 - Publish this as a breaking change

  1. Update the documentation to show the new functionality
  2. Bump the major version in the next release
  3. Be sure to highlight the breaking changes in the release notes

Option 2 - Refactor the changes to be non-breaking

  1. Review this commit, which adds a new interface in a backward-compatible way
  2. Refactor the change to follow this pattern so that existing interfaces are left completely intact
  3. Bump the minor version in the next release

@pragnya17
Copy link
Contributor Author

/azp run

Copy link

This PR changes files in the API project. Does it change any of the API interfaces in any way? Please note that this includes the following types of changes:

  • Changing the signature of an existing interface method
  • Adding a new method to an existing interface
  • Adding a required data member to a class that an existing interface method consumes

Because any of these changes can potentially break a downstream consumer with customized interface implementations, these changes need to be treated as breaking changes. Please do one of the following:

Option 1 - Publish this as a breaking change

  1. Update the documentation to show the new functionality
  2. Bump the major version in the next release
  3. Be sure to highlight the breaking changes in the release notes

Option 2 - Refactor the changes to be non-breaking

  1. Review this commit, which adds a new interface in a backward-compatible way
  2. Refactor the change to follow this pattern so that existing interfaces are left completely intact
  3. Bump the minor version in the next release

@pragnya17
Copy link
Contributor Author

/azp run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants