Skip to content

✨ feat: Refactor scorecard serve cmd #4665

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Fix3dP0int
Copy link

@Fix3dP0int Fix3dP0int commented Jun 17, 2025

What kind of change does this PR introduce?

feature

What is the current behavior?

The current serve uses Go’s built-in http package, which lacks modern features. And It fails to correctly aggregate the total score, and parameters and details cannot be retrieved properly.

What is the new behavior (if this is a feature change)?**

This PR refactors the serve component by migrating the original CLI-based parameter input to a RESTful API interface. Additionally, I replaced the native net/http logic with the chi router, which is lightweight yet expressive and well-suited for modular HTTP services in Go.

  • Tests for the changes have been added (for bug fixes/features)

Which issue(s) this PR fixes

Related to #4627

@Fix3dP0int Fix3dP0int changed the title ✨ feat: Refactor scorecard serve cmd (#4627) ✨ feat: Refactor scorecard serve cmd Jun 17, 2025
@spencerschrock
Copy link
Member

Don't have time to look in-depth, but wanted to make one comment:

The current serve uses Go’s built-in http package, which lacks modern features

What features specifically? Go 1.22 made good strides at least for the routing
https://go.dev/blog/routing-enhancements

@Fix3dP0int
Copy link
Author

Sorry. I'm unfamiliar with new features of Go. It seems that chi isn't necessary. I will revert it. Thx.

Signed-off-by: fixedpoint <961750412@qq.com>
@Fix3dP0int Fix3dP0int marked this pull request as ready for review June 22, 2025 16:45
@Fix3dP0int Fix3dP0int requested a review from a team as a code owner June 22, 2025 16:45
@Fix3dP0int Fix3dP0int requested review from spencerschrock and raghavkaul and removed request for a team June 22, 2025 16:45
Copy link
Member

@spencerschrock spencerschrock left a comment

Choose a reason for hiding this comment

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

At a high level this looks like what we want, an http wrapper around the CLI. You said MCP will be built on top of this API, so is it matching what you need for that?

There are a few things that need changed, which I've left individual comments on. The linter also has some thoughts with this file.

Comment on lines +63 to +64
PolicyFile string `json:"policy_file,omitempty"`
}
Copy link
Member

Choose a reason for hiding this comment

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

In the CLI, policy file is a local file. How do we expect to pass a policy file to a server, with a URI?

Comment on lines +75 to +79
if r.Method == http.MethodPost {
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, "invalid request body", http.StatusBadRequest)
return
}
Copy link
Member

Choose a reason for hiding this comment

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

what is the goal of having POST? Passing parameters as JSON instead of as query parameters?

Comment on lines +115 to +116
if s.opts.LogLevel == "" {
s.opts.LogLevel = "info"
Copy link
Member

Choose a reason for hiding this comment

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

log.InfoLevel is a constant with this value.

Comment on lines +97 to +101
// Set options
s.opts.Repo = req.Repo
s.opts.Local = req.Local
s.opts.NPM = req.NPM
s.opts.PyPI = req.PyPI
Copy link
Member

Choose a reason for hiding this comment

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

Right now we have one options.Options, which is passed in serveCmd, and then this one copy is modified for each request. This seems like a race condition.

we should create a new struct for each request. either through options.New, or manually if we want to avoid the env var parsing.

Comment on lines +121 to +124
} else if s.opts.FileMode != options.FileModeArchive && s.opts.FileMode != options.FileModeGit {
http.Error(w, fmt.Sprintf("unsupported file mode: %s", s.opts.FileMode), http.StatusBadRequest)
return
}
Copy link
Member

Choose a reason for hiding this comment

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

this validation is already covered by the s.opts.Validate call below

Comment on lines +154 to +159
if s.opts.Local != "" {
repo, err = localdir.MakeLocalDirRepo(s.opts.Local)
if err != nil {
http.Error(w, fmt.Sprintf("making local dir: %v", err), http.StatusInternalServerError)
return
}
Copy link
Member

Choose a reason for hiding this comment

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

do we expect people to pass the serve command repos which are local to the server?

Comment on lines +183 to +184
enabledChecks, err := policy.GetEnabled(pol, s.opts.Checks(), requiredRequestTypes)
stdlog.Printf("DEBUG: enabledChecks = %#v", enabledChecks)
Copy link
Member

Choose a reason for hiding this comment

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

should this be removed? was this for your testing?

Comment on lines +227 to +228
Details: s.opts.ShowDetails,
Annotations: false,
Copy link
Member

Choose a reason for hiding this comment

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

we would probably want ShowAnnotations as a query parameter.

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
stdlog.Printf("%s %s %s", r.Method, r.URL, time.Since(start))

Check failure

Code scanning / CodeQL

Log entries created from user input High

This log entry depends on a
user-provided value
.
Copy link

codecov bot commented Jun 24, 2025

Codecov Report

Attention: Patch coverage is 0% with 211 lines in your changes missing coverage. Please review.

Project coverage is 67.71%. Comparing base (353ed60) to head (3060b2a).
Report is 184 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4665      +/-   ##
==========================================
+ Coverage   66.80%   67.71%   +0.91%     
==========================================
  Files         230      249      +19     
  Lines       16602    19044    +2442     
==========================================
+ Hits        11091    12896    +1805     
- Misses       4808     5289     +481     
- Partials      703      859     +156     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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

Successfully merging this pull request may close these issues.

2 participants