Skip to content

feat: add --create-pr flag to open GitHub PR after --fix#518

Merged
sonukapoor merged 9 commits into
OWASP:mainfrom
coder-Yash886:feature/issue-367-create-pr
Jun 5, 2026
Merged

feat: add --create-pr flag to open GitHub PR after --fix#518
sonukapoor merged 9 commits into
OWASP:mainfrom
coder-Yash886:feature/issue-367-create-pr

Conversation

@coder-Yash886

Copy link
Copy Markdown
Contributor

feat: add --create-pr flag to open GitHub PR after --fix

Closes #367

Summary

Apply OSV-validated direct fixes, commit lockfile changes, and open a structured PR via gh. Supports --base and respects --fail-on threshold.

What was added

File Purpose
src/utils/create-pr.ts Branch name, PR title/body, gh + git workflow
src/cli/args.ts --create-pr, --base <branch> flags
src/cli/validate.ts Requires --fix; blocks --json; --base only with --create-pr
src/cli/help.ts Help text
src/index.ts After --fix + rescan: optional PR if --fail-on threshold met
src/types.ts createPr, prBase fields
tests/create-pr.test.ts Unit tests
tests/cli-integration.test.ts --create-pr without --fix fails fast

Behaviour (cve-lite . --fix --create-pr)

  1. Scan → apply validated direct fixes → rescan
  2. Create PR only if initial findings meet --fail-on threshold
  3. Skip PR if no fixes applied or no git changes detected
  4. Branch: cve-lite/fix-YYYY-MM-DD
  5. Commit staged tracked changes (git add -u)
  6. Push to origin and run gh pr create --base main (or --base <branch>)
  7. PR body includes: fixed packages, versions, advisory IDs, before/after finding counts

Bug fixes in this PR

  • Fixed advisorySourceLine used-before-assignment TS error — initialized as let advisorySourceLine = ""
  • Fixed typeof writeHtmlReport reference error in test — replaced with inline type annotation
  • Fixed formatAdvisorySourceLine mock in cli-integration.test.ts

@coder-Yash886

Copy link
Copy Markdown
Contributor Author

@sonukapoor Please review the PR when you have free time

@sonukapoor sonukapoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Good work overall — clean separation into src/utils/create-pr.ts, good validation gates, and the helper functions are well-tested. A few things before this can land:

git add -u stages everything, not just CVE Lite's changes. This is the most important issue. If a developer has other unstaged work in their repo when they run cve-lite . --fix --create-pr, those unrelated changes would end up in the security PR. The stage step should be scoped to only the files CVE Lite modified — the package.json and lockfile(s) in the project directory. The simplest safe approach: stage only package.json, package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lock, and npm-shrinkwrap.json rather than all tracked changes.

No handling when the branch already exists. If a developer runs --fix --create-pr twice in the same day, git checkout -b cve-lite/fix-2026-06-02 will fail. Add a fallback — either a counter suffix (fix-2026-06-02-2) or a short hash.

Please rebase against main — the branch is behind v1.19.1.

Add Closes #367 to the PR body so the tracking issue auto-closes on merge.

I'll also be testing this end-to-end against a real project this week before it merges, so I may have additional feedback after that. Everything else looks solid — the gh auth check, the skip conditions, the PR body format, and the test coverage are all good.

@coder-Yash886 coder-Yash886 force-pushed the feature/issue-367-create-pr branch from 45077ed to 56609d8 Compare June 2, 2026 12:48
@coder-Yash886

Copy link
Copy Markdown
Contributor Author

@sonukapoor please review the PR when you have free time

@sonukapoor

Copy link
Copy Markdown
Collaborator

Thanks for the contribution! We will review and test this end-to-end against a real project this week. Happy contributing!

@sonukapoor sonukapoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Good progress — the two issues from the first review are both fixed. stageDependencyFilesOnly() is the right approach for targeted staging, and selectAvailableBranchName() handles the branch collision case cleanly.

Two new bugs to fix before this can land:

Closes #367 hardcoded in every generated PR body. This is the CVE Lite CLI feature request issue number, not a placeholder. Every user who runs --create-pr will generate a PR in their own repository with Closes #367 in the body — which will auto-close whatever issue #367 happens to be in their repo. Remove this line entirely from buildPullRequestBody() and update the test that asserts on it.

Wrong condition gates PR creation. In index.ts, the check findingsMeetFailOnThreshold(findingsBeforeFixList, options.failOn) controls whether a PR gets created. The --fail-on default is critical, so if a user has only high or medium findings and runs --fix --create-pr, no PR is created even if fixes were successfully applied. The condition should be whether fixes were actually applied (fixResult.appliedFixCount > 0), not whether findings crossed a severity threshold. Those are two independent concerns.

Also please rebase against main — the branch is still behind.

Once these are addressed this is ready to merge.

@coder-Yash886

Copy link
Copy Markdown
Contributor Author

@sonukapoor Please review the Pr when you have free time

@sonukapoor sonukapoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Good progress on the --create-pr implementation — the three issues from the last review are all addressed: targeted file staging, branch collision handling, and the correct appliedFixCount > 0 condition. The Closes #367 line is still missing from the generated PR body.

However the scope has expanded considerably and I need to raise two concerns before this can land:

New runtime dependency (yarn-lockfile). This PR adds yarn-lockfile@^1.1.0 to dependencies. CVE Lite CLI intentionally keeps its runtime footprint small — currently 4 packages. Adding a new one requires sign-off. Please raise this separately so we can evaluate it on its own merits.

Three features in one PR. The --create-pr flag, the Yarn transitive graph extension (createNpmLockGraphFromYarnLock), and the yarn-within-range fixture and tests are three independent changes that should each have their own PR. Mixing them makes it much harder to review and increases risk — a bug in the yarn graph logic could block the --create-pr flag from landing.

Please split into separate PRs: one for --create-pr, one for the yarn graph extension (once the yarn-lockfile dependency is approved), and the fixture belongs in its own PR scoped to issue #540.

@sonukapoor

Copy link
Copy Markdown
Collaborator

Adding more context on the scope concern from the review above: the createNpmLockGraphFromYarnLock function and scanner changes you added are actually the implementation for issue #421 (improve Yarn parser path reconstruction). That work is what makes PR #537 (yarn-within-range fixture) produce the expected yarn upgrade js-cookie command.

It would be really helpful if you could extract that piece — src/parsers/yarn-lock.ts graph function + the scanner changes that wire it in — into a standalone PR targeting #421. That way:

The yarn-lockfile dependency evaluation can also happen in that PR where it's clearly scoped.

@coder-Yash886 coder-Yash886 force-pushed the feature/issue-367-create-pr branch from 405b5c1 to 982ee1b Compare June 4, 2026 13:22
@coder-Yash886

Copy link
Copy Markdown
Contributor Author

@sonukapoor please review the PR

@sonukapoor

Copy link
Copy Markdown
Collaborator

Found a bug while testing against a real project. stageDependencyFilesOnly iterates over the full DEPENDENCY_FILES_TO_STAGE list and runs git add -- <file> for every entry — including files that don't exist in the project. When git add -- yarn.lock runs on an npm-only repo, git exits non-zero with fatal: pathspec 'yarn.lock' did not match any files and the function throws immediately.

Repro: Run --fix --create-pr on any project that only has package.json and package-lock.json.

Fix needed: Check whether each file exists before attempting to stage it, or catch the specific 'pathspec did not match' error and continue to the next file rather than throwing.

Check file existence before git add so npm-only repos do not fail on
missing yarn.lock, pnpm-lock.yaml, and other optional lockfiles.
@coder-Yash886

Copy link
Copy Markdown
Contributor Author

@sonukapoor Please review the Pr When you have free time

@sonukapoor sonukapoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Tested end to end against sonukapoor/cve-lite-test — the previous bug (stageDependencyFilesOnly failing when yarn.lock doesn't exist) is fixed with the existsSync check. The PR correctly staged only package.json and package-lock.json, created branch cve-lite/fix-2026-06-05, and generated a clean PR with the fix and advisory IDs. All previous concerns are addressed. Good to merge.

@sonukapoor

Copy link
Copy Markdown
Collaborator

One small improvement before merge — the generated PR title should include the package name(s) so it's immediately useful in a busy PR list.

Current: fix: resolve 1 vulnerable dependency

Proposed: [CVE-Lite-CLI] fix: upgrade lodash (1 vulnerability resolved)

For multiple packages it truncates gracefully: [CVE-Lite-CLI] fix: upgrade lodash, axios +2 more (4 vulnerabilities resolved)

Changes needed in src/utils/create-pr.ts:

export function buildPullRequestTitle(appliedCount: number, packageNames: string[]): string {
  const pkgList = packageNames.length <= 3
    ? packageNames.join(", ")
    : `${packageNames.slice(0, 2).join(", ")} +${packageNames.length - 2} more`;
  return `[CVE-Lite-CLI] fix: upgrade ${pkgList} (${appliedCount} ${pluralize(appliedCount, "vulnerability", "vulnerabilities")} resolved)`;
}

And update the call site to pass the package names:

const packageNames = params.fixResult.applied.map(a => a.package);
const title = buildPullRequestTitle(params.fixResult.appliedFixCount, packageNames);

Update the two title assertions in tests/create-pr.test.ts to match the new format. Once done please rebase against main and this is ready to merge.

@coder-Yash886

Copy link
Copy Markdown
Contributor Author

@sonukapoor Please review the PR when you have free time

@sonukapoor sonukapoor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Title format looks great — [CVE-Lite-CLI] fix: upgrade lodash (1 vulnerability resolved) is much more useful than the original. The truncation logic for 3+ packages and the test coverage are solid. The existsSync guard for missing lockfiles and the advisorySourceLine initialization fix are good catches too. Ready to merge.

@sonukapoor sonukapoor merged commit bf4b35a into OWASP:main Jun 5, 2026
6 checks passed
@sonukapoor

Copy link
Copy Markdown
Collaborator

Merged — thank you @coder-Yash886!

@coder-Yash886

coder-Yash886 commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@sonukapoor, thanks for the thorough reviews and for merging! Happy to contribute more. please review PR #537

@sonukapoor sonukapoor mentioned this pull request Jun 9, 2026
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.

feat: add --create-pr flag to open a GitHub PR with validated fix commands

2 participants