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

Adding validation for playbook image #4538

Merged
merged 19 commits into from
Oct 21, 2024
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
4 changes: 4 additions & 0 deletions .changelog/4538.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
changes:
- description: Added RM116 validation to the new validate flow. The validation ensure that every playbook has an image and that the image is located under doc_files folder.
type: feature
pr_number: 4538
28 changes: 23 additions & 5 deletions demisto_sdk/commands/content_graph/parsers/related_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,16 +278,34 @@ class ImageRelatedFile(PNGFiles):
file_type = RelatedFileType.IMAGE

def get_optional_paths(self) -> List[Path]:
return [
"""
Generate a list of optional paths for the content item's image.
The right path will be found later.
Returns:
List[Path]: the list of optional paths.
"""
optional_paths_list = [
self.main_file_path.parents[1]
/ "doc_files"
/ str(self.main_file_path.parts[-1])
.replace(".yml", ".png")
.replace("playbook-", ""),
Path(str(self.main_file_path).replace(".yml", ".png")),
self.main_file_path.parent / f"{self.main_file_path.parts[-2]}_image.png",
Path(str(self.main_file_path).replace(".json", "_image.png")),
.replace(
"playbook-", ""
), # In case the playbook's image is located under doc_files folder with the same name as the playbook.
self.main_file_path.parent
/ f"{self.main_file_path.parts[-2]}_image.png", # In case of integration image where the image is located in the integration folder with the same name as the integration.
]
if (
self.main_file_path.suffix == ".json"
): # when editing .yml files, we don't want to end up with the yml file as part of the optional paths.
optional_paths_list.append(
Path(str(self.main_file_path).replace(".json", "_image.png"))
)
else: # when editing .json files, we don't want to end up with the json file as part of the optional paths.
optional_paths_list.append(
Path(str(self.main_file_path).replace(".yml", ".png")),
)
return optional_paths_list


class AuthorImageRelatedFile(PNGFiles):
Expand Down
1 change: 0 additions & 1 deletion demisto_sdk/commands/validate/sdk_validation_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ select = [
"RM113",
"RM114",
"RM115",
"RM116",
"CL100",
"PR101",
"CR102",
Expand Down
64 changes: 64 additions & 0 deletions demisto_sdk/commands/validate/tests/RM_validators_test.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from pathlib import PosixPath

import more_itertools
import pytest

Expand Down Expand Up @@ -53,6 +55,9 @@
from demisto_sdk.commands.validate.validators.RM_validators.RM115_no_default_section_left import (
NoDefaultSectionsLeftReadmeValidator,
)
from demisto_sdk.commands.validate.validators.RM_validators.RM116_missing_playbook_image import (
MissingPlaybookImageValidator,
)
from demisto_sdk.commands.validate.validators.RM_validators.RM116_readme_not_to_short import (
NotToShortReadmeValidator,
)
Expand Down Expand Up @@ -918,6 +923,65 @@ def test_IsCommandsInReadmeValidator_valid():
)


def test_missing_playbook_image_validator_no_image():
edik24 marked this conversation as resolved.
Show resolved Hide resolved
"""
Given
content_items.
- Playbook without an image
When
- Calling the MissingPlaybookImageValidator obtain_invalid_content_items function.

Then
- Make sure that the validator returns an error
"""
content_items = [
create_playbook_object(),
]
result = MissingPlaybookImageValidator().obtain_invalid_content_items(content_items)
assert len(result) == 1


def test_missing_playbook_image_validator_image_exists_wrong_path():
"""
Given
content_items.
- Playbook with an image, but wrong path (the path doesn't include doc_files folder)
When
- Calling the MissingPlaybookImageValidator obtain_invalid_content_items function.

Then
- Make sure that the validator returns an error
"""
content_items = [
create_playbook_object(),
]
content_items[0].image.exist = True
result = MissingPlaybookImageValidator().obtain_invalid_content_items(content_items)
assert len(result) == 1


def test_missing_playbook_image_validator_image_exists_with_path():
"""
Given
content_items.
- Playbook with an image and correct path
When
- Calling the MissingPlaybookImageValidator obtain_invalid_content_items function.

Then
- Make sure that the validator returns an empty list
"""
content_items = [
create_playbook_object(),
]
content_items[0].image.exist = True
content_items[0].image.file_path = PosixPath(
"/var/folders/sd/bk6skd0j1xz7l1g8d4dhfn7c0000gp/T/tmpjmydes4n/Packs/doc_files/Playbooks/playbook-0.png"
)
result = MissingPlaybookImageValidator().obtain_invalid_content_items(content_items)
assert len(result) == 0


@pytest.mark.parametrize(
"file_input, missing_section",
[
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from __future__ import annotations

from typing import Iterable, List

from demisto_sdk.commands.content_graph.objects.playbook import Playbook
from demisto_sdk.commands.validate.validators.base_validator import (
BaseValidator,
ValidationResult,
)

ContentTypes = Playbook


class MissingPlaybookImageValidator(BaseValidator[ContentTypes]):
error_code = "RM116"
description = "Verifies that a playbook image exists in the doc_files folder"
rationale = "It is recommended to have an image for every playbook for better understanding and documentation"
edik24 marked this conversation as resolved.
Show resolved Hide resolved
error_message = "No playbook image found, please add playbook image"
edik24 marked this conversation as resolved.
Show resolved Hide resolved
related_field = ""
edik24 marked this conversation as resolved.
Show resolved Hide resolved
is_auto_fixable = False

def obtain_invalid_content_items(
self, content_items: Iterable[ContentTypes]
) -> List[ValidationResult]:
return [
ValidationResult(
validator=self,
message=self.error_message,
content_object=content_item,
)
for content_item in content_items
if (
not content_item.image.exist
or "doc_files" not in str(content_item.image.file_path)
)
]