Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/packagedcode/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from packagedcode import alpine
from packagedcode import bower
from packagedcode import build
from packagedcode import buildpack
from packagedcode import build_gradle
from packagedcode import cargo
from packagedcode import chef
Expand Down Expand Up @@ -62,6 +63,8 @@
build.BuckMetadataBzlHandler,
build.BuckPackageHandler,

buildpack.BuildpackHandler,

cargo.CargoLockHandler,
cargo.CargoTomlHandler,

Expand Down
143 changes: 143 additions & 0 deletions src/packagedcode/buildpack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# ScanCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/scancode-toolkit for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
#

import toml
from packagedcode import models
from packageurl import PackageURL

class BuildpackHandler(models.DatafileHandler):
"""
Handle buildpack.toml manifests.
See https://buildpacks.io/ for details on buildpack format.
"""
datasource_id = "buildpack_toml"
path_patterns = ("*buildpack.toml",)
default_package_type = "buildpack"
description = "Cloud Native Buildpack manifest"
documentation_url = "https://buildpacks.io/"

@classmethod
def parse(cls, location, package_only=False):
"""
Parse the buildpack.toml file at `location` and yield PackageData.
"""
with open(location, "r", encoding="utf-8") as f:
data = toml.load(f)

# Extract required fields
api_version = data.get("api")
buildpack = data.get("buildpack", {})
if not buildpack:
return

name = buildpack.get("name")
if not name:
return

# Initialize common package data
package_data = dict(
datasource_id=cls.datasource_id,
type=cls.default_package_type,
name=name,
version="unknown",
description=None,
homepage_url=None,
keywords=[],
declared_license_expression=None,
dependencies=[],
)

# Handle Paketo-specific fields if present
if "api" in data:
cls.handle_paketo_buildpack(data, buildpack, package_data)

# Handle Heroku-specific fields if present
elif "publish" in data and "Ignore" in data["publish"]:
cls.handle_heroku_buildpack(data, buildpack, package_data)

yield models.PackageData.from_data(package_data, package_only)

@staticmethod
def handle_paketo_buildpack(data, buildpack, package_data):
buildpack_id = buildpack.get("id")
if buildpack_id:
package_data["extra_data"] = {"id": buildpack_id}

package_data.update({
"version": buildpack.get("version", "unknown"),
"description": buildpack.get("description"),
"homepage_url": buildpack.get("homepage"),
"keywords": buildpack.get("keywords", []),
})

licenses = buildpack.get("licenses", [])
license_expressions = [
license_entry.get("type") for license_entry in licenses if license_entry.get("type")
]
if license_expressions:
package_data["declared_license_expression"] = " AND ".join(license_expressions)

dependencies = []
metadata = data.get("metadata", {})
metadata_dependencies = metadata.get("dependencies", [])
for dep in metadata_dependencies:
dep_purl = dep.get("purl")
dep_name = dep.get("name")
dep_version = dep.get("version")
if dep_purl:
dependencies.append(
models.DependentPackage(
purl=dep_purl,
scope="runtime",
is_runtime=True,
is_optional=False,
)
)
elif dep_name and dep_version:
dependencies.append(
models.DependentPackage(
purl=PackageURL(type="generic", name=dep_name, version=dep_version).to_string(),
scope="runtime",
is_runtime=True,
is_optional=False,
)
)

orders = data.get("order", [])
for order in orders:
for group in order.get("group", []):
group_id = group.get("id")
group_version = group.get("version")
if group_id and group_version:
dependencies.append(
models.DependentPackage(
purl=PackageURL(type="buildpack", name=group_id, version=group_version).to_string(),
scope="runtime",
is_runtime=True,
is_optional=group.get("optional", False),
)
)

package_data["dependencies"] = dependencies

@staticmethod
def handle_heroku_buildpack(data, buildpack, package_data):
publish_section = data.get("publish", {})
if "Ignore" in publish_section:
ignore_files = publish_section["Ignore"].get("files", [])
if ignore_files: # Only add if files are found
package_data["extra_data"] = {"ignore_files": ignore_files}
else:
package_data["extra_data"] = {"ignore_files": []}
else:
package_data["extra_data"] = {"ignore_files": []}

# Add description for Heroku buildpack
package_data["description"] = f"Heroku buildpack for {buildpack.get('name')}"

2 changes: 1 addition & 1 deletion src/packagedcode/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ class PackageData(IdentifiablePackageData):
download_url = String(
label='Download URL',
help='A direct download URL.')

size = Integer(
default=None,
label='download size',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[buildpack]
name = "Java"

[publish.Ignore]
files = [
"etc/",
"spec/",
"test/",
".gitignore",
".github/",
"hatchet.json",
"Gemfile",
"Gemfile.lock"
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
{
"packages": [
{
"type": "buildpack",
"namespace": null,
"name": "Java",
"version": "unknown",
"qualifiers": {},
"subpath": null,
"primary_language": null,
"description": "Heroku buildpack for Java",
"release_date": null,
"parties": [],
"keywords": [],
"homepage_url": null,
"download_url": null,
"size": null,
"sha1": null,
"md5": null,
"sha256": null,
"sha512": null,
"bug_tracking_url": null,
"code_view_url": null,
"vcs_url": null,
"copyright": null,
"holder": null,
"declared_license_expression": null,
"declared_license_expression_spdx": null,
"license_detections": [],
"other_license_expression": null,
"other_license_expression_spdx": null,
"other_license_detections": [],
"extracted_license_statement": null,
"notice_text": null,
"source_packages": [],
"is_private": false,
"is_virtual": false,
"extra_data": {
"ignore_files": [
"etc/",
"spec/",
"test/",
".gitignore",
".github/",
"hatchet.json",
"Gemfile",
"Gemfile.lock"
]
},
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": null,
"package_uid": "pkg:buildpack/Java@unknown?uuid=d332d23b-1b4e-415a-96a8-141416e7e7f2",
"datafile_paths": [
"buildpack.toml"
],
"datasource_ids": [
"buildpack_toml"
],
"purl": "pkg:buildpack/Java@unknown"
}
],
"dependencies": [],
"files": [
{
"path": "buildpack.toml",
"type": "file",
"package_data": [
{
"type": "buildpack",
"namespace": null,
"name": "Java",
"version": "unknown",
"qualifiers": {},
"subpath": null,
"primary_language": null,
"description": "Heroku buildpack for Java",
"release_date": null,
"parties": [],
"keywords": [],
"homepage_url": null,
"download_url": null,
"size": null,
"sha1": null,
"md5": null,
"sha256": null,
"sha512": null,
"bug_tracking_url": null,
"code_view_url": null,
"vcs_url": null,
"copyright": null,
"holder": null,
"declared_license_expression": null,
"declared_license_expression_spdx": null,
"license_detections": [],
"other_license_expression": null,
"other_license_expression_spdx": null,
"other_license_detections": [],
"extracted_license_statement": null,
"notice_text": null,
"source_packages": [],
"file_references": [],
"is_private": false,
"is_virtual": false,
"extra_data": {
"ignore_files": [
"etc/",
"spec/",
"test/",
".gitignore",
".github/",
"hatchet.json",
"Gemfile",
"Gemfile.lock"
]
},
"dependencies": [],
"repository_homepage_url": null,
"repository_download_url": null,
"api_data_url": null,
"datasource_id": "buildpack_toml",
"purl": "pkg:buildpack/Java@unknown"
}
],
"for_packages": [
"pkg:buildpack/Java@unknown?uuid=d332d23b-1b4e-415a-96a8-141416e7e7f2"
],
"scan_errors": []
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[buildpack]
name = "PHP"

[publish.Ignore]
files = [
".github/",
".gitignore",
".rspec_parallel",
"support/build/",
"support/devcenter/",
"test/",
"Gemfile",
"Gemfile.lock",
"hatchet.json",
"hatchet.lock",
"requirements.txt",
]
Loading
Loading