-
Notifications
You must be signed in to change notification settings - Fork 63
Ruby dependency license scanning support via Gemfile.lock. #205
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
Conversation
- Implements apache/skywalking#7744 - Library projects (with a *.gemspec in the same directory as Gemfile.lock) ignore development dependencies and include runtime dependencies and their transitives. - App projects (no *.gemspec) include both runtime and development dependencies from Gemfile.lock. - Will only work if Gemfile.lock is committed to version control, but this is the official recommendation of RubyGems: - https://bundler.io/guides/faq.html#using-gemfiles-inside-gems - License resolution honors user overrides/exclusions and may query the RubyGems API when necessary, with proper support for handling of various status codes. - Documentation updated (README.md) - Ruby setup and GitHub Actions example are in <details> tag to reduce noise
- Error: pkg/deps/ruby.go:289:15: httpNoBody: http.NoBody should be preferred to the nil request body (gocritic req, err := http.NewRequest(http.MethodGet, url, nil)
- Error: pkg/deps/ruby.go:284:1: cyclomatic complexity 24 of func `fetchRubyGemsLicenseFrom` is high (> 20) (gocyclo)
func fetchRubyGemsLicenseFrom(url string) (string, error) {
^
|
Thank you @pboling ! Looks like some files are missing license header themselves, causing the CI to fail. Can you add license headers to the newly added files ? |
|
@kezhenxu94 Only one additional file in this PR was able to have a license header. .lock files do not have a format that allows license headers. I'm not sure if the remaining files need to be configured as excluded. |
|
If the header is not allowed, please add them to exclude list. Otherwise, CI will fail still. |
- Error: pkg/deps/ruby.go:341:1: unnamedResult: consider giving a name to these results (gocritic)
func handleRubyGemsResponse(resp *http.Response) (string, time.Duration, bool, error) {
|
I think it is done @wu-sheng @kezhenxu94 |
| url := fmt.Sprintf("https://rubygems.org/api/v2/rubygems/%s/versions/%s.json", name, version) | ||
| licenseID, err := fetchRubyGemsLicenseFrom(url) | ||
| if err == nil && licenseID != "" { | ||
| return licenseID, nil | ||
| } | ||
| // Fallback to latest info | ||
| url = fmt.Sprintf("https://rubygems.org/api/v1/gems/%s.json", name) |
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.
Does gem package manager downloads the files to a local location like other package manager, if so we can read from the local file system.
Also, do we need to change the url to the one set in the Gemfile.lock? If users want to use they own registry?
remote: https://rubygems.org/
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.
Does gem package manager downloads the files to a local location like other package manager, if so we can read from the local file system.
Yes, if the GHA workflow is setup with Ruby, and runs the bundle install to install all the dependencies. We could check them that way in most scenarios, but:
- On some systems the gem package is split when it is installed, e.g., the gemspec may not exist at the project root, and with relevance to this use case, the split would make the installed dependencies more difficult to parse/walk through than the project's raw Gemfile.lock.
- Downloading entire dependency packages, and doing the complete version solving routine, which requires downloading the entire gem index, may actually be significantly heavier load than API calls for each dependency.
- This would also require that the project be in a good working state. Parsing agnostically like this doesn't require the project to be in any kind of serviceable state.
Also, do we need to change the url to the one set in the Gemfile.lock? If users want to use they own registry?
It is possible that they can use other registries... but
- if they do, they are usually private
- accessing private ones is far more complex
- often involves an API token set in the ENV
- which should never be in version control, and has no uniform naming scheme
- these are edge cases
- I would suggest that support for them be handled in further PRs by people who need that functionality (big corps can pay for things they need to use!)
So, https://rubygems.org is the canonical default, and we could read it from the Gemfile, but it is a lot of complexity for a tiny fraction of users who are not paying me anything.
I'm just trying to provide better than 80/20 functionality for the "rest of us", the open source maintainers.
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.
@kezhenxu94 does that resolve the concern? Do you need more details?
|
Thanks @pboling |
|
@kezhenxu94 @wu-sheng @CodePrometheus I've tried setting this up, against main, in the oauth2 repo: I don't understand the output. There basically isn't any, and perhaps it exits with success because it hasn't found any dependency to check? And that's it. It exits successfully. The problem is, this library does have runtime dependencies that should have been found. I did initially have debugging / logging code in the PR, but it was flagged by the linter / compiler as bad, so I removed it. What would be an ideal approach to debugging this? My preference would be that it die hard/loud on a failure to parse. Another strange bit is in the Post Check there is a warning about a primary key not being generated: This is my first time doing anything with Go on GHA. |
|
@pboling looking into your PR, I found that the |
|
@kezhenxu94 Yes, I'm seeing that failure now. It should handle that gracefully, right? |
Yes, depends on how we want to deal with the dependencies that are missing version/license info, typically we will add it to the list of unknown, so users can check it manually, and set it in the |
|
@pboling can you open a PR to address that? |
|
My last comment wasn't clear - what I mean is I think the error should be trapped, and it should track the list of dependencies with missing licenses, and if the list of missing licenses, or incompatible licenses is non-empty, it should fail. However, thinking about this a bit more - the |
|
@kezhenxu94 First fix: #207 |
|
Second fix #208 |
Uh oh!
There was an error while loading. Please reload this page.