-
Notifications
You must be signed in to change notification settings - Fork 27
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
yarn: SBOM components #739
base: main
Are you sure you want to change the base?
Changes from all commits
f26e1ea
3d7a3db
dd61c68
4941272
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,11 @@ | |
from typing import Iterable, Optional, Union | ||
from urllib.parse import urlparse | ||
|
||
from packageurl import PackageURL | ||
from pyarn.lockfile import Package as PYarnPackage | ||
from pydantic import BaseModel | ||
|
||
from cachi2.core.checksum import ChecksumInfo | ||
from cachi2.core.errors import PackageRejected, UnexpectedFormat | ||
from cachi2.core.package_managers.npm import NPM_REGISTRY_CNAMES | ||
from cachi2.core.package_managers.yarn_classic.project import PackageJson, Project, YarnLock | ||
|
@@ -15,6 +17,7 @@ | |
extract_workspace_metadata, | ||
) | ||
from cachi2.core.rooted_path import RootedPath | ||
from cachi2.core.scm import RepoID | ||
|
||
# https://github.com/yarnpkg/yarn/blob/7cafa512a777048ce0b666080a24e80aae3d66a9/src/resolvers/exotics/git-resolver.js#L15-L17 | ||
GIT_HOSTS = frozenset(("github.com", "gitlab.com", "bitbucket.com", "bitbucket.org")) | ||
|
@@ -26,6 +29,9 @@ | |
re.compile(r"^https?:.+\.git#.+"), | ||
) | ||
|
||
DEFAULT_NPM_REGISTRY = "https://registry.npmjs.org" | ||
ALTERNATIVE_NPM_REGISTRY = "https://registry.yarnpkg.com" | ||
|
||
|
||
class _BasePackage(BaseModel): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we make this inherit from ABC and have |
||
"""A base Yarn 1.x package.""" | ||
|
@@ -47,26 +53,99 @@ class _RelpathMixin(BaseModel): | |
class RegistryPackage(_BasePackage, _UrlMixin): | ||
"""A Yarn 1.x package from the registry.""" | ||
|
||
@property | ||
def purl(self) -> str: | ||
"""Return package URL.""" | ||
qualifiers = {} | ||
|
||
if self.url != DEFAULT_NPM_REGISTRY: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that self.url can be anything? If not then could it be constrained to a union of literals? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do have a check for that: IOW, if a package is |
||
qualifiers = {"repository_url": ALTERNATIVE_NPM_REGISTRY} | ||
|
||
if self.integrity: | ||
checksum = ChecksumInfo.from_sri(self.integrity) | ||
qualifiers["checksum"] = str(checksum) | ||
|
||
return PackageURL( | ||
type="npm", | ||
name=self.name, | ||
version=self.version, | ||
qualifiers=qualifiers, | ||
).to_string() | ||
|
||
|
||
class GitPackage(_BasePackage, _UrlMixin): | ||
"""A Yarn 1.x package from a git repo.""" | ||
|
||
@property | ||
def purl(self) -> str: | ||
"""Return package URL.""" | ||
parsed_url = urlparse(self.url) | ||
repo_id = RepoID(origin_url=self.url, commit_id=parsed_url.fragment) | ||
qualifiers = {"vcs_url": repo_id.as_vcs_url_qualifier()} | ||
return PackageURL( | ||
type="npm", | ||
name=self.name, | ||
version=self.version, | ||
qualifiers=qualifiers, | ||
).to_string() | ||
|
||
|
||
class UrlPackage(_BasePackage, _UrlMixin): | ||
"""A Yarn 1.x package from a http/https URL.""" | ||
|
||
@property | ||
def purl(self) -> str: | ||
"""Return package URL.""" | ||
qualifiers = {"download_url": self.url} | ||
return PackageURL( | ||
type="npm", | ||
name=self.name, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For some of the non-registry packages, we may want to read their respective package.json files from the cached tarballs to get their true names. As a user, I can call these non-registry dependencies whatever I want in my project's package.json and it could be completely different from what it really is:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does the filename in the cache come from package.json or the URL ? |
||
version=self.version, | ||
qualifiers=qualifiers, | ||
).to_string() | ||
|
||
|
||
class FilePackage(_BasePackage, _RelpathMixin): | ||
"""A Yarn 1.x package from a local file path.""" | ||
|
||
@property | ||
def purl(self) -> str: | ||
"""Return package URL.""" | ||
return PackageURL( | ||
type="npm", | ||
name=self.name, | ||
version=self.version, | ||
subpath=str(self.relpath), | ||
).to_string() | ||
|
||
|
||
class WorkspacePackage(_BasePackage, _RelpathMixin): | ||
"""A Yarn 1.x local workspace package.""" | ||
|
||
@property | ||
def purl(self) -> str: | ||
"""Return package URL.""" | ||
return PackageURL( | ||
type="npm", | ||
name=self.name, | ||
version=self.version, | ||
subpath=str(self.relpath), | ||
).to_string() | ||
|
||
|
||
class LinkPackage(_BasePackage, _RelpathMixin): | ||
"""A Yarn 1.x local link package.""" | ||
|
||
@property | ||
def purl(self) -> str: | ||
"""Return package URL.""" | ||
return PackageURL( | ||
type="npm", | ||
name=self.name, | ||
version=self.version, | ||
subpath=str(self.relpath), | ||
).to_string() | ||
|
||
|
||
YarnClassicPackage = Union[ | ||
FilePackage, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor naming nitpick: it creates multiple components, so better be named
_create_sbom_components
. The docstring seems to agree with me on this one.Another controversial naming scheme to consider is this:
_sbom_components_created_from
.Then in the invocation spot you'll have:
which is mostly a regular English sentence (except for weird punctuation).
I am absolutely not insisting on the second one, it is just a readability idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be
_create_sbom_components
(probably just a typo).