-
Notifications
You must be signed in to change notification settings - Fork 107
Kayode local yaml config dev #2646
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
base: main
Are you sure you want to change the base?
Conversation
|
Build succeeded. ✔️ pre-commit SUCCESS in 2m 01s |
LecrisUT
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a general note, I would recommend to view PRs not as a complete implementation of an issue, and try to implement everything from the start, particularly if you are not familiar with all the intricacies of a project. Instead try to break it down into more minimal pieces and evolve it together with the reviewer comments, and make comments whenever you are uncertain about an issue or design.
And also I believe you are a GSOC or outreachy or something along those lines. I would recommend to make use of the opportunity to learn how to navigate an open source project in general, how to approach resolving issues, etc. If you have questions, take the opportunity to ask the mentors and people in the community directly, instead of LLM tools.
packit/constants.py
Outdated
|
|
||
| PROJECT_LOCAL_CONFIG_FILE = ".packitLocal.yaml" | ||
|
|
||
| ALLOWED_LOCAL_OVERRIDES = {"debug", "fas_user", "fas_password", "plans"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't add any of the keys available in the User config file, until there appears to be a need for it. These are also a completely different schema to the project config files which would make the implementation quite complicated.
| "packit.yml", | ||
| } | ||
|
|
||
| PROJECT_LOCAL_CONFIG_FILE = ".packitLocal.yaml" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the configuration for the CONFIG_FILE_NAMES, it should be able to handle the different naming schemas as above. I would try instead to reuse the logic of that variable and alter the path by adding a suffix to the filenames being tested. See packit.config.package_config.find_packit_yaml.
packit/config/config.py
Outdated
| project_local_config = cls.get_project_local_config() | ||
| if project_local_config: | ||
| validated_config = cls._validate_project_local_config(project_local_config) | ||
| loaded_config = cls._merge_configs(loaded_config, validated_config) | ||
| logger.debug("Merged project and local yaml config overrides") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not where we would want to alter. This would allow user-configs to be overridden, but we would rather want the project-configs to be overridden instead. That is located in
packit/packit/config/package_config.py
Lines 285 to 289 in fdcdf3a
| def find_packit_yaml( | |
| *directory: Union[Path, str], | |
| try_local_dir_first: bool = False, | |
| try_local_dir_last: bool = False, | |
| ) -> Path: |
This of course also depends a lot on what is the usecase of #1910 and we should figure out in the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @LecrisUT , looking at this a second time, I don't think we would want to alter here. Reason being that the method is used for finding the packit.yaml file, I think we should separate the logic of finding the local user config. I think the change should be made here instead:
packit/packit/config/package_config.py
Line 382 in fdcdf3a
| def get_local_package_config( |
So we find and load the two configs separately, then merge them here before final parsing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes and no. Yes, the logic of getting the local/user config file would be outside at the caller of find_packit_yaml. But, no, you would want to alter that function, because that is the part where the various CONFIG_FILE_NAMES are being tested, and you would want to have the same logic used, except for appending/prepending something to the file name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite understand. The logic of trying various CONFIG_FILE_NAMES is at the point of getting the user config right? That's what the find_packit_yaml method does. And we agree that the logic of getting the local user config should be separate. If these are true then I don't see the need for a change to this method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic of trying various CONFIG_FILE_NAMES is at the point of getting the user config right?
It is not specific to user config, project config uses it also 1. There is package_config.find_packit_yaml and Config.get_user_config.
Footnotes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree with you, but in the case of this local user config that we're implementing here, the CONFIG_FILE_NAMES would change to something like:
LOCAL_USER_CONFIG_FILE_NAMES = { ".packitLocal.yaml", ".packitLocal.yml", "packitLocal.yaml", "packitLocal.yml", }
That's why I think it should be separate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or I could just introduce a flag into the find_packit_yaml method argument that would be used to specifically check for only packitLocal.yaml files if that is the case, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or I could just introduce a flag into the find_packit_yaml method argument that would be used to specifically check for only packitLocal.yaml files if that is the case, what do you think?
Yes, that was what I was referring to (specifically a kwarg where you would pass "Local" or otherwise be a default ""). Specifically, you just need to alter config_file_name(_full) in
packit/packit/config/package_config.py
Lines 329 to 330 in fdcdf3a
| for config_file_name in CONFIG_FILE_NAMES: | |
| config_file_name_full = config_dir / config_file_name |
Here's a snippet to get you inspired
>>> from pathlib import Path
>>> path = Path("/path/to/.abc.def")
>>> path.with_name(f"{path.stem}XYZ{path.suffix}")
PosixPath('/path/to/.abcXYZ.def')I don't have any preference on how to tackle this, you can use the string directly to manipulate the file name
>>> ".abc.def".rsplit(".",1)
['.abc', 'def']There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright then, thank you
packit/config/config.py
Outdated
| return Proxy(partial(self._get_project, url, required, get_project_kwargs)) | ||
|
|
||
| @classmethod | ||
| def get_project_local_config(cls) -> dict: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these I don't think are transferable to packit.config.package_config.find_packit_yaml. You might want to re-implement some of it, but it would be somewhere around the caller part.
| @click.option( | ||
| "--clean-before/--no-clean-before", | ||
| default=False, | ||
| help="Run 'tmt clean --all' before starting the test (default: disabled).", | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not check what the discussions were during the implementation of this feature, I might need to give it a review. Is it all in #2632?
This option specifically, I do not see a reason to expose, and it is a different PR to be discussed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kayodegigz you need to rebase your PR. Most of the Lecris comments are related with your PR being outdated (or based on the wrong branch).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @majamassarini , I have rebased
packit/cli/init_local_yaml.py
Outdated
| @click.command( | ||
| "init-local-config", | ||
| context_settings=get_context_settings(), | ||
| short_help="Creates a localyaml config file for and ensures it's not version controlled", | ||
| ) | ||
| @pass_config | ||
| def init_local_yaml(config): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the issue, let's deffer this.
| target: Optional[str] = "fedora:rawhide", | ||
| rpm_paths: Optional[list[str]] = None, | ||
| run_all: bool = False, | ||
| rpm_paths: Optional[list[Path]] = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as in the cli counterpart of this.
| class LocalTestUtils: | ||
| @staticmethod | ||
| def _build_tmt_cmd( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably part of the other comments about splitting this feature to a different PR.
But to quickly note something, the LocalTestUtils has no meaning when all the functions are static. It should be plain functions instead. Use classes if:
- You want to inherit and override some implementations (in which case
classmethodis a more pythonic elegant way of designing it) - You need to instantiate an object with different parameters (in which case you use plain methods)
| class TestBuildTmtCmd: | ||
| """Test cases for _build_tmt_cmd function""" | ||
|
|
||
| def test_basic_command_structure(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Afaict, packit doesn't use class-based organization of tests. Use fixtures and plain function-based tests unless instructed otherwise by the core packit team.
| # SPDX-License-Identifier: MIT | ||
|
|
||
| from pathlib import Path | ||
| from unittest.mock import patch |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
packit uses pytest not unittest. See what fixtures are available either from the packit tests, pytest directly, or any other dependencies that are being used. It might be faster to state how you need to prepare the more complicated tests and then we can point you to some fixtures that you can try to use.
Do not rely on any suggestions from something like an LLM. It would most likely re-implement a lot of things that are already present in the code. Just ask us about it, we would be slower at giving you an answer, but we would be giving you that answer at review time anyway, so it would be a lot faster if you ask any of us directly, maybe as a quick question in the matrix room.
|
Build failed. ✔️ pre-commit SUCCESS in 2m 17s |
packit/cli/init_local_yaml.py
Outdated
| @pass_config | ||
| def init_local_yaml(config): | ||
| """Initialize packit-local yaml configuration file.""" | ||
| config_path = Path(".packitLocal.yaml") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how I feel about the config name, but I guess that can be easily adjusted.
Also I don't have a good suggestion for naming it, not to mention how convoluted this is becoming.
packit/cli/init_local_yaml.py
Outdated
| # Authentication (optional - overrides ~/.config/packit.yaml) | ||
| # authentication: | ||
| # github.com: | ||
| # token: YOUR_TOKEN |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that this is the exact goal of this feature, and also I have a feeling that if you go in this direction, you might complicate this issue by a lot for yourself.
If I understood correctly, the aim was to provide a way to configure Packit jobs that can be run only locally.
packit/cli/init_local_yaml.py
Outdated
| else: | ||
| with open(gitignore_path, "w") as f: | ||
| f.write(f"# Packit local config (local only overrides)\n{localYamlFile}\n") | ||
| click.echo(f"Created .gitignore with {localYamlFile}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Careful here, this branch doesn't imply that the current working directory is even version-controlled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| # # Copyright Contributors to the Packit project. | ||
| # # SPDX-License-Identifier: MIT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Why are you commenting out even the comments?
- Why are you even commenting it out?
| f"Allowed keys are: {', '.join(sorted(ALLOWED_LOCAL_OVERRIDES))}", | ||
| ) | ||
| return validated | ||
| # @classmethod |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just an FYI, as long as you don't alter the history in the git, you are able to recover any changes, i.e., there's no need to comment out code, if you don't need it, just delete it.
| *directory, | ||
| try_local_dir_first=True, | ||
| try_local_dir_last=False, | ||
| suffix="Local", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a feeling that this is a pretty good candidate for extending the part of the user config, so it's possible to configure this. You have prepared it pretty well for that.
| local_loaded_config = load_packit_yaml(config_file_path=local_config_file_name) | ||
| local_loaded_config = validate_project_local_config(local_loaded_config) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two lines don't make much sense type-wise, i.e., they are correct, Python allows it, but it doesn't read very well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm you think I should just assign to another variable altogether? I did that because the second method would also return a dict, just a cleaned up one.
| def merge_configs(base: dict, override: dict) -> dict: | ||
| """ | ||
| Deep merge override config into base config. | ||
| Override values take precedence. | ||
| """ | ||
| from copy import deepcopy | ||
|
|
||
| result = deepcopy(base) | ||
|
|
||
| for key, value in override.items(): | ||
| if key in result and isinstance(result[key], dict) and isinstance(value, dict): | ||
| result[key] = merge_configs(result[key], value) | ||
| else: | ||
| result[key] = value | ||
|
|
||
| return result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This definitely needs to be covered by tests. Not for the sake of testing, but for the sake of defining the expected behavior.
packit/constants.py
Outdated
| LOCAL_USER_CONFIG_FILE_NAMES = { | ||
| ".packitLocal.yaml", | ||
| ".packitLocal.yml", | ||
| "packitLocal.yaml", | ||
| "packitLocal.yml", | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand why do you hard-code the filenames here, but at the same time you allow the “middle” part to be customized as part of the interface.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was an oversight, I forgot to remove, sorry.
3fac935 to
4651848
Compare
|
Build failed. ✔️ pre-commit SUCCESS in 2m 01s |
|
Build failed. ✔️ pre-commit SUCCESS in 2m 01s |
|
hi @kayodegigz! Do you plan to continue working on this? |
TODO:
packit/packit.dev.Fixes
Related to
Merge before/after
RELEASE NOTES BEGIN
Packit now supports automatic ordering of ☕ after all checks pass.
RELEASE NOTES END