-
Notifications
You must be signed in to change notification settings - Fork 29
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
Adding SBOM components and integration tests #831
base: main
Are you sure you want to change the base?
Conversation
ead6a4b
to
1564e0e
Compare
mk_purl = lambda n, v: PackageURL(type="cargo", name=n, version=v).to_string() # noqa: E731 | ||
mk_comp = lambda n, v: Component(name=n, version=v, purl=mk_purl(n, v)) # noqa: E731 | ||
components = [mk_comp(n, v) for n, v in name_versions] |
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.
I know the PURL spec is extremely vague, but I am missing here the qualifiers and a subpath that we use in other package managers' backends and some differentiation among various dependency types that are mentioned in the design doc...
Plus, the information about dev package managers, but that could done separately.
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.
We could add source=registry+https://github.com/...
qualifier here which would let us differentiate between oure git dependencies and registry dependencies. IIRC we should not see any other in the wild. I think I'll try parsing the lock file after all. Could you please elaborate on "the information about dev package managers"?
pytest.param( | ||
utils.TestParameters( | ||
branch="cargo/mixed-git-crate-dependency", | ||
packages=({"path": ".", "type": "cargo"},), | ||
flags=["--dev-package-managers"], | ||
check_output=False, | ||
check_deps_checksums=False, | ||
check_vendor_checksums=False, | ||
expected_exit_code=0, | ||
expected_output="", | ||
), | ||
id="mixed_git_crate_dependency", |
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.
This is a duplicate test already present as e2e
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.
I'd rather kept it to make spotting failures easier: if this one passes and e2e fails then we would instantly know that fetch is fine.
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.
I guess this is the same topic as discussed in #832 (comment).
BTW I removed duplicate tests for bundler in #783..
test_e2e_x is a basically superset of test_x_packages, it adds utils.build_image_and_check_cmd
.
In total, there are only two function calls, so I don't see any big investigation here after a failed test.
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.
50% reduction of potentially problematic are at a glance is quite a feat, I'd say :)
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.
What's the problem here? If the function that prefetches dependencies fails, we know that the prefetching of dependencies has failed; similarly, if the building image fails, we know that the building image has failed.
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.
Do you suggest dropping all three ITs in favor of the unified e2e?
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.
Yes. But it should be a collective decision :)
tests/integration/test_data/cargo_mixed_dep/container/Containerfile
Outdated
Show resolved
Hide resolved
pytest.param( | ||
utils.TestParameters( | ||
branch="cargo/just-a-crate-dependency", | ||
packages=({"path": ".", "type": "cargo"},), | ||
flags=["--dev-package-managers"], | ||
check_output=False, | ||
check_deps_checksums=False, | ||
check_vendor_checksums=False, | ||
expected_exit_code=0, | ||
expected_output="", | ||
), | ||
id="just_a_crate_dependency", | ||
), | ||
pytest.param( | ||
utils.TestParameters( | ||
branch="cargo/just-a-git-dependency", | ||
packages=({"path": ".", "type": "cargo"},), | ||
flags=["--dev-package-managers"], | ||
check_output=False, | ||
check_deps_checksums=False, | ||
check_vendor_checksums=False, | ||
expected_exit_code=0, | ||
expected_output="", | ||
), | ||
id="just_a_git_dependency", |
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.
I think we could merge these test cases IMO to a more complex one. Having a git dependency and crate dependency together is a common scenario IMO. I would maybe add a negative scenario instead, for example missing Cargo.lock etc.
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.
When things go wrong in a complex scenario one would need to invest more time into figuring out which part caused the issue. Having separate tests helps in making sure that individual types work fine. I thought about negative tests like missing lock file or project config, but could not come up with a realistic scenario in which that could happen. Hermeto will be used for building public projects with at least some following and likely some CI. These projects will be collected by a tool which is extremely unlikely to loose a file. In the extremely unlikely case of one of the files missing cargo itself would exit with a very non-zero exit code and would pull everything down with it which is a good thing -- we'll have this behavior logged and users would know that something is very wrong with their repository. It does feel a bit like testing thin wrappers around stdlib functions just in case. I might be wrong in my analysis so please correct me if I missed something.
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.
When things go wrong in a complex scenario one would need to invest more time into figuring out which part caused the issue. Having separate tests helps in making sure that individual types work fine.
Depends, these tests are fairly cheap compared to e2e, but then if e2e is a superset, then I also don't see that much value in individual positive tests, because positive cases should be covered in an e2e. Testing negative scenarios individually is a different story.
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.
We have an older IT, which is now a public archive, created by @brunoapimentel - https://github.com/cachito-testing/cachi2-rust.
I always thought about e2e tests to be more or less real-world projects with many dependencies. Personally, I don't like the idea of having simple tests just to have less work to do when something fails.
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.
The point of having simple tests is the same as for having well organized code -- to compartmentalize behavior in manageable components. I can easily buy the argument for having more tests, some of which could be quite complex, but I still think that having simpler tests increases precision.
@@ -0,0 +1,9 @@ | |||
FROM docker.io/rust:1.67 |
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.
The current stable version is 1.84. Have we freezed our implementation at a given release? Please refresh my memory because I don't remember.
In any case, these Dockerfiles are not checked by dependabot which means that we might be stuck at this particular version of rust for a very long time until someone notices. That said, latest
isn't an option because with a potential release 2.0 it might instantly break our tests. I think with rust releases the same logic applies as with go - major version guarantees backwards compatibility (https://rust-for-linux.com/unstable-features) so I'd prefer rust:1
instead. And since these are mostly trivial Dockerfiles, ultimately (it's on my todo list) we should convert all of these (whichever can!) to alpine, so in this case rust:1-alpine
please.
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.
Actually we don't even need to wait until 2.0 to get things broken: 1.84 generates lock file v4 while 1.67 generates v3. The remnants of my experiments with versions could be seen below (sed
update). Thank you for the hint, I'll switch to rust:1-alpine
.
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.
Hold on, I'm getting confused now.
1.84 generates lock file v4 while 1.67 generates v3.
What does ^this mean for us? Are we entering a yarn-like territory with these versions or are we completely unaffected by different lockfile versions? Can you elaborate some more please?
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.
v4 could be incompatible with v3 and older versions of cargo would refuse dealing with lock files generated by newer ones.
1063b9f
to
e42c386
Compare
The new revision has components generation unified with a dedicated dataclass, package qualifiers are added to purls, Containerfile is switched to a different base image. |
pytest.param( | ||
utils.TestParameters( | ||
branch="cargo/just-a-crate-dependency", | ||
packages=({"path": ".", "type": "cargo"},), | ||
flags=["--dev-package-managers"], | ||
check_output=False, | ||
check_deps_checksums=False, | ||
check_vendor_checksums=False, | ||
expected_exit_code=0, | ||
expected_output="", | ||
), | ||
id="just_a_crate_dependency", | ||
), | ||
pytest.param( | ||
utils.TestParameters( | ||
branch="cargo/just-a-git-dependency", | ||
packages=({"path": ".", "type": "cargo"},), | ||
flags=["--dev-package-managers"], | ||
check_output=False, | ||
check_deps_checksums=False, | ||
check_vendor_checksums=False, | ||
expected_exit_code=0, | ||
expected_output="", | ||
), | ||
id="just_a_git_dependency", |
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.
When things go wrong in a complex scenario one would need to invest more time into figuring out which part caused the issue. Having separate tests helps in making sure that individual types work fine.
Depends, these tests are fairly cheap compared to e2e, but then if e2e is a superset, then I also don't see that much value in individual positive tests, because positive cases should be covered in an e2e. Testing negative scenarios individually is a different story.
@@ -0,0 +1,9 @@ | |||
FROM docker.io/rust:1.67 |
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.
Hold on, I'm getting confused now.
1.84 generates lock file v4 while 1.67 generates v3.
What does ^this mean for us? Are we entering a yarn-like territory with these versions or are we completely unaffected by different lockfile versions? Can you elaborate some more please?
46a07e2
to
d0f903e
Compare
This change makes Cargo package manager generate components to populate resulting SBOM. Signed-off-by: Alexey Ovchinnikov <[email protected]>
Previously only crates.io was replaced with vendored directory. This does not work with git-based projects. This change fetches cargo-provided config and updates it to make it relocatable. This commit also removes tests for creation of .cargo/config.toml and corresponding code: it should not be created at this moment, the config will be injected later by inject-files command basing on generated template. Signed-off-by: Alexey Ovchinnikov <[email protected]>
This commit introduces integration tests for cargo and an e2e test. Signed-off-by: Alexey Ovchinnikov <[email protected]>
d0f903e
to
3dc587c
Compare
This change adds SBOM components generation and integration tests to finalize Cargo support implementation. It also fixes a problem of missing git dependencies substitution: git dependencies have to be explicitly replaced with a local copy. This change deals with this by collecting cargo output which is one substitution away from a correct config file template.
Maintainers will complete the following section
Note: if the contribution is external (not from an organization member), the CI
pipeline will not run automatically. After verifying that the CI is safe to run:
/ok-to-test
(as is the standard for Pipelines as Code)