Skip to content

feat: langmgr and python #1091

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

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from

Conversation

sozercan
Copy link
Member

@sozercan sozercan commented Jun 4, 2025

Signed-off-by: Sertac Ozercan [email protected]
Part of #147

Hold merge after current release

Describe the changes in this pull request using active verbs such as Add, Remove, Replace ...

Adds experimental app-level patching support with Python language manager

This PR introduces scaffolding for experimental support for patching application-level dependencies (libraries/packages) in addition to OS packages, with initial Python support.

Key Features

🔬 Experimental Feature

  • Requires COPA_EXPERIMENTAL=1 environment variable
  • Subject to breaking changes in future releases

📦 Package Type Filtering

  • New --pkg-types flag with values: os, library, os,library
  • Defaults to os (maintains backward compatibility)
  • Enables separate patching policies for OS vs application dependencies

🎯 Patch Level Control

  • New --library-patch-level flag with values: patch, minor, major
  • Defaults to patch for conservative updates
  • Implements preference ordering: patch > minor > major for safest upgrades

🐍 Python Support

  • Support for pip-managed Python packages. Other package managers are not considered for this initial PR.
  • Special handling for certifi (always latest version)

Example Usage

export COPA_EXPERIMENTAL=1
export IMAGE=mcr.microsoft.com/azure-cli:2.50.0 

# Scan for package vulnerabilities
trivy image --vuln-type os,library --ignore-unfixed -f json -o scan.json $IMAGE

# Patch only libraries with patch level updates only
copa patch -i $IMAGE -r scan.json --pkg-types library --library-patch-level patch

# Mixed OS and library patching with major level updates allowed
copa patch -i $IMAGE -r scan.json --pkg-types os,library --library-patch-level major

sozercan added 14 commits June 3, 2025 23:03
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Copy link

codecov bot commented Jun 5, 2025

Codecov Report

❌ Patch coverage is 57.05882% with 365 lines in your changes missing coverage. Please review.
✅ Project coverage is 45.40%. Comparing base (fb6b525) to head (c68a564).

Files with missing lines Patch % Lines
pkg/langmgr/python.go 54.38% 116 Missing and 14 partials ⚠️
pkg/patch/core.go 0.00% 62 Missing ⚠️
pkg/report/trivy.go 77.43% 44 Missing and 14 partials ⚠️
pkg/patch/cmd.go 16.07% 45 Missing and 2 partials ⚠️
pkg/patch/single.go 40.00% 35 Missing and 1 partial ⚠️
pkg/langmgr/langmgr.go 86.58% 8 Missing and 3 partials ⚠️
pkg/patch/patch.go 25.00% 7 Missing and 2 partials ⚠️
pkg/utils/utils.go 0.00% 9 Missing ⚠️
pkg/buildkit/buildkit.go 0.00% 1 Missing ⚠️
pkg/pkgmgr/dpkg.go 0.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1091      +/-   ##
==========================================
+ Coverage   42.86%   45.40%   +2.53%     
==========================================
  Files          35       37       +2     
  Lines        4122     4898     +776     
==========================================
+ Hits         1767     2224     +457     
- Misses       2224     2509     +285     
- Partials      131      165      +34     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 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.

sozercan added 12 commits June 5, 2025 04:18
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
@sozercan sozercan marked this pull request as ready for review June 6, 2025 23:05
Signed-off-by: Sertac Ozercan <[email protected]>
Copy link
Contributor

@robert-cronin robert-cronin left a comment

Choose a reason for hiding this comment

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

just a few comments, otherwise LGTM!

var installCommands []string
for _, pkgArg := range installPkgArgs {
installCommands = append(installCommands,
fmt.Sprintf(`pip install %s || echo "WARN: pip install failed for %s"`, pkgArg, pkgArg))
Copy link
Contributor

Choose a reason for hiding this comment

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

should we do any validation/escaping here for the package names to prevent interpolation issues?

Copy link
Member Author

Choose a reason for hiding this comment

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

good point, added validation functions to validate names and version

var uniqueFailedPkgsList []string
if len(failedPackages) > 0 {
for _, pkgName := range failedPackages {
if !uniqueFailedPkgsMap[pkgName] {
Copy link
Contributor

Choose a reason for hiding this comment

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

it looks like this part might be duplicated a few times, perhaps we can pull out into a function like deduplicateStringSlice(input []string) []string?

Copy link
Member Author

Choose a reason for hiding this comment

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

added utils.DeduplicateStringSlice

}
installCmd := fmt.Sprintf(`sh -c '%s'`, strings.Join(installCommands, "; "))
pipInstalled = pm.config.ImageState.Run(
llb.Shlex(installCmd),
Copy link
Contributor

Choose a reason for hiding this comment

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

should we add a timeout for the pip install command?

Copy link
Member Author

Choose a reason for hiding this comment

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

by default pip has 15 seconds timeout. added a const for 300 seconds (5m), I am not sure if we want to make this configurable yet since we don't want too many knobs. maybe we can wait and see if someone wants a configurable timeout


// GetLanguageManagers returns a list of all available language managers.
// As new language managers are implemented, they should be added to this list.
func GetLanguageManagers(config *buildkit.Config, workingFolder string) []LangManager {
Copy link
Contributor

Choose a reason for hiding this comment

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

is this function only for testing?

Copy link
Member Author

Choose a reason for hiding this comment

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

this is used in patch.go for getting the package managers (kinda equivalent to the GetPackageManager for OS packages), but we only have python in this PR


#### `minor` Level

- **Allows**: `2.6.0` → `2.6.1` (preferred) or `2.7.0`
Copy link
Contributor

Choose a reason for hiding this comment

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

does this mean even if minor is set it will patch to 2.6.1 if both 2.6.1 and 2.7.0 are available?

Copy link
Member Author

Choose a reason for hiding this comment

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

correct, since focus is on CVE fixes while maintaining compatibility as much as possible. It'll only bump to 2.7.0 if 2.6.1 doesn't fix that CVE

sozercan added 2 commits June 15, 2025 05:19
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
@sozercan sozercan linked an issue Jun 25, 2025 that may be closed by this pull request
@leodewang leodewang moved this from 🆕 New to 🏗 In progress in Copacetic Workboard Jun 27, 2025
@leodewang leodewang moved this from 🏗 In progress to 👀 In review in Copacetic Workboard Jun 27, 2025
@leodewang leodewang moved this from 👀 In review to 🏗 In progress in Copacetic Workboard Jul 2, 2025
@robert-cronin robert-cronin added this to the v0.12.0 milestone Jul 14, 2025
Signed-off-by: Sertac Ozercan <[email protected]>
@Copilot Copilot AI review requested due to automatic review settings July 25, 2025 22:09
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces experimental support for app-level patching with Python package management in addition to existing OS package patching. The feature enables patching application-level dependencies using configurable patch levels and package type filtering.

Key changes:

  • Adds experimental Python language manager for patching pip-managed packages
  • Introduces --pkg-types flag to filter between OS and library packages
  • Implements --library-patch-level flag for controlling upgrade aggressiveness (patch/minor/major)
  • Updates manifest structure to separate OS and language updates

Reviewed Changes

Copilot reviewed 32 out of 33 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pkg/langmgr/python.go Core Python package manager implementation with pip integration
pkg/patch/patch.go Enhanced patching logic to support language managers and package filtering
pkg/patch/cmd.go New CLI flags for experimental package types and patch level control
pkg/report/trivy.go Extended Trivy parser with optimal version selection and library patch level support
pkg/types/unversioned/types.go Updated manifest structure separating OS and language updates
website/docs/app-level-patching.md Comprehensive documentation for the new feature

sozercan added 2 commits July 25, 2025 22:55
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
@sozercan sozercan marked this pull request as draft July 31, 2025 21:28
sozercan and others added 10 commits July 31, 2025 22:14
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Signed-off-by: Sertac Ozercan <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

[REQ] support for app-level patching
3 participants