-
Notifications
You must be signed in to change notification settings - Fork 277
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
Add commits differentiation logic for incremental build #4207
Conversation
Signed-off-by: Zelin Hao <zelinhao@amazon.com>
Signed-off-by: Zelin Hao <zelinhao@amazon.com>
Signed-off-by: Zelin Hao <zelinhao@amazon.com>
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #4207 +/- ##
==========================================
- Coverage 93.17% 93.16% -0.01%
==========================================
Files 188 189 +1
Lines 5920 5973 +53
==========================================
+ Hits 5516 5565 +49
- Misses 404 408 +4 ☔ View full report in Codecov by Sentry. |
Signed-off-by: Zelin Hao <zelinhao@amazon.com>
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.
Taking a first pass at this PR.
Thanks @zelinh . Is this PR a 2 part? Wondering what are we doing with plugins that needs to be rebuild? The code for incremental build in run_build.py
is only listing the diffs as of now. Confused as what difference is it making from build point of view.
def commits_diff(self, input_manifest: InputManifest) -> List[str]: | ||
build_manifest_path = os.path.join(self.distribution, "builds", input_manifest.build.filename, "manifest.yml") | ||
if not os.path.exists(build_manifest_path): | ||
logging.info("Previous build manifest is not exists. Rebuilding Core.") |
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.
nit
logging.info("Previous build manifest is not exists. Rebuilding Core.") | |
logging.info("Previous build manifest does not exist. Rebuilding Core.") |
Also wondering why are we only re-building core? Won't that write to the directory and replace all the existing build artifacts too?
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.
It would rebuilding all components since core changed according to the logic in below.
if args.incremental: | ||
buildIncremental = BuildIncremental(manifest, args.distribution) | ||
list_of_updated_plugins = buildIncremental.commits_diff(manifest) | ||
logging.info(f"Plugins for incremental build: {buildIncremental.rebuild_plugins(list_of_updated_plugins, manifest)}") | ||
return 0 |
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.
Pointing the exact question from the overview here: Wondering what difference is this making in overall build.
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.
Yeah as I stated in the description of this issue, these additions in run_build.py
is a placeholder to further implementation on incremental build. For this PR, it's intended for getting a list of components for rebuild.
Signed-off-by: Zelin Hao <zelinhao@amazon.com>
|
||
# Given input manifest and return a list of what components changed and added. | ||
def commits_diff(self, input_manifest: InputManifest) -> List[str]: | ||
build_manifest_path = os.path.join(self.distribution, "builds", input_manifest.build.filename, "manifest.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 am assuming we will be downloading the build-manifest and storing it in the path mentioned before this logic executes?
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.
In the scope of the workflow on python side, we would assume we already have the builds
folder along with build-manifest in local directory. We would need to download this entire builds
folder on the CI level when we are running on Jenkins.
return [input_manifest.build.name.replace(" ", "-")] | ||
previous_build_manifest = BuildManifest.from_path(build_manifest_path) | ||
stable_input_manifest = input_manifest.stable() | ||
if previous_build_manifest.build.version != stable_input_manifest.build.version: |
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 this check is here?
Could there be a case where OS version in the previous build manifest differ from that in input manifest?
If yes, can you please give an example.
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 came out of my mind when I was testing on local. When we are building artifacts in local, we don't have any sub-folder for different version. All built artifacts stored in the same directory following this pattern: <architecture>/builds/<opensearch/opensearch-dashboards>/<plugins/... or manifest.yml>
. Even we built input manifests of different versions. Latter build-manifest will overwrite the previous one but all artifacts would all be in place without any of removal.
So I believe at least we need to check we are incrementally building the same version artifacts.
|
||
# Given updated plugins and look into the depends_on of all components to finalize a list of rebuilding components. | ||
def rebuild_plugins(self, changed_plugins: List, input_manifest: InputManifest) -> List[str]: | ||
if not changed_plugins: |
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.
May be add this check in the run_build.py
and call this method only if you have plugins to rebuild as the method name suggests.
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 sure. This would be considered in the current implementation on the building process for incremental build.
queue = changed_plugins | ||
rebuild_list = [] | ||
|
||
rebuild_list.append("OpenSearch-Dashboards") if input_manifest.build.filename == "opensearch-dashboards" else rebuild_list |
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.
Did not understand this.
Aren't we supposed to rebuild everything if core is present in the changed_plugins
list at line 49?
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 for OSD plugins to rebuild, we need OSD to be rebuilt again?
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. OSD doesn't have any those built-tool available just like OS. Every time we rebuild any of dashboards plugin, we have to build OSD core.
rebuild_list.append("OpenSearch-Dashboards") if input_manifest.build.filename == "opensearch-dashboards" else rebuild_list | ||
while queue: | ||
plugin = queue.pop(0) | ||
rebuild_list.append(plugin) if plugin not in rebuild_list else rebuild_list |
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 this?
Is there a possibility to have duplicates in the passed changed_plugins
list?
If yes, shouldn't that be handled before it is being passed here.
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 to make sure there is no duplicate in the rebuild_list
which we would return.
@@ -41,6 +42,12 @@ def main() -> int: | |||
|
|||
output_dir = BuildOutputDir(manifest.build.filename, args.distribution).dir | |||
|
|||
if args.incremental: |
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.
please add test.
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 a placeholder for the next PR and it's just logging a list of plugins for rebuilding. I have complete tests for all those functions within buildIncremental
class.
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.
It still is part of the code flow and should be tested, if not in this PR then in subsequent PRs.
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.
Will absolutely add tests in my following PR.
Signed-off-by: Zelin Hao <zelinhao@amazon.com>
Description
This is a milestone for the incremental build. Two methods in the
run_incremental.py
class are used to find whatever components have updated commits from previous build and find whatever plugins depend on them according to the input manifest.Those additions in
run_build.py
is a placeholder to further implementation on incremental build.Issues Resolved
#4201
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.