Skip to content

Pipeline for Maven#1953

Open
chinyeungli wants to merge 103 commits into
mainfrom
1763_pipeline_for_maven
Open

Pipeline for Maven#1953
chinyeungli wants to merge 103 commits into
mainfrom
1763_pipeline_for_maven

Conversation

@chinyeungli

@chinyeungli chinyeungli commented Nov 13, 2025

Copy link
Copy Markdown
Contributor

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
- Update format

Signed-off-by: Chin Yeung Li <tli@nexb.com>
@chinyeungli chinyeungli requested a review from tdruez November 13, 2025 10:40
Comment thread scanpipe/pipes/resolve.py Fixed
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Comment thread scanpipe/pipes/resolve.py Fixed
…1763

- Update package's license if missing while the same package has license detected in RESOURCES

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>

@tdruez tdruez left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • Create a new maven pipe module in place of use resolve
  • Opening and loading a large file to make edits multiple times in various steps is not great.
  • To be discussed: Do we need a dedicated pipeline for just an extra step? Shouldn't the original scan_single_package detect that it's a Maven package and apply the necessary? Any reason to keep this new logic separated?

Comment thread scanpipe/pipelines/scan_maven_package.py Outdated
Comment thread scanpipe/pipelines/scan_single_package.py Outdated
Comment thread scanpipe/pipelines/scan_single_package.py Outdated
Comment thread scanpipe/pipes/resolve.py Outdated
Comment thread scanpipe/pipes/resolve.py Outdated
Signed-off-by: Chin Yeung Li <tli@nexb.com>
- Create a new maven pipe module
- Use database queries for update_package_license_from_resource_if_missing()
- Add tests

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
@chinyeungli

Copy link
Copy Markdown
Contributor Author

@tdruez I’ve updated the code to include support for the "D2D" option.

Screenshot 2025-12-29 113240

The "deploy_to_devel" option is equivalent to the "map_deploy_to_develop" pipeline, which runs on Java, JavaScript, Kotlin, and Scala as these are the languages commonly found in Maven projects.

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
@chinyeungli chinyeungli requested a review from tdruez January 28, 2026 03:31
@TG1999 TG1999 self-requested a review May 1, 2026 09:08
Some projects encountered a unique constraint violation when a resource
was already mapped:
```
duplicate key value violates unique constraint "scanpipe_codebaserelation_unique_relation"
DETAIL:  Key (from_resource_id, to_resource_id, map_type)=(1512780, 1512790, jar_to_source) already exists.
```

Signed-off-by: Chin Yeung Li <tli@nexb.com>
tdruez and others added 2 commits June 19, 2026 07:25
@chinyeungli

chinyeungli commented Jun 19, 2026

Copy link
Copy Markdown
Contributor Author

@chinyeungli Can you merge in the new changes and fix the failing test for scan_maven_package_single_file (https://github.com/aboutcode-org/scancode.io/actions/runs/26379105691/job/77644819092?pr=1953#step:10:1020)

The failing test is related to #2172 (#1763 (comment))

Reference data:
https://github.com/aboutcode-org/scancode.io/blob/1763_pipeline_for_maven/scanpipe/tests/data/jvm/scancodeio_wisp-logging.json#L739

      "is_binary": true,
      "is_text": false,

However, in SCIO the file reports:

      "is_binary": false,
      "is_text": true,

So this discrepancy is not something to be fixed in this issue?

Signed-off-by: Chin Yeung Li <tli@nexb.com>
@chinyeungli

Copy link
Copy Markdown
Contributor Author

I decided to change to another test file so that the test is passing.

@JonoYang

Copy link
Copy Markdown
Member

There seems to be duplicate commits coming in when you updated your branch, I'm not sure how to resolve this.

@chinyeungli

Copy link
Copy Markdown
Contributor Author

There seems to be duplicate commits coming in when you updated your branch, I'm not sure how to resolve this.

Are you referring to the DCO? Should I force it and click “Set DCO to pass”?

Signed-off-by: Chin Yeung <tli@nexb.com>
@tdruez

tdruez commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

I have doubts about this design, and I want to revisit a concern I raised earlier that wasn't addressed: #1953 (review)

"Do we need a dedicated pipeline for just an extra step? Shouldn't the original scan_single_package detect that it's a Maven package and apply the necessary? Any reason to keep this new logic separated?"

This new pipeline ScanMavenPackage implementation merges two fundamentally different processing paths: a basic scan and a full D2D analysis, into one class controlled by a d2d_option_enabled boolean.

The current design will be confusing to maintain and to users.

@chinyeungli

chinyeungli commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

I have doubts about this design, and I want to revisit a concern I raised earlier that wasn't addressed: #1953 (review)

"Do we need a dedicated pipeline for just an extra step? Shouldn't the original scan_single_package detect that it's a Maven package and apply the necessary? Any reason to keep this new logic separated?"

This new pipeline ScanMavenPackage implementation merges two fundamentally different processing paths: a basic scan and a full D2D analysis, into one class controlled by a d2d_option_enabled boolean.

The current design will be confusing to maintain and to users.

@tdruez The current pipeline design combines the basic scan and the D2D steps that already exist in other pipelines, with two additional steps:
fetch_and_scan_remote_pom() and update_package_license_from_resource_if_missing().

  • fetch_and_scan_remote_pom()
    If a package doesn't have a pom.xml, try to find and fetch and scan the remote (upstream) pom.xml if exist.

  • update_package_license_from_resource_if_missing()
    If a package doesn't have a declared/detected package license, but a license is found at the file level, update the package license using the license detected at the file level.

So, I guess the question is is it necessary to have a dedicated pipeline for these 2 extra steps.

@pombredanne any comment on it?

@pombredanne

Copy link
Copy Markdown
Member

@chinyeungli I like the dedicated pipeline as it helps focus the analysis, we just need to make sure we have design that @tdruez agrees to. One question is the way to invoke this. IMHO the input should be ONE PURL, and based on that the POM, the src JAR, the binary JAR(s) should be fetched, and possibly also even the corresponding source git repo should be fetched and processed. That way I could run it at the scale of a whole Maven repo, spawning one SCIO project for each PURL. Another question is if we want to also include C/C++ and native binaries steps, but that's for later. Let's discuss the details in the next call, if that works for you and @tdruez

@pombredanne pombredanne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

At last some feedback!

options = ["Java", "Kotlin", "Scala", "JavaScript"]
d2d_config.load_ecosystem_config(pipeline=self, options=options)

self.map_about_files()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am not sure you want to call all mapping steps inside a step? Should not these be their own steps?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've separated the logic into different steps

Comment thread scanpipe/pipes/maven.py Outdated
return scanning_errors


def parse_maven_filename(filename):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should this be in ScanCode? Do we have that already somewhere in PurlDB too?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed as this is not needed.

Comment thread scanpipe/pipes/maven.py Outdated
package_ns = package.get("namespace", "")
package_name = package.get("name", "")
package_version = package.get("version", "")
pom_url = (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Using this hardcoded URL means that we cannot run that on any other repo. We need to find a way to avoid that. If we use a PURL as a project input, then the Maven repo will be part of the PURL (most of the times as default), but then we do not have to further dive into that

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated code to use PURL as an input.

Comment thread scanpipe/pipes/maven.py Outdated
return None, None


def get_pom_url_list(input_source, packages):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
def get_pom_url_list(input_source, packages):
def get_pom_urls(input_source, packages):

Comment thread scanpipe/pipes/maven.py Outdated

def get_pom_url_list(input_source, packages):
"""Generate Maven POM URLs from package metadata or input source."""
pom_url_list = []

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

May be use:

Suggested change
pom_url_list = []
pom_urls = []

Comment thread scanpipe/pipes/maven.py Outdated
input_source_url = input_source.get("download_url", "")

parsed_url = urlparse(input_source_url)
maven_hosts = {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

See my comment above: no hardcoding of hosts should be needed

Comment thread scanpipe/pipes/maven.py Outdated
"repo.maven.apache.org",
"maven.google.com",
}
if input_source_url and parsed_url.netloc in maven_hosts:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do not we have code to do that in FetchCode, packageurl-python and/or scancode-toolkit? Also I have a hard time to understand all the parsing with indices. Do you have an example or tests of what you are trying to accomplish?

Comment thread scanpipe/pipes/maven.py Outdated
Comment thread scanpipe/pipes/maven.py Outdated
return False


def download_pom_files(pom_url_list):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is best to avoid a _list suffix IMHO

Suggested change
def download_pom_files(pom_url_list):
def download_pom_files(pom_url):

Comment thread scanpipe/pipes/maven.py Outdated
for pom_url in pom_url_list:
pom_file_dict = {}
try:
downloaded_pom = fetch.fetch_http(pom_url)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we use fetchcode to fetch instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, we could, but the issue is do we want to.
Following is the code if we switch to fetchcode which seems making things complicated, OR we can move the "fetch_http" to fetchcode and use it.

        import os
        import fetchcode
        downloaded_pom = fetchcode.fetch(pom_url)
        location = str(downloaded_pom.location)
        path = location + ".pom"
        # The fetch function from fetchcode save the file as /tmp/name
        # without an extension. We need to add the ".pom" extension so that
        # the package scan can work properly for this file.
        os.rename(location, path)

tdruez and others added 11 commits July 14, 2026 10:32
Signed-off-by: tdruez <tdruez@aboutcode.org>
Signed-off-by: tdruez <tdruez@aboutcode.org>
Signed-off-by: tdruez <tdruez@aboutcode.org>
Signed-off-by: tdruez <tdruez@aboutcode.org>
- Remove unnecessary code
- Override the default "download_inputs" action
- Accept only a single Maven PURL as input
- Perform a D2D scan by default if both binary and source are available
- Update tests

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
* Require for `"tab_context": {"VULNERABLECODE_URL": settings.VULNERABLECODE_URL},`

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung <tli@nexb.com>
@chinyeungli

Copy link
Copy Markdown
Contributor Author

I've redesigned the code. It now only takes 1 PURL as input.
I've also removed the manual option for d2d. If both the source and binary are available, d2d will be performed automatically, otherwise, only a basic scan is performed.

Example 1:
PURL: pkg:maven/aero/champ/cargojson@1.0
Screenshot 2026-07-14 102531

Without fetching the remote POM and updating the package data, no packages are detected because the fetched binary (https://repo1.maven.org/maven2/aero/champ/cargojson/1.0/cargojson-1.0.jar) doesn't contain a pom.xml.

However, with remote POM fetching and package data updates enabled, we successfully detect 1 package and update 17 dependencies in the summary:
Screenshot 2026-07-14 102430
Screenshot 2026-07-14 102457
Screenshot 2026-07-14 102509
(We can see the POM file was fetched remotely under "Datafile paths".)

Example 2:
PURL: pkg:maven/activemq/activemq-axis@1.2
https://repo1.maven.org/maven2/activemq/activemq-axis/1.2/

Since there is no source available for this package, only a basic scan is performed.
Screenshot 2026-07-14 102622

* Require for `"tab_context": {"VULNERABLECODE_URL": settings.VULNERABLECODE_URL},`

Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
Signed-off-by: Chin Yeung Li <tli@nexb.com>
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.