Skip to content

Commit df0f740

Browse files
TG1999keshav-space
andauthored
Refactor conan mining pipeline for git deployment (#787)
* Refactor conan mining pipeline for git deployment Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Refactor tests Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Fix tests Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Restructure code and tests Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Release minecode for conan pipeline deployment Signed-off-by: Keshav Priyadarshi <git@keshav.space> * Fix saneyaml import Signed-off-by: Keshav Priyadarshi <git@keshav.space> * Fix missing MINECODE_CONAN_INDEX_REPO Signed-off-by: Keshav Priyadarshi <git@keshav.space> * Fix errors Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Fix errors Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Fix errors Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Fix errors Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Fix errors Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> * Fix errors Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> --------- Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com> Signed-off-by: Keshav Priyadarshi <git@keshav.space> Co-authored-by: Keshav Priyadarshi <git@keshav.space>
1 parent 51f02e0 commit df0f740

File tree

6 files changed

+61
-179
lines changed

6 files changed

+61
-179
lines changed

minecode_pipelines/miners/conan.py

Lines changed: 0 additions & 68 deletions
This file was deleted.

minecode_pipelines/pipelines/mine_conan.py

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -20,60 +20,44 @@
2020
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
2121
# Visit https://github.com/aboutcode-org/scancode.io for support and download.
2222

23-
import os
24-
from scanpipe.pipelines import Pipeline
25-
from minecode_pipelines import pipes
26-
from minecode_pipelines.miners import conan
23+
from pathlib import Path
24+
from minecode_pipelines.pipes import conan
25+
from minecode_pipelines.pipelines import MineCodeBasePipeline
2726
from scanpipe.pipes import federatedcode
2827

29-
MINECODE_CONAN_INDEX_REPO = "https://github.com/conan-io/conan-center-index"
3028

31-
MINECODE_DATA_CONAN_REPO = os.environ.get(
32-
"MINECODE_DATA_CONAN_REPO", "https://github.com/aboutcode-data/minecode-data-conan-test"
33-
)
34-
35-
36-
class MineConan(Pipeline):
29+
class MineConan(MineCodeBasePipeline):
3730
"""Pipeline to mine Conan packages and publish them to FederatedCode repo."""
3831

32+
MINECODE_CONAN_INDEX_REPO = "https://github.com/conan-io/conan-center-index"
33+
3934
@classmethod
4035
def steps(cls):
4136
return (
4237
cls.check_federatedcode_eligibility,
43-
cls.clone_conan_repos,
44-
cls.mine_and_publish_conan_package_urls,
38+
cls.create_federatedcode_working_dir,
39+
cls.clone_conan_index,
40+
cls.fetch_federation_config,
41+
cls.mine_and_publish_packageurls,
42+
cls.delete_working_dir,
4543
)
4644

47-
def check_federatedcode_eligibility(self):
48-
"""
49-
Check if the project fulfills the following criteria for
50-
pushing the project result to FederatedCode.
51-
"""
52-
federatedcode.check_federatedcode_configured_and_available(logger=self.log)
53-
54-
def clone_conan_repos(self):
55-
"""
56-
Clone the Conan-related repositories (index, data, and pipelines config)
57-
and store their Repo objects in the corresponding instance variables.
58-
"""
59-
self.conan_index_repo = federatedcode.clone_repository(MINECODE_CONAN_INDEX_REPO)
60-
self.cloned_data_repo = federatedcode.clone_repository(MINECODE_DATA_CONAN_REPO)
61-
62-
if self.log:
63-
self.log(
64-
f"{MINECODE_CONAN_INDEX_REPO} repo cloned at: {self.conan_index_repo.working_dir}"
65-
)
66-
self.log(
67-
f"{MINECODE_DATA_CONAN_REPO} repo cloned at: {self.cloned_data_repo.working_dir}"
68-
)
69-
70-
def mine_and_publish_conan_package_urls(self):
71-
conan.mine_and_publish_conan_packageurls(
72-
self.conan_index_repo, self.cloned_data_repo, self.log
45+
def clone_conan_index(self):
46+
"""Clone the Cargo index Repo."""
47+
self.conan_index_repo = federatedcode.clone_repository(
48+
repo_url=self.MINECODE_CONAN_INDEX_REPO,
49+
clone_path=self.working_path / "conan-index",
50+
logger=self.log,
7351
)
7452

75-
def delete_cloned_repos(self):
76-
pipes.delete_cloned_repos(
77-
repos=[self.conan_index_repo, self.cloned_data_repo],
53+
def packages_count(self):
54+
base_path = Path(self.conan_index_repo.working_tree_dir)
55+
package_dir = [p for p in base_path.iterdir() if p.is_dir() and not p.name.startswith(".")]
56+
return sum(1 for dir in package_dir for f in dir.rglob("*") if f.is_file())
57+
58+
def mine_packageurls(self):
59+
"""Yield PackageURLs from Cargo index."""
60+
return conan.mine_conan_packageurls(
61+
conan_index_repo=self.conan_index_repo,
7862
logger=self.log,
7963
)

minecode_pipelines/pipes/conan.py

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,40 @@
2020
# ScanCode.io is a free software code scanning tool from nexB Inc. and others.
2121
# Visit https://github.com/aboutcode-org/scancode.io for support and download.
2222

23-
from packageurl import PackageURL
2423
from pathlib import Path
25-
from aboutcode import hashid
26-
from minecode_pipelines.pipes import write_data_to_yaml_file
24+
from packageurl import PackageURL
2725

26+
import saneyaml
2827

29-
def store_conan_packages(pacakge_name, versions_data, fed_repo):
30-
"""Collect Conan package versions into purls and write them to the repo."""
3128

32-
base_purl = PackageURL(type="conan", name=pacakge_name)
29+
def get_conan_packages(file_path, file_versions_data):
30+
# Example: file_path = Path("repo_path/recipes/7zip/config.yml")
31+
# - file_path.parts = ("repo_path", "recipes", "7zip", "config.yml")
32+
# - file_path.parts[-2] = "7zip" (the package name)
33+
if len(file_path.parts) < 2:
34+
return None, []
35+
package_name = file_path.parts[-2]
36+
base_purl = PackageURL(type="conan", name=package_name)
3337

3438
updated_purls = []
35-
versions = list(versions_data["versions"].keys())
39+
versions = file_versions_data.get("versions") or []
3640
for version in versions:
37-
purl = PackageURL(type="conan", name=pacakge_name, version=version).to_string()
41+
purl = PackageURL(type="conan", name=package_name, version=str(version)).to_string()
3842
updated_purls.append(purl)
43+
return base_purl, updated_purls
44+
45+
46+
def mine_conan_packageurls(conan_index_repo, logger):
47+
"""Mine Conan PackageURLs from package index."""
48+
49+
base_path = Path(conan_index_repo.working_dir)
50+
for file_path in base_path.glob("recipes/**/*"):
51+
if not file_path.name == "config.yml":
52+
continue
53+
with open(file_path, encoding="utf-8") as f:
54+
versions = saneyaml.load(f)
55+
56+
if not versions:
57+
continue
3958

40-
ppath = hashid.get_package_purls_yml_file_path(base_purl)
41-
purl_file_full_path = Path(fed_repo.working_dir) / ppath
42-
write_data_to_yaml_file(path=purl_file_full_path, data=updated_purls)
43-
return purl_file_full_path, base_purl
59+
yield get_conan_packages(file_path=file_path, file_versions_data=versions)

minecode_pipelines/tests/pipes/test_conan.py

Lines changed: 6 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,20 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10-
import tempfile
1110
from pathlib import Path
12-
from unittest import mock
13-
from unittest.mock import Mock, patch
1411
import saneyaml
1512
import yaml
1613

1714
from django.test import TestCase
1815

19-
from minecode_pipelines.pipes import write_data_to_yaml_file
20-
from minecode_pipelines.pipes.conan import store_conan_packages
16+
from minecode_pipelines.pipes.conan import get_conan_packages
2117

2218
DATA_DIR = Path(__file__).parent.parent / "test_data" / "conan"
2319

2420

2521
class ConanPipelineTests(TestCase):
26-
@patch("minecode_pipelines.pipes.conan.write_data_to_yaml_file")
27-
def test_collect_packages_from_cargo_calls_write(self, mock_write):
28-
packages_file = DATA_DIR / "cairo-config.yml"
22+
def test_collect_packages_from_conan_calls_write(self, mock_write):
23+
packages_file = DATA_DIR / "cairo" / "cairo-config.yml"
2924
expected_file = DATA_DIR / "expected-cairo-purls.yml"
3025

3126
with open(packages_file, encoding="utf-8") as f:
@@ -34,51 +29,6 @@ def test_collect_packages_from_cargo_calls_write(self, mock_write):
3429
with open(expected_file, encoding="utf-8") as f:
3530
expected = saneyaml.load(f)
3631

37-
with tempfile.TemporaryDirectory() as tmpdir:
38-
repo = Mock()
39-
repo.working_dir = tmpdir
40-
41-
store_conan_packages("cairo", versions_data, repo)
42-
43-
mock_write.assert_called_once()
44-
args, kwargs = mock_write.call_args
45-
base_purl, written_packages = kwargs["path"], kwargs["data"]
46-
47-
expected_base_purl = (
48-
Path(tmpdir) / "aboutcode-packages-conan-0" / "conan" / "cairo" / "purls.yml"
49-
)
50-
51-
self.assertEqual(str(base_purl), str(expected_base_purl))
52-
self.assertEqual(written_packages, expected)
53-
54-
def _assert_purls_written(self, purls):
55-
with tempfile.TemporaryDirectory() as tmpdir:
56-
repo_dir = Path(tmpdir)
57-
58-
mock_repo = mock.MagicMock()
59-
mock_repo.working_dir = str(repo_dir)
60-
mock_repo.index.add = mock.MagicMock()
61-
62-
purls_file = repo_dir / "purls.yaml"
63-
64-
write_data_to_yaml_file(purls_file, purls)
65-
66-
self.assertTrue(purls_file.exists())
67-
68-
with open(purls_file, encoding="utf-8") as f:
69-
content = saneyaml.load(f)
70-
71-
self.assertEqual(content, purls)
72-
73-
def test_add_purl_result_with_mock_repo(self):
74-
purls = [
75-
{"purl": "pkg:conan/cairo@1.18.0"},
76-
{"purl": "pkg:conan/cairo@1.17.8"},
77-
{"purl": "pkg:conan/cairo@1.17.6"},
78-
{"purl": "pkg:conan/cairo@1.17.4"},
79-
]
80-
81-
self._assert_purls_written(purls)
82-
83-
def test_add_empty_purl_result_with_mock_repo(self):
84-
self._assert_purls_written([])
32+
base, purls = get_conan_packages(packages_file, versions_data)
33+
self.assertEqual(purls, expected)
34+
self.assertEqual(str(base), "pkg:conan/cairo")

pyproject-minecode_pipelines.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "flot.buildapi"
44

55
[project]
66
name = "minecode_pipelines"
7-
version = "0.0.1b32"
7+
version = "0.0.1b41"
88
description = "A library for mining packageURLs and package metadata from ecosystem repositories."
99
readme = "minecode_pipelines/README.rst"
1010
license = { text = "Apache-2.0" }

0 commit comments

Comments
 (0)