diff --git a/.github/workflows/action-ci.yml b/.github/workflows/action-ci.yml index 6c6d643..f2eae42 100644 --- a/.github/workflows/action-ci.yml +++ b/.github/workflows/action-ci.yml @@ -44,15 +44,22 @@ jobs: steps: - name: Run action id: test-action - uses: ynput/github-query@main + uses: ynput/github-query@generate-changelog with: repo: "ynput/ayon-addon-action-testing" date: "2024-08-20T12:03:23Z" - query_parameters: "body,labels,title" + query_parameters: "body,labels,title,number,url,id" + changelog_labels: "feature,enhancement,bugfix,refactor,docs,test,pr" - name: Show results run: | echo "RAW-response: " && echo '${{ steps.test-action.outputs.raw-output }}' echo "Labels: " && echo '${{ steps.test-action.outputs.label-list }}' echo "Bump-increment: " && echo '${{ steps.test-action.outputs.bump-increment }}' - # echo "Changelog: " && echo '${{ steps.test-action.outputs.changelog-markdown }}' + echo "Changelog: " && echo '${{ steps.test-action.outputs.changelog-markdown }}' + + + - name: Show changelog formatted + shell: bash + run: | + printf '${{ steps.test-action.outputs.changelog-markdown }}' diff --git a/README.md b/README.md index bfb0956..5030348 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,53 @@ -# CI-Status +# Github-Query + [![CI-Status](https://github.com/ynput/github-query/actions/workflows/action-ci.yml/badge.svg)](https://github.com/ynput/github-query/actions/workflows/action-ci.yml) -# Github-Data -Fetch and convert certain information retrieved from github +**This is a customized query action for Ayon-related repo-workflows.** + +## Purpose + +This action mainly queries pull request related information. +It got a bunch of conversion going on to prepare the data for further usage. This includes + +* Filtering PR labels +* Suggest version increment based on found labels +* Preparing data structure for release information +* Prepare a markdown formatted changelog based on PR information + +## Usage + +For details see [action.yml](https://github.com/ynput/github-query/blob/main/action.yml) file + +```yaml +- name: Query PR data + uses: ynput/github-query@main + with: + # Repository name with owner. For example, actions/checkout + repo: "" + # Date-Time-Stamp as a starting point for the query, will only process merged PRs newer then that date + # format: "2024-08-20T12:03:23Z" + date: "" + # JSON keys to query for in a gh query command + # gh pr list --state merged --search f'merged:>=' --json "body,labels,title,id,number,url" --repo + query_parameters: "" + # Define change log content and order by this comma separated value string + # example: "enhancement,bugfix,docs" + changelog_labels: "" +``` + +## Outputs + +* raw-output - Full output json dictionary from github api +* label-list - List of unique labels found in PRs +* bump-increment - Increment for version bumping - either 'patch', 'minor' or 'major' +* changelog-markdown - String containing markdown formatted release changelog + +## Testing + +Unit-test are included in `tests/` and will run on every pr targeting main and very push to main. +These tests can be run local by changing into the `tests/` directory and running `pytest` + +## Developer-Hints + +The python file `github_query.py` calls all the main logic and provides it's function to `action.yml` through click-parameters. +This makes the python function calls convenient to use from terminal while keeping them easy to test. diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 3329707..0000000 --- a/TODO.md +++ /dev/null @@ -1,16 +0,0 @@ -# Implement changelog creation - -## Changelog sections - -* New Features -* Enhancements -* Bug Fixes -* Refactored code -* Documentation -* Testing -* Merged Pull requests - -## Structure for implementation - -* Implement section order in repo variable -* One repo var per section to store PR label names \ No newline at end of file diff --git a/action.yml b/action.yml index c50d6d4..488e0ef 100644 --- a/action.yml +++ b/action.yml @@ -1,12 +1,12 @@ --- -# TODO need strategy where to store defaults - which an be overriden by repo var +# TODO need strategy where to store defaults - which an be override by repo var name: Github Release Information description: Fetch and convert data from github to use for a release trigger branding: - icon: plus + icon: arrow-left-circle color: green inputs: @@ -19,6 +19,9 @@ inputs: query_parameters: description: Parameters to query for in pr Information required: true + changelog_labels: + description: CSV string of labels for changelog order + required: false outputs: raw-output: @@ -30,9 +33,9 @@ outputs: bump-increment: description: Increment for version bumping - either `patch` or 'minor' value: ${{ steps.bump-increment.outputs.increment }} - # changelog-markdown: - # description: String containing full makrdown syntax for release changelog information - # value: ${{ steps.write-changelog.outputs.changelog }} + changelog-markdown: + description: String containing full markdown syntax for release changelog information + value: ${{ steps.write-changelog.outputs.changelog }} runs: using: composite @@ -55,12 +58,8 @@ runs: shell: bash run: | cd $GITHUB_ACTION_PATH - label_list=$(python -c 'import github_query; print(github_query.get_labels(github_query.parse_args()))' "${{ inputs.repo }}" "${{ inputs.query_parameters }}" "${{ inputs.date }}") - if [[ "$label_list" == '[]' ]]; then - echo "label_list=''" >> $GITHUB_OUTPUT - exit 0 - fi - + label_list=$(python github_query.py pr-labels "${{ inputs.repo }}" "${{ inputs.query_parameters }}" "${{ inputs.date }}") + echo "label_list=$label_list" >> $GITHUB_OUTPUT - name: Get version increment @@ -68,18 +67,26 @@ runs: shell: bash run: | cd $GITHUB_ACTION_PATH - increment=$(python -c 'import github_query; pr_labels = github_query.get_labels(github_query.parse_args()); patch_repo_var = github_query.get_repo_var(repo="${{ inputs.repo }}", var_name="PATCH_BUMP_LABEL"); minor_repo_var = github_query.get_repo_var(repo="${{ inputs.repo }}", var_name="MINOR_BUMP_LABEL"); print(github_query.get_version_increment(patch_bump_list=patch_repo_var, minor_bump_list=minor_repo_var, pr_label_list=pr_labels))' "${{ inputs.repo }}" "${{ inputs.query_parameters }}" "${{ inputs.date }}") + increment=$(python github_query.py version-increment "${{ inputs.repo }}" "${{ inputs.query_parameters }}" "${{ inputs.date }}") + echo "increment=$increment" >> $GITHUB_OUTPUT - # disabled until fixed - # - name: Prepare Changelog - # id: write-changelog - # shell: bash - # run: | - # cd $GITHUB_ACTION_PATH - # changelog=$(python -c 'import github_query; gh_query = github_query.parse_args(); patch_repo_var = github_query.get_repo_var(repo="${{ inputs.repo }}", var_name="PATCH_BUMP_LABEL"); minor_repo_var = github_query.get_repo_var(repo="${{ inputs.repo }}", var_name="MINOR_BUMP_LABEL"); print(github_query.prepare_changelog_markdown(pr_query=gh_query, minor_bump_list=minor_repo_var, patch_bump_list=patch_repo_var))' "${{ inputs.repo }}" "${{ inputs.query_parameters }}" "${{ inputs.date }}") - # oneline_changelog=$(echo "$changelog" | base64 | tr -d '/n') - # echo "oneline changelog: $oneline_changelog" - # # echo "changelog=$oneline_changelog" >> $GITHUB_OUTPUT + # INFO multiline strings need to be precessed like this according to + # INFO https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#multiline-strings + # INFO and + # INFO https://stackoverflow.com/questions/74137120/how-to-fix-or-avoid-error-unable-to-process-file-command-output-successfully/74232400#74232400 + - name: Prepare Changelog + if: ${{ inputs.changelog_labels }} + id: write-changelog + shell: bash + run: | + cd $GITHUB_ACTION_PATH + changelog=$(python github_query.py generate-release-changelog "${{ inputs.repo }}" "${{ inputs.query_parameters }}" "${{ inputs.date }}" "${{ inputs.changelog_labels }}") + delimiter="$(openssl rand -hex 8)" + { + echo "changelog<<${delimiter}" + echo "$changelog" + echo "${delimiter}" + } >> $GITHUB_OUTPUT ... diff --git a/github_query.py b/github_query.py index cec0841..3cd1eb6 100644 --- a/github_query.py +++ b/github_query.py @@ -1,162 +1,83 @@ """ -This script is written in a certain - maybe even unconventional way - by intention. -It's supposed to be run from comamndline right away to be used in a github action workflow yaml file. -Additonally it's test suite relies mainly on putest and therefore the functions need to be importable to the pytest script. +This script is supposed to be run from command line right away to be used in a github action workflow yaml file. +Additionally it's test suite relies mainly on pytest and therefore the functions need to be importable to the pytest script. """ -import argparse -import json -import logging -import re -import subprocess +import click +from src import conversion_logic, queries +from typing import List -logger = logging.getLogger(__name__) +@click.group() +def cli() -> None: + pass -def parse_args() -> dict: - """Parse command-line arguments and store them in a global variable.""" - parser = argparse.ArgumentParser(description="A python script to convert GitHub PR information to a more simple format.") - parser.add_argument("repo", type=str, help="Repository name consisting of 'repo-owner/repo-name'") - parser.add_argument("query_parameters", type=str, help="Keys to query for.") - parser.add_argument("date", type=str, default="2024-07-08T09:48:33Z", help="Latest release date.") - parsed_args = parser.parse_args() +@cli.command() +@click.argument('repo_name', type=click.STRING) +@click.argument('query_tags', type=click.STRING) +@click.argument('latest_release_date', type=click.STRING) +def pr_labels(latest_release_date: str, query_tags: str, repo_name: str) -> None: + """Get a list of all version relevant PR labels. - repo_name = parsed_args.repo - query_tags = parsed_args.query_parameters.split(',') - latest_release_date = parsed_args.date - - command = f"gh pr list --state merged --search 'merged:>={latest_release_date}' --json {','.join(query_tags)} --repo {repo_name}" - pr_json = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - - return json.loads(pr_json.stdout) - -def get_changelog(pr_data, changelog_start="## Changelog", heading="##"): - """Get list of changes from a PRs changelog. - - Args: - pr_body (list(str)): List of PR body contents. - changelog_start (str, optional): Indicates markdown changelog section. Defaults to "## Changes". - heading (str, optional): Markdown heading. Defaults to "##". - - Returns: - list(str): List of changes found. - """ - - lines = pr_data.splitlines() - changelog_section = None - changelog_lines = [] - - for line in lines: - if line.startswith(changelog_start): - changelog_section = True - continue - - if changelog_section and line.startswith(heading): - break - - if changelog_section and line.startswith("* "): - changelog_lines.append(line.strip("* ").strip()) - - return changelog_lines - -def changelog_per_label(json_dict): - # TODO replace with labels fetched from repo variables - changelog_labels = ["bugfix", "enhancement", "feature"] - labels = [] - for item in json_dict: - labels.append(item["labels"]) - if any(item in changelog_labels for item in labels): - pass - -def prepare_changelog_markdown(pr_query, minor_bump_list, patch_bump_list): - # ? should version bump labels also be filter for changelog ? - label_list = minor_bump_list + patch_bump_list - changelog = "" - - for pr in pr_query: - # get all label names in a list - pr_label_list = [label["name"] for label in pr["labels"]] - fitlered_label = list(set(label_list).intersection(pr_label_list))[0] - - if fitlered_label: - change_list = get_changelog(pr_data=pr["body"]) - - changelog += f"## {fitlered_label.capitalize()}\n" - changelog += "".join([f"* {change}\n" for change in change_list]) - changelog += "\n" - - return changelog - - -def get_labels(pr_data: dict) -> list: - """Filter all unique labels from dictionary. - - Args: - pr_data (dict): Github PR query result - - Returns: - [str]: Liste of unique labels strings found or `None`. + latest_release_date (str): datatime string\n + query_tags (str): csv string\n + repo_name (str): repo name as \n """ + + query_tags_list: List[str] = conversion_logic.csv_string_to_list(input=query_tags) + pr_result: List[dict[str, str]] = queries.query_merged_prs(latest_release_date, query_tags_list, repo_name) + pr_labels: List[str] = conversion_logic.filter_unique_labels(pr_data=pr_result) - labels = set() - - for item in pr_data: - if not item.get("labels"): - return [] - for label in item["labels"]: - if not label.get("name"): - return [] + if not pr_labels: + click.echo("") + return - labels.add(label["name"]) + click.echo(pr_labels) - return list(labels) -def get_repo_var(repo: str, var_name: str) -> list: - """Query labels from repository variables. +@cli.command() +@click.argument('repo_name', type=click.STRING) +@click.argument('query_tags', type=click.STRING) +@click.argument('latest_release_date', type=click.STRING) +def version_increment(latest_release_date: str, query_tags: str, repo_name: str): + """Output a calculated version increment suggestion. - Args: - repo (str): Repository name `owner/repo-name` - var_name (str): Repo variable name - - Returns: - str: Comma separated value string. + latest_release_date (str): datetime string\n + query_tags (str): csv string\n + repo_name (str): repo name as \n """ - labels = subprocess.run( - ["gh", "variable", "get", var_name, "--repo", repo], - capture_output=True, - text=True, - check=True - ) - - return csv_string_to_list(labels.stdout) -def csv_string_to_list(input: str) -> list: - if input: - return re.split(r',\s*', input.strip()) + query_tags_list: list[str] = conversion_logic.csv_string_to_list(query_tags) + pr_result: list[dict[str, str]] = queries.query_merged_prs(latest_release_date, query_tags_list, repo_name) + pr_labels: conversion_logic.List[str] = conversion_logic.filter_unique_labels(pr_data=pr_result) + patch_repo_var_list: conversion_logic.List[str] = conversion_logic.csv_string_to_list(queries.get_repo_var(repo=repo_name, var_name="PATCH_BUMP_LABEL")) + minor_repo_var_list: conversion_logic.List[str] = conversion_logic.csv_string_to_list(queries.get_repo_var(repo=repo_name, var_name="MINOR_BUMP_LABEL")) + increment = conversion_logic.get_version_increment(patch_bump_list=patch_repo_var_list, minor_bump_list=minor_repo_var_list, pr_label_list=pr_labels) - return [] + click.echo(increment) -def get_version_increment(patch_bump_list: list, minor_bump_list: list, pr_label_list: list): - """Figure out version increment based on PR labels. - Args: - patch_bump_list ([str]): Labels for bumping patch version - minor_bump_list ([str]): Labels for bumping minor version - label_list([str]): Labels found in PRs +@cli.command() +@click.argument('repo_name', type=click.STRING) +@click.argument('query_tags', type=click.STRING) +@click.argument('latest_release_date', type=click.STRING) +@click.argument('changelog_labels', type=click.STRING) +def generate_release_changelog(latest_release_date: str, query_tags: str, repo_name: str, changelog_labels: str) -> None: + """Output a markdown formatted changelog. - Returns: - str: version increment + latest_release_date (str): datetime string\n + query_tags (str): csv string\n + repo_name (str): repo name as \n """ - if not pr_label_list: - return "" - - # TODO add major bump option - if any(label in pr_label_list for label in minor_bump_list): - return "minor" + query_tags_list: list[str] = conversion_logic.csv_string_to_list(query_tags) + pr_result: list[dict[str, str]] = queries.query_merged_prs(latest_release_date, query_tags_list, repo_name) + changelog_labels_result: list[str] = conversion_logic.csv_string_to_list(changelog_labels) + pr_filtered: list[conversion_logic.Changelog] = conversion_logic.filter_changes_per_label(pr_data=pr_result, changelog_label_list=changelog_labels_result) + markdown_changelog: str = conversion_logic.format_changelog_markdown(changes=pr_filtered, changelog_label_list=changelog_labels_result) - if any(label in pr_label_list for label in patch_bump_list): - return "patch" + click.echo(markdown_changelog) - return "" +if __name__ == "__main__": + cli() diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/conversion_logic.py b/src/conversion_logic.py new file mode 100644 index 0000000..13ddaa6 --- /dev/null +++ b/src/conversion_logic.py @@ -0,0 +1,191 @@ +import logging +import re + +from typing import NamedTuple, List + +logger: logging.Logger = logging.getLogger(__name__) + + +class Changelog(NamedTuple): + labels: List[str] + title: str + number: int + url: str + id: int + body: str + + +def filter_unique_labels(pr_data: List[dict[str, str]]) -> List[str]: + """Filter all unique labels from dictionary. + + Args: + pr_data (dict): Github PR query result + + Returns: + list: List of unique labels strings found or `None`. + """ + + labels = set() + + for item in pr_data: + if not item.get("labels"): + logger.warning("No PR label data found.") + return [] + for label in item["labels"]: + if not label.get("name"): + logger.warning("No PR label names found.") + return [] + + labels.add(label["name"]) + logger.debug("PR labels found.") + + return list(labels) + + +def csv_string_to_list(input: str) -> List[str]: + """Convert string to list. + + Args: + input (str): Expected csv string. + + Returns: + list: List of strings. + """ + + if input: + return re.split(r',\s*', input.strip()) + + return [] + + +def get_version_increment(pr_label_list: List[str] | None, patch_bump_list: List[str]=[], minor_bump_list: List[str]=[], major_bump_list: List[str] | str=[]): + """Figure out version increment based on PR labels. + + Args: + patch_bump_list ([str]): Labels for bumping patch version + minor_bump_list ([str]): Labels for bumping minor version + label_list ([str]): Labels found in PRs + + Returns: + str: version increment + """ + + if not pr_label_list: + logger.warning("PR label list was empty") + return "" + + for name, param in locals().items(): + if not isinstance(param, list): + raise ValueError(f"{name} must be a list.") + + if any(label in pr_label_list for label in major_bump_list): + return "major" + + if any(label in pr_label_list for label in minor_bump_list): + return "minor" + + if any(label in pr_label_list for label in patch_bump_list): + return "patch" + + logger.warning("No relevant labels found for version increment.") + return "" + + +def filter_changes_per_label(pr_data: List[dict[str, str]], changelog_label_list: List[str]) -> List[Changelog]: + """Convert list of PR dictionaries to Changelog list + + Args: + pr_data (list[dict[str, str]]): PR information and metadata + changelog_label_list (list[str]): Changelog labels + + Returns: + list[Changelog]: List of changelog objects + """ + + changes_list: List[Changelog] = [] + + for pull_request in pr_data: + if pull_request.get("labels"): + changes_list.append(Changelog(labels=[label["name"] for label in pull_request["labels"]], + title=pull_request["title"], + number=pull_request["number"], + url=pull_request["url"], + id=pull_request["id"], + body=pull_request["body"], + ) + ) + + return changes_list + + +def get_changelog_description(pr_body: str, changelog_desc: str ="## Changelog Description", heading: str ="##") -> List[str]: + """Get list of changes from a PRs changelog. + + Args: + pr_body list(str): PR body content + changelog_desc (str, optional): Indicates markdown changelog section. Defaults to "## Changes" + heading (str, optional): Markdown heading. Defaults to "##" + + Returns: + list(str): List of changes found. + """ + + lines: list[str] = pr_body.splitlines() + changelog_section = None + description_lines: list[str] = [] + + for line in lines: + if line.startswith(changelog_desc): + changelog_section = True + continue + + if changelog_section and line.startswith(heading): + break + + if changelog_section: + description_lines.append(line.strip()) + + for index in [0, -1]: + if not description_lines[index]: + description_lines.pop(index) + + return description_lines + + +def format_changelog_markdown(changes: List[Changelog], changelog_label_list: List[str]) -> str: + """Create markdown formatted changelog. + + Args: + changes (list[Changelog]): Changelogs in a list + changelog_label_list (list[str]): Label list to control order and filtering + + Returns: + str: Markdown formatted string + """ + + changelog = "# Changelog\n" + change_label_list: set[str] = {label for change in changes for label in change.labels} + + for label in changelog_label_list: + if label not in change_label_list: + continue + + formatted_label: str = label.removeprefix("type: ").capitalize() + changelog += f"\n### **{formatted_label}**\n\n" + + for change in changes: + if label in change.labels: + changelog += f"
\n" + changelog += f"{change.title} - #{change.number}\n\n" + + changelog_desc: List[str] = get_changelog_description(change.body, changelog_desc="## Changelog Description", heading="##") + + for desc_line in changelog_desc: + if desc_line.startswith("\r\n\r\nThis was \"deprecated\" since OpenPype 3.15.5.\r\n\r\nAlso removed the legacy OCIO config settings that were for Maya 2020 and older since those are Py2 anyway and are already unsupported.\r\n\r\n## Testing notes:\r\n\r\n1. Test whether the color management settings work and apply as you'd expect\r\n2. Preferably you also test how this influences older projects from before and highlight where the issues may appear.\r\n", + "id": "PR_kwDOMQ8b8s57Ivvp", + "labels": [ + { + "id": "LA_kwDOMQ8b8s8AAAABvFMNlw", + "name": "bump minor", + "description": "", + "color": "F1F25D" + } + ], + "number": 103, + "title": "Remove deprecated color management settings ", + "url": "https://github.com/ynput/ayon-maya/pull/103" + }, + { + "body": "## Changelog Description\r\n\r\n\r\nThis fixes a case where looks failed to apply due to `None` values being present in the collected attributes.\r\nThese will now be ignored in collected. There's an edge case where Maya returns `None` for string attributes that have no values set - those are captured now explicitly to just `\"\"` to still collect and apply them later.\r\n\r\nExisting looks will now also apply correctly with `None` value in their look attributes, but the attributes with `None` values will be ignored with a warning.\r\n\r\n## Additional info\r\n\r\n\r\n## Testing notes:\r\n\r\n1. Load a model reference\r\n2. Create a string attribute, e.g. `test`\r\n3. Do not set any value for it.\r\n - Maya will return None for this attribute, e.g. select the object and run:\r\n```python\r\nfrom maya import cmds\r\nprint(cmds.getAttr(\".test\"))\r\n```\r\nIt will print `None`.\r\n4. Publish the look for this mesh\r\n5. The published `.json` file should have attribute value for `test` set to `\"\"`\r\n\r\nTo test the 'backwards compatible fix':\r\n- Publish the same look with `develop` branch. The value will be `null` in the `.json` file.`\r\n- OR, just open the last published `.json` file, and edit the `\"\"` value to `null`\r\n\r\nThen, confirm that applying the look succeeds without errors but with a warning regarding the `None` value when applying with this PR. For example in my test run it logged:\r\n\r\n```\r\n// Warning: ayon_maya.api.lib : Skipping setting |_GRP|cube_GEO.test with value 'None'\r\n```", + "id": "PR_kwDOMQ8b8s56Ps1m", + "labels": [ + { + "id": "LA_kwDOMQ8b8s8AAAABqmH60w", + "name": "type: bug", + "description": "Something isn't working", + "color": "FFA696" + }, + { + "id": "LA_kwDOMQ8b8s8AAAABtfdQMg", + "name": "sponsored", + "description": "This is directly sponsored by a client or community member", + "color": "FCD63D" + } + ], + "number": 89, + "title": "AY-6654 Look: Fix None values in collecting and applying attributes", + "url": "https://github.com/ynput/ayon-maya/pull/89" + }, + { + "body": "## Changelog Description\r\n\r\n\r\nFix name in settings to match with name of plug-in to ensure settings are actually applied\r\n\r\n## Additional info\r\n\r\n\r\nOriginally reported by @LiborBatek here: https://github.com/ynput/ayon-maya/pull/68#issuecomment-2288791598\r\n\r\n## Testing notes:\r\n\r\n1. Settings should adjust the extractor's defaults\r\n2. Disabling it in settings should hide the attributes from the publisher UI\r\n", + "id": "PR_kwDOMQ8b8s55oDx8", + "labels": [ + { + "id": "LA_kwDOMQ8b8s8AAAABqmH60w", + "name": "type: bug", + "description": "Something isn't working", + "color": "FFA696" + } + ], + "number": 77, + "title": "Fix settings for Maya USD Animation Extractor", + "url": "https://github.com/ynput/ayon-maya/pull/77" + }, + { + "body": "## Changelog Description\r\n\r\n\r\nFix pixel aspect ratio / device aspect ratio getting messed up for Arnold renderer on render settings reset.\r\n\r\nAdditionally:\r\n- This now applies the resolution from the task entity, not the folder entity.\r\n- This now also applies pixel aspect ratio as defined on the entity.\r\n\r\n## Additional info\r\n\r\n\r\nThis fixes a bug when resetting render resolution for Arnold where on reset the pixel/device aspect ratio would be oddly set with a pixel aspect ratio that is not 1.0.\r\n\r\nE.g. left is before, right is after resetting render settings **without this PR**\r\n![image](https://github.com/user-attachments/assets/1b36d70b-2490-47f0-8731-d1ce5b20dfe9)\r\n\r\nAfter this PR the pixel aspect ratio will now adhere to what is specified on the task entity.\r\n_This bug was only occurring if the current renderer render settings were reset for was actively Arnold (mtoa) renderer._\r\n\r\n## Testing notes:\r\n\r\n1. Resetting render settings should work for the different renderers and should set the resolution (and pixel aspect ratio correctly!)\r\n - [x] Arnold (mtoa)\r\n - [x] Redshift (should work if Arnold works because it uses same attributes as Arnold)\r\n - [x] V-Ray (may be good to check because it uses a custom render settings node!)\r\n - [ ] Renderman (should work if Arnold works because it uses same attributes as Arnold)\r\n\r\nNote that this is about **Set Render Settings** or the feature that it automatically does so on creating a render publish instance in the scene (enabled by default).\r\n\r\n![image](https://github.com/user-attachments/assets/ad8b0534-0921-4dc2-add9-eb276326030f)\r\n", + "id": "PR_kwDOMQ8b8s55L5zV", + "labels": [ + { + "id": "LA_kwDOMQ8b8s8AAAABqmH60w", + "name": "type: bug", + "description": "Something isn't working", + "color": "FFA696" + }, + { + "id": "LA_kwDOMQ8b8s8AAAABqmH62w", + "name": "type: enhancement", + "description": "Improvement of existing functionality or minor addition", + "color": "b9f29d" + }, + { + "id": "LA_kwDOMQ8b8s8AAAABtfdQMg", + "name": "sponsored", + "description": "This is directly sponsored by a client or community member", + "color": "FCD63D" + } + ], + "number": 75, + "title": "Improve applying render resolution and aspect ratio on render settings reset", + "url": "https://github.com/ynput/ayon-maya/pull/75" + }, + { + "body": "## Changelog Description\r\n\r\n\r\nOn Maya scene exports only include the relevant history for the selected nodes downstream and upstream and not upstream, and also their downstream descendant children.\r\n\r\n## Additional info\r\n\r\n\r\nNote: This may affect maya scene exports, camera rig exports and layout exports. However, I do feel this is a way more sensible default behavior on exports _with_ construction history enabled.\r\n\r\nWith this change, if you have a hierarchy like:\r\n```\r\ngrp/\r\n obj1\r\n obj2\r\n```\r\nAnd `obj1` is inside the instance then after this PR `obj2` is not included.\r\nBefore this PR all other descendents from upstream groups would be included, regardless of whether they were \"inputs\" to the `obj1`.\r\n\r\nAfter this PR, if `obj2` is an input connection to `obj1` (e.g. there are active constraints driving `obj1` or some other connections driving it) then `obj2` **will still be included.**\r\n\r\nAs such, only objects actively contributing to members of the instance will still be included in the output.\r\n\r\n## Testing notes:\r\n\r\n1. Recreate the aforementioned hierarchy from additional info.\r\n2. Publish `obj1` - it should not include `obj2`\r\n3. Now make a connection from `obj2` to `obj1` (e.g. translate connection)\r\n4. Now `obj2` should also be included in `obj2`.\r\n5. Now disconnect the connection, and key `obj1` transforms.\r\n6. The keys should be exported along just fine.", + "id": "PR_kwDOMQ8b8s542vNM", + "labels": [ + { + "id": "LA_kwDOMQ8b8s8AAAABqmH60w", + "name": "type: bug", + "description": "Something isn't working", + "color": "FFA696" + } + ], + "number": 71, + "title": "Maya Scene exports do not default to including nodes that not children of members", + "url": "https://github.com/ynput/ayon-maya/pull/71" + }, + { + "body": "## Changelog Description\r\n\r\n\r\nValidate unique names only within the instance not in full scene\r\n\r\n## Additional info\r\n\r\n\r\nThis is allowed:\r\n![image](https://github.com/user-attachments/assets/ce25d2aa-fa3a-4b25-b0ff-b58ebe7b6124)\r\n\r\nThis is not allowed:\r\n![image](https://github.com/user-attachments/assets/67b3099b-18a1-4779-ae1c-422887675ba8)\r\n\r\nThe validation only checks for member transforms that are included in the export instance.\r\n\r\n![image](https://github.com/user-attachments/assets/e6950101-1210-423b-afe8-6797c33ea5bf)\r\n\r\n## Testing notes:\r\n\r\nMake sure to enable the validator: `ayon+settings://maya/publish/ValidateUniqueNames/enabled`\r\n\r\n1. Create a scene with non-unique node names (e.g. see screenshots above).\r\n2. When both included in the instance it should not be allowed, \r\n3. Otherwise when just present elsewhere in the scene unrelated to the export it should be allowed.\r\n", + "id": "PR_kwDOMQ8b8s54uX2I", + "labels": [ + { + "id": "LA_kwDOMQ8b8s8AAAABqmH62w", + "name": "type: enhancement", + "description": "Improvement of existing functionality or minor addition", + "color": "b9f29d" + }, + { + "id": "LA_kwDOMQ8b8s8AAAABtfdQMg", + "name": "sponsored", + "description": "This is directly sponsored by a client or community member", + "color": "FCD63D" + } + ], + "number": 70, + "title": "Validate unique names only within the instance not in full scene", + "url": "https://github.com/ynput/ayon-maya/pull/70" + } +] diff --git a/tests/merged_pr_query_testing.json b/tests/merged_pr_query_testing.json new file mode 100644 index 0000000..000685a --- /dev/null +++ b/tests/merged_pr_query_testing.json @@ -0,0 +1,32 @@ +[ + { + "body": "\n# Memory usage check added\n\n## Summary\n\nGot a check for memory usage implemented\n\n## Root Cause Analysis\n\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)\n\n## Changelog\n\n* Add text file\n* Commit it the memory check\n* Fix no memory usage file\n\n## Testing Strategy\n\nTested all the way.\n\n## Checklist\n\n* [x] The fix has been locally tested\n* [x] New unit tests have been added to prevent future regressions\n* [x] The documentation has been updated if necessary\n", + "id": "PR_kwDONG2H-M6ADxBD", + "labels": [ + { + "id": "LA_kwDONG2H-M8AAAAByPb2-g", + "name": "enhancement", + "description": "New feature or request", + "color": "b9f29d" + } + ], + "number": 2, + "title": "Add mem file", + "url": "https://github.com/ynput/ayon-addon-action-testing/pull/2" + }, + { + "body": "\n# Date file added\n\n## Summary\n\nGot a date file included\n\n## Root Cause Analysis\n\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)\n\n## Changelog\n\n* Add date file\n* Commit it\n* Fix no date file\n\n## Testing Strategy\n\nTested all the way.\n\n## Checklist\n\n* [x] The fix has been locally tested\n* [x] New unit tests have been added to prevent future regressions\n* [x] The documentation has been updated if necessary\n", + "id": "PR_kwDONG2H-M6ADxAA", + "labels": [ + { + "id": "LA_kwDONG2H-M8AAAAByPb6PA", + "name": "bugfix", + "description": "Something got fixed", + "color": "f96713" + } + ], + "number": 1, + "title": "Add date file", + "url": "https://github.com/ynput/ayon-addon-action-testing/pull/1" + } + ] diff --git a/tests/pr_api_output.json b/tests/pr_api_output.json new file mode 100644 index 0000000..8f9d049 --- /dev/null +++ b/tests/pr_api_output.json @@ -0,0 +1,26 @@ +[ + { + "body": "# Bug Fix PR Template\r\n\r\n[ x] Feature/Enhancement
\r\n[ ] Bugfix
\r\n[ ] Documentation update
\r\n\r\n## Summary\r\n\r\n\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\n\r\n\r\n## Changes\r\n\r\n\r\n* Add more test\r\n* Was very important\r\n* Needed to add this here\r\n\r\n## Testing Strategy\r\n\r\n\r\n\r\n## Checklist\r\n\r\n* [ x] The fix has been locally tested\r\n* [ x] New unit tests have been added to prevent future regressions\r\n* [ x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\n", + "labels": [ + { + "id": "LA_kwDOMje8_88AAAABtOJ1Ig", + "name": "enhancement", + "description": "New feature or request", + "color": "b9f29d" + } + ], + "title": "Add more data" + }, + { + "body": "# Date file added\r\n\r\n## Summary\r\n\r\nSome awesome summary going on right here.\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\nDate file so absolutely needed.\r\n\r\n## Changes\r\n\r\n\r\n* Run a command\r\n* Pipe its output to a text file\r\n* Commit dem stuff\r\n\r\n## Testing Strategy\r\n\r\nnahhhhh\r\n\r\n## Checklist\r\n\r\n* [x] The fix has been locally tested\r\n* [x] New unit tests have been added to prevent future regressions\r\n* [x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\nNop", + "labels": [ + { + "id": "LA_kwDOMje8_88AAAABtOJ1Gw", + "name": "bugfix", + "description": "Something got fixed", + "color": "ff9195" + } + ], + "title": "Add date file" + } +] \ No newline at end of file diff --git a/tests/pr_api_output_missing_label.json b/tests/pr_api_output_missing_label.json new file mode 100644 index 0000000..2a97d4a --- /dev/null +++ b/tests/pr_api_output_missing_label.json @@ -0,0 +1,18 @@ +[ + { + "body": "# Bug Fix PR Template\r\n\r\n[ x] Feature/Enhancement
\r\n[ ] Bugfix
\r\n[ ] Documentation update
\r\n\r\n## Summary\r\n\r\n\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\n\r\n\r\n## Changes\r\n\r\n\r\n* Add more test\r\n* Was very important\r\n* Needed to add this here\r\n\r\n## Testing Strategy\r\n\r\n\r\n\r\n## Checklist\r\n\r\n* [ x] The fix has been locally tested\r\n* [ x] New unit tests have been added to prevent future regressions\r\n* [ x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\n", + "title": "Add more data" + }, + { + "body": "# Date file added\r\n\r\n## Summary\r\n\r\nSome awesome summary going on right here.\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\nDate file so absolutely needed.\r\n\r\n## Changes\r\n\r\n\r\n* Run a command\r\n* Pipe its output to a text file\r\n* Commit dem stuff\r\n\r\n## Testing Strategy\r\n\r\nnahhhhh\r\n\r\n## Checklist\r\n\r\n* [x] The fix has been locally tested\r\n* [x] New unit tests have been added to prevent future regressions\r\n* [x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\nNop", + "labels": [ + { + "id": "LA_kwDOMje8_88AAAABtOJ1Gw", + "name": "bug", + "description": "Something isn't working", + "color": "ff9195" + } + ], + "title": "Add date file" + } +] \ No newline at end of file diff --git a/tests/test_github_query.py b/tests/test_github_query.py index 2948f8d..1922ef0 100644 --- a/tests/test_github_query.py +++ b/tests/test_github_query.py @@ -1,171 +1,232 @@ +from typing import Any, Literal, List +import json import pytest -from unittest.mock import patch - -import github_query - -@pytest.fixture -def pr_api_output(): - return [ - { - "body": "# Bug Fix PR Template\r\n\r\n[ x] Feature/Enhancement
\r\n[ ] Bugfix
\r\n[ ] Documentation update
\r\n\r\n## Summary\r\n\r\n\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\n\r\n\r\n## Changes\r\n\r\n\r\n* Add more test\r\n* Was very important\r\n* Needed to add this here\r\n\r\n## Testing Strategy\r\n\r\n\r\n\r\n## Checklist\r\n\r\n* [ x] The fix has been locally tested\r\n* [ x] New unit tests have been added to prevent future regressions\r\n* [ x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\n", - "labels": [ - { - "id": "LA_kwDOMje8_88AAAABtOJ1Ig", - "name": "enhancement", - "description": "New feature or request", - "color": "b9f29d" - } - ], - "title": "Add more data" - }, - { - "body": "# Date file added\r\n\r\n## Summary\r\n\r\nSome awesome summary going on right here.\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\nDate file so absolutely needed.\r\n\r\n## Changes\r\n\r\n\r\n* Run a command\r\n* Pipe its output to a text file\r\n* Commit dem stuff\r\n\r\n## Testing Strategy\r\n\r\nnahhhhh\r\n\r\n## Checklist\r\n\r\n* [x] The fix has been locally tested\r\n* [x] New unit tests have been added to prevent future regressions\r\n* [x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\nNop", - "labels": [ - { - "id": "LA_kwDOMje8_88AAAABtOJ1Gw", - "name": "bugfix", - "description": "Something got fixed", - "color": "ff9195" - } - ], - "title": "Add date file" - } - ] - -@pytest.fixture -def pr_api_output_missing_label(): - return [ - { - "body": "# Bug Fix PR Template\r\n\r\n[ x] Feature/Enhancement
\r\n[ ] Bugfix
\r\n[ ] Documentation update
\r\n\r\n## Summary\r\n\r\n\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\n\r\n\r\n## Changes\r\n\r\n\r\n* Add more test\r\n* Was very important\r\n* Needed to add this here\r\n\r\n## Testing Strategy\r\n\r\n\r\n\r\n## Checklist\r\n\r\n* [ x] The fix has been locally tested\r\n* [ x] New unit tests have been added to prevent future regressions\r\n* [ x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\n", - "title": "Add more data" - }, - { - "body": "# Date file added\r\n\r\n## Summary\r\n\r\nSome awesome summary going on right here.\r\n\r\n## Root Cause Analysis\r\n\r\n[Issue Link](https://github.com/ynput/ci-testing/blob/develop/.github/ISSUE_TEMPLATE/bug_report.yml)
\r\nDate file so absolutely needed.\r\n\r\n## Changes\r\n\r\n\r\n* Run a command\r\n* Pipe its output to a text file\r\n* Commit dem stuff\r\n\r\n## Testing Strategy\r\n\r\nnahhhhh\r\n\r\n## Checklist\r\n\r\n* [x] The fix has been locally tested\r\n* [x] New unit tests have been added to prevent future regressions\r\n* [x] The documentation has been updated if necessary\r\n\r\n## Additional Notes\r\n\r\nNop", - "labels": [ - { - "id": "LA_kwDOMje8_88AAAABtOJ1Gw", - "name": "bug", - "description": "Something isn't working", - "color": "ff9195" - } - ], - "title": "Add date file" - } - ] - -@pytest.fixture -def minor_bump(): + +from src import conversion_logic + +@pytest.fixture +def pr_api_output() -> List[dict[str, Any]]: + with open("pr_api_output.json") as file: + return json.load(file) + +@pytest.fixture +def pr_api_output_missing_label() -> List[dict[str, Any]]: + with open("pr_api_output_missing_label.json") as file: + return json.load(file) + +@pytest.fixture +def major_bump() -> List[str]: + return ["epic"] + +@pytest.fixture +def major_bump_no_list() -> Literal['epic']: + return "epic" + +@pytest.fixture +def merged_pr_samples(): + with open("merged_pr_query.json") as file: + return json.load(file) + +@pytest.fixture +def changelog_markdown() -> str: + with open("formatted_changelog.md") as file: + return file.read() + +@pytest.fixture +def changelog_body() -> str: + with open("changelog.md") as file: + return file.read() + +@pytest.fixture +def changelog_description() -> List[str]: + return ['Some more information', '', '- Prototype loading of USD references into a Maya USD proxy while keeping it managed by the pipeline', '- Prototype loading of Maya references into a Maya USD proxy while keeping it managed by the pipeline'] + +@pytest.fixture +def minor_bump() -> list[str]: return ["feature", "enhancement"] @pytest.fixture -def patch_bump(): +def patch_bump() -> list[str]: return ["bugfix"] @pytest.fixture -def pr_labels_bug(): +def pr_labels_bug() -> list[str]: return ["bugfix"] @pytest.fixture -def pr_labels_enhancement(): +def pr_labels_enhancement() -> list[str]: return ["bugfix", "documentation", "feature", "enhancement"] @pytest.fixture -def pr_labels_wrong_labels(): +def pr_labels_epic() -> List[str]: + return ["bugfix", "documentation", "feature", "enhancement", "epic"] + +@pytest.fixture +def pr_labels_wrong_labels() -> list[str]: return ["documentation", "wontfix"] @pytest.fixture -def pr_labels_empty_list(): +def pr_labels_empty_list() -> list[Any]: return [] @pytest.fixture -def pr_labels_none(): +def pr_labels_none() -> None: return None @pytest.fixture -def csv_string_spaces(): +def csv_string_spaces() -> Literal['bugfix, enhancement, feature']: return "bugfix, enhancement, feature" @pytest.fixture -def csv_string_no_spaces(): +def csv_string_no_spaces() -> Literal['bugfix,enhancement,feature']: return "bugfix,enhancement,feature" @pytest.fixture -def csv_string_no_spaces(): - return "bugfix,enhancement,feature" +def csv_string_no_comma() -> Literal['bugfix']: + return "bugfix" @pytest.fixture -def csv_string_no_comma(): - return "bugfix" +def csv_string_empty() -> Literal['']: + return "" @pytest.fixture -def csv_string_no_comma(): - return "bugfix" +def changelog_label_list() -> list[str]: + return ["type: enhancement", "type: bug", "type: maintenance"] @pytest.fixture -def csv_string_empty(): - return "" +def changelog_exclude_label_list() -> List[str]: + return ["sponsored"] # Get PR Label test-cases -def test_get_labels(pr_api_output): - labels = github_query.get_labels(pr_data=pr_api_output) +def test_get_labels(pr_api_output: List[dict[str, Any]]) -> None: + labels: List[str] = conversion_logic.filter_unique_labels(pr_data=pr_api_output) assert isinstance(labels, list) assert set(labels) == {"bugfix", "enhancement"} -def test_get_labels_missing_input(pr_api_output_missing_label): - labels = github_query.get_labels(pr_data=pr_api_output_missing_label) +def test_get_labels_missing_input(pr_api_output_missing_label: List[dict[str, Any]]) -> None: + labels: List[str] = conversion_logic.filter_unique_labels(pr_data=pr_api_output_missing_label) assert labels == [] # Convert repo label list -def test_csv_string_to_list_spaces(csv_string_spaces): - string_list = github_query.csv_string_to_list(csv_string_spaces) +def test_csv_string_to_list_spaces(csv_string_spaces: Literal['bugfix, enhancement, feature']) -> None: + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_spaces) + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_spaces) assert string_list == ["bugfix", "enhancement", "feature"] -def test_csv_string_to_list_no_spaces(csv_string_no_spaces): - string_list = github_query.csv_string_to_list(csv_string_no_spaces) +def test_csv_string_to_list_no_spaces(csv_string_no_spaces: Literal['bugfix,enhancement,feature']) -> None: + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_no_spaces) + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_no_spaces) assert string_list == ["bugfix", "enhancement", "feature"] -def test_csv_string_to_list_no_comma(csv_string_no_comma): - string_list = github_query.csv_string_to_list(csv_string_no_comma) +def test_csv_string_to_list_no_comma(csv_string_no_comma: Literal['bugfix']) -> None: + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_no_comma) + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_no_comma) assert string_list == ["bugfix"] -def test_csv_string_to_list_empty(csv_string_empty): - string_list = github_query.csv_string_to_list(csv_string_empty) +def test_csv_string_to_list_empty(csv_string_empty: Literal['']) -> None: + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_empty) + string_list: List[str] = conversion_logic.csv_string_to_list(csv_string_empty) assert string_list == [] # Version Increment test-cases -def test_get_version_increment_patch(minor_bump, patch_bump, pr_labels_bug): - increment = github_query.get_version_increment(patch_bump_list=patch_bump, minor_bump_list=minor_bump, pr_label_list=pr_labels_bug) +def test_get_version_increment_patch(minor_bump: List[str], patch_bump: List[str], pr_labels_bug: List[str]) -> None: + increment = conversion_logic.get_version_increment( + pr_label_list=pr_labels_bug, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + ) assert increment == "patch" -def test_get_version_increment_minor(minor_bump, patch_bump, pr_labels_enhancement): - increment = github_query.get_version_increment(patch_bump_list=patch_bump, minor_bump_list=minor_bump, pr_label_list=pr_labels_enhancement) +def test_get_version_increment_minor(minor_bump: List[str], patch_bump: List[str], pr_labels_enhancement: List[str]) -> None: + increment = conversion_logic.get_version_increment( + pr_label_list=pr_labels_enhancement, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + ) assert increment == "minor" -def test_get_version_increment_wrong_labels(minor_bump, patch_bump, pr_labels_wrong_labels): - increment = github_query.get_version_increment(patch_bump_list=patch_bump, minor_bump_list=minor_bump, pr_label_list=pr_labels_wrong_labels) +def test_get_version_increment_major(minor_bump: List[str], patch_bump: List[str], major_bump: List[str], pr_labels_epic: List[str]) -> None: + increment = conversion_logic.get_version_increment( + pr_label_list=pr_labels_epic, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + major_bump_list=major_bump, + ) + + assert increment == "major" + +def test_get_version_increment_wrong_labels(minor_bump: List[str], patch_bump: List[str], pr_labels_wrong_labels: List[str]): + increment = conversion_logic.get_version_increment( + pr_label_list=pr_labels_wrong_labels, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + ) assert increment == "" -def test_get_version_increment_none(minor_bump, patch_bump, pr_labels_none): - increment = github_query.get_version_increment(patch_bump_list=patch_bump, minor_bump_list=minor_bump, pr_label_list=pr_labels_none) +def test_get_version_increment_none(minor_bump: List[str], patch_bump: List[str], pr_labels_none: None) -> None: + increment = conversion_logic.get_version_increment( + pr_label_list=pr_labels_none, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + ) assert increment == "" -def test_get_version_increment_ampty_list(minor_bump, patch_bump, pr_labels_empty_list): - increment = github_query.get_version_increment(patch_bump_list=patch_bump, minor_bump_list=minor_bump, pr_label_list=pr_labels_empty_list) +def test_get_version_increment_empty_list(minor_bump: List[str], patch_bump: List[str], pr_labels_empty_list: List[Any]) -> None: + increment = conversion_logic.get_version_increment( + pr_label_list=pr_labels_empty_list, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + ) assert increment == "" + +def test_get_version_increment_no_list(minor_bump: List[str], patch_bump: List[str], major_bump_no_list: Literal['epic'], pr_labels_epic: List[str]) -> None: + with pytest.raises(ValueError, match="must be a list"): + conversion_logic.get_version_increment( + pr_label_list=pr_labels_epic, + patch_bump_list=patch_bump, + minor_bump_list=minor_bump, + major_bump_list=major_bump_no_list, + ) + + +# Changelog test-cases + +def test_filter_changes_per_label_types(merged_pr_samples: List[dict[str, str]], changelog_label_list: List[str]) -> None: + filtered_pr_list: List[conversion_logic.Changelog] = conversion_logic.filter_changes_per_label(pr_data=merged_pr_samples, changelog_label_list=changelog_label_list) + + assert all(isinstance(changelog, conversion_logic.Changelog) for changelog in filtered_pr_list) + +def test_get_changelog_description(changelog_body: str, changelog_description: str) -> None: + filtered_changelog: List[str] = conversion_logic.get_changelog_description(changelog_body) + + assert filtered_changelog == changelog_description + +def test_format_changelog_markdown(merged_pr_samples: List[dict[str, str]], changelog_label_list: List[str], changelog_markdown: str) -> None: + filtered_pr_list: List[conversion_logic.Changelog] = conversion_logic.filter_changes_per_label(pr_data=merged_pr_samples, changelog_label_list=changelog_label_list) + changelog_result: str = conversion_logic.format_changelog_markdown(changes=filtered_pr_list, changelog_label_list=changelog_label_list) + + print(changelog_result) + assert changelog_result == changelog_markdown + +def test_format_changelog_markdown_no_data(changelog_label_list: List[str]) -> None: + filtered_pr_list: List[conversion_logic.Changelog] = conversion_logic.filter_changes_per_label(pr_data=[], changelog_label_list=changelog_label_list) + changelog_result: str = conversion_logic.format_changelog_markdown(changes=filtered_pr_list, changelog_label_list=changelog_label_list) + + assert changelog_result == "# Changelog\n"