Skip to content
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

Merge staging to main #36

Merged
merged 9 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# kics-scan disable=fd54f200-402c-4333-a5a4-36ef6709af2f,b03a748a-542d-44f4-bb86-9199ab4fd2d5
FROM python:3.8.1-slim as python-base
FROM python:3.9-slim as python-base

ENV PYTHONUNBUFFERED=1 \
# prevents python creating .pyc files
Expand Down Expand Up @@ -33,10 +33,11 @@ FROM python-base as dependencies
RUN apt-get update \
&& apt-get install --no-install-recommends -y \
# deps for building python deps
build-essential
build-essential \
git

# install poetry - respects $POETRY_VERSION & $POETRY_HOME
RUN python3.8 -m pip install --no-cache-dir --upgrade pip \
RUN python3.9 -m pip install --no-cache-dir --upgrade pip \
&& pip install --no-cache-dir poetry=="$POETRY_VERSION"

# Cache runtime deps
Expand All @@ -59,5 +60,5 @@ COPY ./entrypoint.sh /

RUN chmod +x /entrypoint.sh

ENTRYPOINT ["python3.8", "-m" , "trestlebot"]
ENTRYPOINT ["python3.9", "-m" , "trestlebot"]

2 changes: 1 addition & 1 deletion entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ else
fi

# Initialize the command variable
command="python3.8 -m trestlebot \
command="python3.9 -m trestlebot \
--markdown-path=\"${INPUT_MARKDOWN_PATH}\" \
--oscal-model=\"${INPUT_OSCAL_MODEL}\" \
--ssp-index-path=\"${INPUT_SSP_INDEX_PATH}\" \
Expand Down
549 changes: 276 additions & 273 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ trestle-bot = "trestlebot.cli:run"
[tool.poetry.dependencies]
python = '^3.8.1'
gitpython = "^3.1.31"
compliance-trestle = "^2.2.1"
compliance-trestle = {git = "https://github.com/RedHatProductSecurity/compliance-trestle.git", rev = "bb19091d08025f630379da59cba42b64e4701839"}
github3-py = "^4.0.1"
python-gitlab = "^3.15.0"

Expand Down
14 changes: 12 additions & 2 deletions tests/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
from trestle.oscal import component as comp
from trestle.oscal import profile as prof

from trestlebot.const import COMPDEF_KEY_NAME, LEVERAGED_SSP_KEY_NAME, PROFILE_KEY_NAME


JSON_TEST_DATA_PATH = pathlib.Path("tests/data/json/").resolve()

Expand Down Expand Up @@ -78,6 +80,7 @@ def setup_for_ssp(
yaml_header=None,
allowed_sections=None,
force_overwrite=None,
leveraged_ssp="",
)

return args
Expand Down Expand Up @@ -161,12 +164,19 @@ def setup_for_compdef(


def write_index_json(
file_path: str, ssp_name: str, profile: str, component_definitions: List[str]
file_path: str,
ssp_name: str,
profile: str,
component_definitions: List[str],
leveraged_ssp: str = "",
) -> None:
"""Write out ssp index JSON for tests"""
data = {
ssp_name: {"profile": profile, "component_definitions": component_definitions}
ssp_name: {PROFILE_KEY_NAME: profile, COMPDEF_KEY_NAME: component_definitions}
}

if leveraged_ssp:
data[ssp_name][LEVERAGED_SSP_KEY_NAME] = leveraged_ssp

with open(file_path, "w") as file:
json.dump(data, file, indent=4)
69 changes: 69 additions & 0 deletions tests/trestlebot/tasks/authored/test_ssp.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
test_comp = "test_comp"
test_ssp_output = "test-ssp"
markdown_dir = "md_ssp"
leveraged_ssp = "leveraged_ssp"


def test_assemble(tmp_trestle_dir: str) -> None:
Expand Down Expand Up @@ -145,3 +146,71 @@ def test_get_profile_by_ssp(tmp_trestle_dir: str) -> None:
ssp_index: SSPIndex = SSPIndex(ssp_index_path)

assert ssp_index.get_profile_by_ssp(test_ssp_output) == test_prof


def test_get_leveraged_ssp(tmp_trestle_dir: str) -> None:
"""Test to get leveraged ssp from index"""
ssp_index_path = os.path.join(tmp_trestle_dir, "ssp-index.json")
testutils.write_index_json(
ssp_index_path, test_ssp_output, test_prof, [test_comp], leveraged_ssp
)
ssp_index: SSPIndex = SSPIndex(ssp_index_path)

assert ssp_index.get_leveraged_by_ssp(test_ssp_output) == leveraged_ssp


def test_add_ssp_to_index(tmp_trestle_dir: str) -> None:
"""Test adding an ssp to an index"""
ssp_index_path = os.path.join(tmp_trestle_dir, "ssp-index.json")
testutils.write_index_json(ssp_index_path, test_ssp_output, test_prof, [test_comp])
ssp_index: SSPIndex = SSPIndex(ssp_index_path)

ssp_index.add_new_ssp("new_ssp", "test_prof", ["my_comp"])

assert ssp_index.get_profile_by_ssp("new_ssp") == "test_prof"
assert "my_comp" in ssp_index.get_comps_by_ssp("new_ssp")
assert ssp_index.get_leveraged_by_ssp("new_ssp") is None

ssp_index.add_new_ssp("another_new_ssp", "test_prof", ["my_comp"], "test_leveraged")

assert ssp_index.get_profile_by_ssp("another_new_ssp") == "test_prof"
assert "my_comp" in ssp_index.get_comps_by_ssp("another_new_ssp")
assert ssp_index.get_leveraged_by_ssp("another_new_ssp") == "test_leveraged"

# Test adding to an empty ssp index

ssp_index_path = os.path.join(tmp_trestle_dir, "another-ssp-index.json")
ssp_index = SSPIndex(ssp_index_path)

ssp_index.add_new_ssp("another_new_ssp", "test_prof", ["my_comp"], "test_leveraged")

assert ssp_index.get_profile_by_ssp("another_new_ssp") == "test_prof"
assert "my_comp" in ssp_index.get_comps_by_ssp("another_new_ssp")
assert ssp_index.get_leveraged_by_ssp("another_new_ssp") == "test_leveraged"


def test_write_new_ssp_index(tmp_trestle_dir: str) -> None:
"""Test writing out a new ssp index"""
ssp_index_path = os.path.join(tmp_trestle_dir, "ssp-index.json")
testutils.write_index_json(ssp_index_path, test_ssp_output, test_prof, [test_comp])
ssp_index: SSPIndex = SSPIndex(ssp_index_path)

ssp_index.add_new_ssp("new_ssp", "test_prof", ["my_comp"])
ssp_index.add_new_ssp("another_new_ssp", "test_prof", ["my_comp"], "test_leveraged")

ssp_index.write_out()

# Reread the ssp index from JSON
ssp_index = SSPIndex(ssp_index_path)

assert ssp_index.get_profile_by_ssp(test_ssp_output) == test_prof
assert test_comp in ssp_index.get_comps_by_ssp(test_ssp_output)
assert ssp_index.get_leveraged_by_ssp(test_ssp_output) is None

assert ssp_index.get_profile_by_ssp("new_ssp") == "test_prof"
assert "my_comp" in ssp_index.get_comps_by_ssp("new_ssp")
assert ssp_index.get_leveraged_by_ssp("new_ssp") is None

assert ssp_index.get_profile_by_ssp("another_new_ssp") == "test_prof"
assert "my_comp" in ssp_index.get_comps_by_ssp("another_new_ssp")
assert ssp_index.get_leveraged_by_ssp("another_new_ssp") == "test_leveraged"
21 changes: 20 additions & 1 deletion tests/trestlebot/test_gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
[
"https://gitlab.com/owner/repo",
"https://gitlab.com/owner/repo.git",
"https://test:[email protected]/owner/repo.git",
"gitlab.com/owner/repo.git",
],
)
Expand All @@ -55,7 +56,7 @@ def test_parse_repository(repo_url: str) -> None:
],
)
def test_parse_repository_with_server_url(repo_url: str) -> None:
"""Test an invalid url input"""
"""Test with a custom server url"""
gl = GitLab("fake", "https://mygitlab.com")

owner, repo_name = gl.parse_repository(repo_url)
Expand All @@ -64,6 +65,24 @@ def test_parse_repository_with_server_url(repo_url: str) -> None:
assert repo_name == "repo"


@pytest.mark.parametrize(
"repo_url",
[
"https://mygitlab.com/group/owner/repo",
"https://mygitlab.com/group/owner/repo.git",
"mygitlab.com/group/owner/repo.git",
],
)
def test_parse_repository_with_group(repo_url: str) -> None:
"""Test with nested namespaces"""
gl = GitLab("fake", "https://mygitlab.com")

owner, repo_name = gl.parse_repository(repo_url)

assert owner == "group/owner"
assert repo_name == "repo"


def test_parse_repository_integration(tmp_repo: Tuple[str, Repo]) -> None:
"""Tests integration with git remote get-url"""
repo_path, repo = tmp_repo
Expand Down
14 changes: 11 additions & 3 deletions trestlebot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ def run(
commit_sha: str = ""
pr_number: int = 0

# Create Git Repo
repo = Repo(working_dir)

branch_names: List[str] = [b.name for b in repo.branches] # type: ignore
if branch in branch_names:
logger.debug(f"Local branch {branch} found")
repo.git.checkout(branch)
else:
logger.debug(f"Local branch {branch} created")
repo.git.checkout("-b", branch)

# Execute bot pre-tasks before committing repository updates
if pre_tasks is not None:
for task in pre_tasks:
Expand All @@ -128,9 +139,6 @@ def run(
except TaskException as e:
raise RepoException(f"Bot pre-tasks failed: {e}")

# Create Git Repo
repo = Repo(working_dir)

# Check if there are any unstaged files
if repo.is_dirty(untracked_files=True):
if check_only:
Expand Down
7 changes: 7 additions & 0 deletions trestlebot/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,10 @@
# Common exit codes
SUCCESS_EXIT_CODE = 0
ERROR_EXIT_CODE = 1


# SSP Index Fields

PROFILE_KEY_NAME = "profile"
COMPDEF_KEY_NAME = "component_definitions"
LEVERAGED_SSP_KEY_NAME = "leveraged_ssp"
12 changes: 8 additions & 4 deletions trestlebot/gitlab.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(self, api_token: str, server_url: str = "https://gitlab.com"):
self._gitlab_client = gitlab.Gitlab(server_url, private_token=api_token)

stripped_url = re.sub(r"^(https?://)?", "", server_url)
self.pattern = r"^(?:https?://)?{0}/([^/]+)/([^/.]+)".format(
self.pattern = r"^(?:https?://)?{0}(/.+)/([^/.]+)(\.git)?$".format(
re.escape(stripped_url)
)

Expand All @@ -46,12 +46,16 @@ def parse_repository(self, repo_url: str) -> Tuple[str, str]:
Returns:
Owner and project name in a tuple, respectively
"""
match = re.match(self.pattern, repo_url)

# Strip out any basic auth
stripped_url = re.sub(r"https?://.*?@", "https://", repo_url)

match = re.match(self.pattern, stripped_url)

if not match:
raise GitProviderException(f"{repo_url} is an invalid repo URL")
raise GitProviderException(f"{stripped_url} is an invalid repo URL")

owner = match.group(1)
owner = match.group(1)[1:] # Removing the leading slash
repo = match.group(2)
return (owner, repo)

Expand Down
Loading
Loading