Smart CI POC (#19825)

* Try using a custom action directly from repo

* Run smart CI under ubuntu-latest

* Set output + add a sample step

* Update linux.yml

* Add components.yml

* Add some conditions

* Just to check if reference to "needs" work in job context

* Update linux.yml

* More example cases

* Dummy change to CPU

* Fix typo

* Fix SAMPLES_AFFECTED variable

* Use more correct dependents key

* Fighting with messy GHA conditions

* No brackets and no double quotes in conditions

* Revert "Dummy change to CPU"

This reverts commit 4eae09e5b5.

* Use refactored action

* Move action implementation to openvino repo

* Extend components.yml config

* Update labeler.yml

* Dummy change to TF FE

* Fix indentation

* Add missing needs

* Add missing records

* Allow missing records for components in validation

* install_openvino_dependencies as a separate step for Python_Unit_Tests

* Improve config validation

* Revert "Dummy change to TF FE"

This reverts commit 01190864d1.

* Dummy change to model hub tests

* Update CPU component config

* Dummy change to Python API

* Dummy change to Python API

* Revert "Dummy change to Python API"

This reverts commit 3fce0bb3fb.

* Dummy change to Python API

* Simplify conditions. Cover "no components changed" case

* Update components.yml

* Update .gitignore

* Revert "Dummy change to Python API"

This reverts commit e57ea9852c.

* Fix dependencies scopes

* Add simple unit tests for smart ci functionality

* Revert "Dummy change to model hub tests"

This reverts commit c3d6837e22.

* Use ghapi module with permissive license

* Cover install_build_dependencies.sh script by labeler

* More labels

* Use ghapi. Apply review comments

* Enable dot files to be matched by labeler

* Warning instead of error in artifacts upload where smart ci is enabled

* Fix master merge

* Fix condition for TF FE common tests

* Fix condition for Pytorch FE tests

* Remove condition for pytorch model tests

* Allow any label as a component

* Refactor tests log handling

* Allow any defined label as a component

* Rearrange config structure. Fill the config with actual data

* Run full scope on changes to non-matching files

* Add missing conditions

---------

Co-authored-by: Ilya Lavrenov <ilya.lavrenov@intel.com>
This commit is contained in:
Alina KladievaandIlya Lavrenov authored and GitHub committed 2023-11-09 11:38:58 +04:00
1 parent 6e073b1165
commit 000966660c
8 files changed
+798 -10

No files matched your search

+86
View File
@@ -0,0 +1,86 @@
name: "Smart CI action"
description: "Returns product components affected by PR or commit"
inputs:
repository:
description: "GitHub repository"
required: true
repo_token:
description: "Token for access to GitHub repository"
required: true
pr:
description: "GitHub PR number. If not set - commit is used"
required: false
commit_sha:
description: "GitHub commit hash. Used if no PR number is set"
required: false
component_pattern:
description: "Pattern to extract component name from PR label. If not set, any label is considered a component name"
required: false
labeler_check_name:
description: "Name of the labeler check"
required: false
default: "triage"
components_config:
description: "Path to components configuration file"
required: false
default: ".github/components.yml"
components_config_schema:
description: "Path to the schema file for components configuration"
required: false
default: ".github/actions/smart-ci/components_schema.yml"
labeler_config:
description: "Path to labeler configuration file"
required: false
default: ".github/labeler.yml"
outputs:
all_components:
description: "All components listed in configuration"
value: ${{ steps.smart_ci.outputs.all_components }}
affected_components:
description: "Affected components to run validation for and their validation scope"
value: ${{ steps.smart_ci.outputs.affected_components }}
runs:
using: "composite"
steps:
- name: Wait for labeler to finish
uses: lewagon/wait-on-check-action@v1.3.1
if: ${{ github.event_name == 'pull_request' }}
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: ${{ inputs.labeler_check_name }}
repo-token: ${{ inputs.repo_token }}
wait-interval: 10
- name: checkout components file
uses: actions/checkout@v4
with:
sparse-checkout: .github/components.yml
sparse-checkout-cone-mode: false
- name: Install Python dependencies
uses: py-actions/py-dependency-install@v4
with:
path: "${{ github.action_path }}/requirements.txt"
update-setuptools: "false"
update-wheel: "false"
- name: Test functionality
run: |
python ${{ github.action_path }}/smart_ci_test.py
shell: bash
- name: Smart CI
id: smart_ci
run: |
python ${{ github.action_path }}/smart_ci.py \
$([[ -n "${{ inputs.pr }}" ]] && echo '--pr ${{ inputs.pr }}' || echo '-s ${{ inputs.commit_sha }}') \
-r ${{ inputs.repository }} \
-p "${{ inputs.component_pattern }}" \
-c "${{ inputs.components_config }}" \
-m "${{ inputs.components_config_schema }}" \
-l "${{ inputs.labeler_config }}"
shell: bash
env:
GITHUB_TOKEN: ${{ inputs.repo_token }}
@@ -0,0 +1,35 @@
# YAML schema for Smart CI configuration file components.yml (see https://json-schema.org)
definitions:
component_name:
type: string
pattern: "^[a-zA-Z_][a-zA-Z0-9_]*$"
component_data:
type: object # dict
additionalProperties: false
properties:
cmake:
type: array
uniqueItems: true
items:
'$ref': '#/definitions/component_name'
revalidate:
type: array
uniqueItems: true
items:
'$ref': '#/definitions/component_name'
build:
type: array
uniqueItems: true
items:
'$ref': '#/definitions/component_name'
propertyNames: # Validates component names
'$ref': '#/definitions/component_name'
patternProperties:
".*": # Component (name validated via propertyNames)
'$ref': '#/definitions/component_data'
additionalProperties: false
@@ -0,0 +1,3 @@
ghapi~=1.0.4
pyyaml~=6.0.1
jsonschema~=4.19.1
+197
View File
@@ -0,0 +1,197 @@
import os
import re
import argparse
import yaml
import json
import jsonschema
import logging
from pathlib import Path
from ghapi.all import GhApi
class ComponentConfig:
FullScope = {'build', 'test'}
ScopeKeys = {'build', 'revalidate'}
def __init__(self, config: dict, schema: dict, all_possible_components: set):
self.config = config
self.log = logging.getLogger(self.__class__.__name__)
self.all_defined_components = set(self.config.keys()) # already defined in components.yml
self.all_possible_components = all_possible_components # can be added to components.yml (based on labeler.yml)
self.validate(schema, all_possible_components)
def validate(self, schema: dict, all_possible_components: set) -> None:
"""Validates syntax of configuration file"""
jsonschema.validate(self.config, schema)
invalid_components = self.all_defined_components.difference(all_possible_components)
if invalid_components:
error_msg = f"components are invalid: " \
f"{invalid_components} are not listed in labeler config: {all_possible_components}"
raise jsonschema.exceptions.ValidationError(error_msg)
for component_name, data in self.config.items():
dependent_components = set(data.get('dependent_components', dict()).keys()) if data else set()
invalid_dependents = dependent_components.difference(all_possible_components)
if invalid_dependents:
error_msg = f"dependent_components of {component_name} are invalid: " \
f"{invalid_dependents} are not listed in components config: {all_possible_components}"
raise jsonschema.exceptions.ValidationError(error_msg)
def get_affected_components(self, changed_components_names: set) -> dict:
"""Returns changed components, their dependencies and validation scope for them"""
affected_components = dict()
# If some changed components were not defined in config or no changed components detected at all,
# run full scope for everything (just in case)
changed_not_defined_components = changed_components_names.difference(self.all_defined_components)
if not changed_components_names or changed_not_defined_components:
self.log.info(f"Changed components {changed_not_defined_components} are not defined in smart ci config, "
"run full scope")
affected_components.update({name: self.FullScope for name in self.all_possible_components})
return affected_components
# Else check changed components' dependencies and add them to affected
for name in changed_components_names:
component_scopes = {k: v for k, v in self.config.get(name, dict()).items() if k in self.ScopeKeys}
for key, dependents in component_scopes.items():
for dep_name in dependents:
affected_components[dep_name] = affected_components.get(dep_name, set())
scope = self.FullScope if key == 'revalidate' else {key}
affected_components[dep_name] = affected_components[dep_name].union(scope)
if not component_scopes:
self.log.info(f"Changed component '{name}' doesn't have {self.ScopeKeys} keys in components config. "
f"Assuming that it affects everything, the whole scope will be started")
for dep_name in self.all_possible_components:
affected_components[dep_name] = self.FullScope
# If the component was explicitly changed, run full scope for it
affected_components.update({name: self.FullScope for name in changed_components_names})
self.log.info(f"Changed components with dependencies: {affected_components}")
# For non-affected components that are not defined in config - run full scope
affected_components.update({name: self.FullScope for name in self.all_possible_components
if name not in self.all_defined_components})
return affected_components
def get_static_data(self, components_names: set, data_key: str, default: str = None) -> dict:
"""Returns requested generic static data defined for each component"""
data = {name: self.config[name].get(data_key, default) for name in components_names}
return data
def component_name_from_label(label: str, component_pattern: str = None) -> str:
"""Extracts component name from label"""
component = label
if component_pattern:
matches = re.findall(component_pattern, label)
component = matches[0] if matches else None
component = component.replace(' ', '_') if component else None
return component
def get_changed_component_names(pr, all_possible_components: set, component_pattern: str = None) -> set:
"""Returns component names changed in a given PR"""
components = set()
for label in pr.labels:
component = component_name_from_label(label.name, component_pattern)
if component:
components.add(component)
elif label.name in all_possible_components:
# Allow any labels defined explicitly in labeler config as components
# (predefined labels, such as "do not merge", are still ignored)
components.add(label.name)
return components
def parse_args():
parser = argparse.ArgumentParser(description='Returns product components changed in a given PR or commit')
parser.add_argument('--pr', type=int, required=False, help='PR number. If not set, --commit is used')
parser.add_argument('-s', '--commit-sha', required=False, help='Commit SHA. If not set, --pr is used')
parser.add_argument('-r', '--repo', help='GitHub repository')
parser.add_argument('-p', '--pattern', default=None, help='Pattern to extract component name from PR label. '
'If not set, any label is considered a component name')
parser.add_argument('-c', '--components-config', default='.github/components.yml',
help='Path to config file with info about dependencies between components')
parser.add_argument('-m', '--components-config-schema', default='.github/actions/smart-ci/components_schema.yml',
help='Path to the schema file for components config')
parser.add_argument('-l', '--labeler-config', default='.github/labeler.yml',
help='Path to PR labeler config file')
args = parser.parse_args()
return args
def init_logger():
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(name)-15s %(levelname)-8s %(message)s',
datefmt='%m-%d-%Y %H:%M:%S')
def set_github_output(name: str, value: str, github_output_var_name: str = 'GITHUB_OUTPUT'):
"""Sets output variable for a GitHub Action"""
logger = logging.getLogger(__name__)
# In an environment variable "GITHUB_OUTPUT" GHA stores path to a file to write outputs to
with open(os.environ.get(github_output_var_name), 'a+') as file:
logger.info(f"Add {name}={value} to {github_output_var_name}")
print(f'{name}={value}', file=file)
def main():
init_logger()
logger = logging.getLogger(__name__)
args = parse_args()
for arg, value in sorted(vars(args).items()):
logger.info(f"Argument {arg}: {value}")
with open(Path(args.components_config), 'r') as config:
components_config = yaml.safe_load(config)
owner, repository = args.repo.split('/')
gh_api = GhApi(owner=owner, repo=repository, token=os.getenv("GITHUB_TOKEN"))
pr = gh_api.pulls.get(args.pr) if args.pr else None
with open(Path(args.components_config_schema), 'r') as schema_file:
schema = yaml.safe_load(schema_file)
with open(Path(args.labeler_config), 'r') as labeler_file:
labeler_config = yaml.safe_load(labeler_file)
all_possible_components = set()
for label in labeler_config.keys():
component_name = component_name_from_label(label, args.pattern)
all_possible_components.add(component_name if component_name else label)
# For now, we don't want to apply smart ci rules for post-commits
is_postcommit = not pr
if is_postcommit:
logger.info(f"The run is a post-commit run, executing full validation scope for all components")
no_match_files_changed = 'no-match-files' in [label.name for label in pr.labels]
if no_match_files_changed:
logger.info(f"There are changed files that don't match any pattern in labeler config, "
f"executing full validation scope for all components")
run_full_scope = is_postcommit or no_match_files_changed
# In post-commits - validate all components regardless of changeset
# In pre-commits - validate only changed components with their dependencies
all_defined_components = components_config.keys()
changed_component_names = set(all_defined_components) if run_full_scope else \
get_changed_component_names(pr, all_possible_components, args.pattern)
logger.info(f"changed_component_names: {changed_component_names}")
cfg = ComponentConfig(components_config, schema, all_possible_components)
affected_components = cfg.get_affected_components(changed_component_names)
# Syntactic sugar for easier use in GHA pipeline
affected_components_output = {name: {s: True for s in scope} for name, scope in affected_components.items()}
set_github_output("affected_components", json.dumps(affected_components_output))
if __name__ == '__main__':
main()
+198
View File
@@ -0,0 +1,198 @@
import logging
import sys
import unittest
from smart_ci import ComponentConfig
log = logging.getLogger()
log.level = logging.DEBUG
def log_handler(func):
def wrapper(*args, **kwargs):
stream_handler = logging.StreamHandler(sys.stdout)
log.addHandler(stream_handler)
result = func(*args, **kwargs)
log.removeHandler(stream_handler)
return result
return wrapper
class TestComponentConfig(unittest.TestCase):
def setUp(self):
self.all_possible_components = {'comp1', 'comp2', 'comp3', 'comp4'}
ComponentConfig.ScopeKeys = {'build', 'revalidate', '_scope_1', '_scope_2', '_scope_3'}
@log_handler
def validate(self, config_data: dict, changed_components: set, expected_result: dict):
log.info(f"{self._testMethodName}:")
config = ComponentConfig(config_data, {}, self.all_possible_components)
result = config.get_affected_components(changed_components)
self.assertEqual(expected_result, result)
def test_no_changed_components(self):
config_data = {
'comp1': {'build': {}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = set()
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': ComponentConfig.FullScope,
'comp3': ComponentConfig.FullScope,
'comp4': ComponentConfig.FullScope,
}
self.validate(config_data, changed_components, expected_result)
def test_all_components_changed(self):
config_data = {
'comp1': {'build': {}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1', 'comp2', 'comp3', 'comp4'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': ComponentConfig.FullScope,
'comp3': ComponentConfig.FullScope,
'comp4': ComponentConfig.FullScope,
}
self.validate(config_data, changed_components, expected_result)
def test_changed_component_not_defined(self):
config_data = {
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': ComponentConfig.FullScope,
'comp3': ComponentConfig.FullScope,
'comp4': ComponentConfig.FullScope,
}
self.validate(config_data, changed_components, expected_result)
def test_component_changed_no_scope_keys(self):
config_data = {
'comp1': {},
'comp2': {},
'comp3': {},
'comp4': {},
}
changed_components = {'comp1'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': ComponentConfig.FullScope,
'comp3': ComponentConfig.FullScope,
'comp4': ComponentConfig.FullScope,
}
self.validate(config_data, changed_components, expected_result)
def test_one_component_changed_dependents_empty(self):
config_data = {
'comp1': {'build': {}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1'}
expected_result = {
'comp1': ComponentConfig.FullScope,
}
self.validate(config_data, changed_components, expected_result)
def test_not_changed_dependent_component(self):
config_data = {
'comp1': {'build': {'comp2'}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': {'build'}
}
self.validate(config_data, changed_components, expected_result)
def test_changed_dependent_component(self):
config_data = {
'comp1': {'build': {'comp2'}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1', 'comp2'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': ComponentConfig.FullScope
}
self.validate(config_data, changed_components, expected_result)
def test_dependent_component_multiple_parents(self):
config_data = {
'comp1': {'_scope_1': {'comp2'}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, '_scope_2': {'comp2'}, '_scope_3': {'comp2'}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1', 'comp3'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': {'_scope_1', '_scope_2', '_scope_3'},
'comp3': ComponentConfig.FullScope
}
self.validate(config_data, changed_components, expected_result)
def test_dependent_component_empty_scopes(self):
config_data = {
'comp1': {'build': {}, 'revalidate': {'comp2'}},
'comp2': {},
'comp3': {},
'comp4': {},
}
changed_components = {'comp1', 'comp3'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': ComponentConfig.FullScope,
'comp3': ComponentConfig.FullScope,
'comp4': ComponentConfig.FullScope
}
self.validate(config_data, changed_components, expected_result)
def test_changed_component_empty_dependencies(self):
config_data = {
'comp1': {'build': {}, 'revalidate': {}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1'}
expected_result = {
'comp1': ComponentConfig.FullScope,
}
self.validate(config_data, changed_components, expected_result)
def test_multiple_dependents(self):
config_data = {
'comp1': {'build': {'comp2'}, 'revalidate': {'comp3'}},
'comp2': {'build': {}, 'revalidate': {}},
'comp3': {'build': {'comp4'}, 'revalidate': {}},
'comp4': {'build': {}, 'revalidate': {}},
}
changed_components = {'comp1'}
expected_result = {
'comp1': ComponentConfig.FullScope,
'comp2': {'build'},
'comp3': ComponentConfig.FullScope,
# We don't consider dependencies of dependencies affected, so comp4 is not expected here
}
self.validate(config_data, changed_components, expected_result)
if __name__ == '__main__':
unittest.main(verbosity=2)
+198
View File
@@ -0,0 +1,198 @@
CPU:
revalidate:
- C_API
- Python_API
- samples
build:
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- IR_FE
GPU:
build:
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- IR_FE
GNA:
build:
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- IR_FE
HETERO:
revalidate:
- CPU
- GPU
- GNA
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- C_API
- Python_API
build:
- IR_FE
AUTO_BATCH:
revalidate:
- CPU
- GPU
- GNA
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- C_API
- Python_API
build:
- IR_FE
TEMPLATE:
revalidate:
- CPU
- GPU
- GNA
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- C_API
- Python_API
build:
- IR_FE
AUTO:
revalidate:
- CPU
- GPU
- GNA
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- C_API
- Python_API
build:
- IR_FE
IR_FE:
revalidate:
- C_API
- Python_API
- samples
build:
- CPU
ONNX_FE:
revalidate:
- MO
build:
- CPU
- Python_API
PDPD_FE:
revalidate:
- MO
build:
- CPU
- Python_API
TF_FE:
revalidate:
- MO
build:
- CPU
- Python_API
TFL_FE:
revalidate:
- MO
build:
- CPU
- Python_API
PyTorch_FE:
revalidate:
- MO
build:
- CPU
- Python_API
C_API:
build:
- CPU
- HETERO
- AUTO_BATCH
- AUTO
- IR_FE
Python_API:
revalidate:
- samples
- MO
- POT
- tools
build:
- CPU
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
- IR_FE
- ONNX_FE
- PDPD_FE
- TF_FE
- TFL_FE
- PyTorch_FE
samples:
build:
- CPU
- AUTO_BATCH
- AUTO
- IR_FE
- C_API
- Python_API
IE_Tests:
revalidate:
- CPU
- GPU
- GNA
- HETERO
- AUTO_BATCH
- TEMPLATE
- AUTO
build:
- IR_FE
MO:
revalidate:
- POT
build:
- Python_API
POT:
build:
- CPU
- Python_API
tools:
build:
- CPU
- Python_API
docs:
revalidate: []
build: []
licensing:
revalidate: []
build: []
+80 -10
View File
@@ -34,6 +34,31 @@ env:
PYTHON_VERSION: '3.11'
jobs:
Smart_CI:
runs-on: ubuntu-latest
outputs:
affected_components: "${{ steps.smart_ci.outputs.affected_components }}"
steps:
- name: checkout action
uses: actions/checkout@v4
with:
sparse-checkout: .github/actions/smart-ci
- name: Get affected components
id: smart_ci
uses: ./.github/actions/smart-ci
with:
repository: ${{ github.repository }}
pr: ${{ github.event.pull_request.number }}
commit_sha: ${{ github.sha }}
component_pattern: "category: (.*)"
repo_token: ${{ secrets.GITHUB_TOKEN }}
- name: Show affected components
run: |
echo "${{ toJSON(steps.smart_ci.outputs.affected_components) }}"
shell: bash
Build:
timeout-minutes: 150
defaults:
@@ -303,7 +328,7 @@ jobs:
ovc --help
Samples:
needs: Build
needs: [Build, Smart_CI]
timeout-minutes: 20
defaults:
run:
@@ -316,6 +341,7 @@ jobs:
INSTALL_DIR: /__w/openvino/openvino/install
INSTALL_TEST_DIR: /__w/openvino/openvino/install/tests
BUILD_DIR: /__w/openvino/openvino/build
if: fromJSON(needs.smart_ci.outputs.affected_components).samples
steps:
- name: Download OpenVINO package
@@ -381,6 +407,7 @@ jobs:
#
- name: Samples tests
if: fromJSON(needs.smart_ci.outputs.affected_components).samples.test
run: |
export WORKSPACE=${INSTALL_DIR}
export IE_APP_PATH=${INSTALL_DIR}/samples_bin
@@ -402,7 +429,7 @@ jobs:
with:
name: test-results-samples
path: ${{ env.INSTALL_TEST_DIR }}/TEST*.xml
if-no-files-found: 'error'
if-no-files-found: 'warn'
Conformance:
needs: Build
@@ -646,7 +673,7 @@ jobs:
CXX_Unit_Tests:
name: C++ unit tests
needs: Build
needs: [Build, Smart_CI]
timeout-minutes: 20
defaults:
run:
@@ -706,6 +733,7 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-InferenceUnit.xml
- name: Low Precision Transformations Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).LP_transformations.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_lp_transformations_tests --gtest_print_time=1 \
@@ -718,6 +746,7 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-ConditionalCompilation.xml
- name: IR frontend tests
if: fromJSON(needs.smart_ci.outputs.affected_components).IR_FE.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_ir_frontend_tests --gtest_print_time=1 \
@@ -731,6 +760,7 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-PaddleTests.xml
- name: ONNX frontend tests
if: fromJSON(needs.smart_ci.outputs.affected_components).ONNX_FE.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_onnx_frontend_tests --gtest_print_time=1 \
@@ -738,30 +768,36 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-ONNXFrontend.xml
- name: TensorFlow Common frontend tests
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test ||
fromJSON(needs.smart_ci.outputs.affected_components).TFL_FE.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_tensorflow_common_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-TensorFlowCommonFrontend.xml
- name: TensorFlow frontend tests
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_tensorflow_frontend_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-TensorFlowFrontend.xml
- name: TensorFlow Lite frontend tests
if: fromJSON(needs.smart_ci.outputs.affected_components).TFL_FE.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_tensorflow_lite_frontend_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-TensorFlowLiteFrontend.xml
- name: Transformations func tests
if: fromJSON(needs.smart_ci.outputs.affected_components).transformations.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_transformations_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-Transformations.xml
- name: Legacy Transformations func tests
if: fromJSON(needs.smart_ci.outputs.affected_components).transformations.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_legacy_transformations_tests --gtest_print_time=1 \
@@ -780,12 +816,14 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-CommonUtilTests.xml
- name: Snippets func tests
if: fromJSON(needs.smart_ci.outputs.affected_components).CPU.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_snippets_func_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-SnippetsFuncTests.xml
- name: CPU plugin unit tests
if: fromJSON(needs.smart_ci.outputs.affected_components).CPU.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_cpu_unit_tests --gtest_print_time=1 \
@@ -804,18 +842,21 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-OpImplTests.xml
- name: AUTO unit tests
if: fromJSON(needs.smart_ci.outputs.affected_components).AUTO.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_auto_unit_tests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-ov_auto_unit_tests.xml
- name: AUTO func Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).AUTO.test
run: |
source ${{ env.INSTALL_DIR }}/setupvars.sh
${{ env.INSTALL_TEST_DIR }}/ov_auto_func_tests --gtest_print_time=1 \
--gtest_output=xml:${{ env.INSTALL_TEST_DIR }}/TEST-ov_auto_func_tests.xml
- name: Template plugin func tests
if: fromJSON(needs.smart_ci.outputs.affected_components).TEMPLATE.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_template_func_tests --gtest_print_time=1 \
@@ -823,23 +864,27 @@ jobs:
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-TemplateFuncTests.xml
- name: Inference Engine C API tests
if: fromJSON(needs.smart_ci.outputs.affected_components).C_API.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/InferenceEngineCAPITests --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-InferenceEngineCAPITests.xml
- name: OpenVINO C API tests
if: fromJSON(needs.smart_ci.outputs.affected_components).C_API.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_capi_test --gtest_print_time=1 \
--gtest_output=xml:${INSTALL_TEST_DIR}/TEST-OpenVINOCAPITests.xml
- name: AutoBatch unit tests
if: fromJSON(needs.smart_ci.outputs.affected_components).AUTO_BATCH.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_auto_batch_unit_tests --gtest_output=xml:${INSTALL_TEST_DIR}/TEST-ov_auto_batch_unit_tests.xml
- name: AutoBatch func tests
if: fromJSON(needs.smart_ci.outputs.affected_components).AUTO_BATCH.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_auto_batch_func_tests --gtest_output=xml:${INSTALL_TEST_DIR}/TEST-ov_auto_batch_func_tests.xml
@@ -850,11 +895,13 @@ jobs:
${INSTALL_TEST_DIR}/ov_proxy_plugin_tests --gtest_print_time=1 --gtest_output=xml:${INSTALL_TEST_DIR}/TEST-OVProxyTests.xml
- name: Hetero unit tests
if: fromJSON(needs.smart_ci.outputs.affected_components).HETERO.test
run: |
source ${{ env.INSTALL_DIR }}/setupvars.sh
${{ env.INSTALL_TEST_DIR }}/ov_hetero_unit_tests --gtest_print_time=1 --gtest_output=xml:${{ env.INSTALL_TEST_DIR }}/TEST-OVHeteroUnitTests.xml
- name: Hetero func tests
if: fromJSON(needs.smart_ci.outputs.affected_components).HETERO.test
run: |
source ${INSTALL_DIR}/setupvars.sh
${INSTALL_TEST_DIR}/ov_hetero_func_tests --gtest_print_time=1 --gtest_output=xml:${INSTALL_TEST_DIR}/TEST-OVHeteroFuncTests.xml
@@ -865,11 +912,11 @@ jobs:
with:
name: test-results-cpp
path: ${{ env.INSTALL_TEST_DIR }}/TEST*.xml
if-no-files-found: 'error'
if-no-files-found: 'warn'
Python_Unit_Tests:
name: Python unit tests
needs: Build
needs: [Build, Smart_CI]
timeout-minutes: 40
defaults:
run:
@@ -926,6 +973,9 @@ jobs:
pip-cache-path: ${{ env.PIP_CACHE_PATH }}
should-setup-pip-paths: 'true'
- name: Install OpenVINO dependencies
run: ${INSTALL_DIR}/install_dependencies/install_openvino_dependencies.sh -c=core -y
- name: Install OpenVINO Python wheels
run: |
# Install the core OV wheel
@@ -952,6 +1002,7 @@ jobs:
#
- name: Python API 1.0 Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).Python_API.test
run: |
python3 -m pytest -s ${INSTALL_TEST_DIR}/pyngraph \
--junitxml=${INSTALL_TEST_DIR}/TEST-Pyngraph.xml \
@@ -959,6 +1010,7 @@ jobs:
--ignore=${INSTALL_TEST_DIR}/pyngraph/tests_compatibility/test_onnx/test_backend.py
- name: Python API 2.0 Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).Python_API.test
run: |
# for 'template' extension
export LD_LIBRARY_PATH=${INSTALL_TEST_DIR}:$LD_LIBRARY_PATH
@@ -967,6 +1019,7 @@ jobs:
--ignore=${INSTALL_TEST_DIR}/pyopenvino/tests/test_utils/test_utils.py
- name: Model Optimizer unit tests
if: fromJSON(needs.smart_ci.outputs.affected_components).MO.test
run: |
# required for MxNet
apt-get install -y libgomp1 libquadmath0
@@ -982,6 +1035,7 @@ jobs:
--ignore=${INSTALL_TEST_DIR}/onnx/test_python/test_zoo_models.py
- name: OVC unit tests
if: fromJSON(needs.smart_ci.outputs.affected_components).MO.test
run: python3 -m pytest -s ${INSTALL_TEST_DIR}/ovc/unit_tests --junitxml=${INSTALL_TEST_DIR}/TEST-OpenVinoConversion.xml
- name: Install Python Layer tests dependencies
@@ -990,6 +1044,7 @@ jobs:
python3 -m pip install -r ${LAYER_TESTS_INSTALL_DIR}/requirements.txt
- name: MO Python API Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).MO.test
run: |
# Import 'test_utils' installed in '<package_test>/tests/python/openvino'
export LD_LIBRARY_PATH=${PIP_INSTALL_PATH}/openvino/libs:$LD_LIBRARY_PATH
@@ -1000,6 +1055,7 @@ jobs:
TEST_PRECISION: FP16
- name: OVC Python API Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).MO.test
run: |
# Import 'test_utils' installed in '<package_test>/tests/python/openvino'
export PYTHONPATH=${INSTALL_TEST_DIR}/python
@@ -1010,6 +1066,8 @@ jobs:
TEST_PRECISION: FP16
- name: Python Frontend tests
if: fromJSON(needs.smart_ci.outputs.affected_components).PyTorch_FE.test ||
fromJSON(needs.smart_ci.outputs.affected_components).PDPD_FE.test
run: |
# to allow 'libtest_builtin_extensions.so' to find 'libopenvino_onnx_frontend.so'
export LD_LIBRARY_PATH=${PIP_INSTALL_PATH}/openvino/libs:$LD_LIBRARY_PATH
@@ -1022,6 +1080,7 @@ jobs:
TEST_PRECISION: FP32
- name: PyTorch torch.compile TORCHFX Layer Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).PyTorch_FE.test
run: |
python3 -m pytest ${LAYER_TESTS_INSTALL_DIR}/pytorch_tests -m precommit_fx_backend --junitxml=${INSTALL_TEST_DIR}/TEST-pytorch.xml
env:
@@ -1030,6 +1089,7 @@ jobs:
PYTORCH_TRACING_MODE: TORCHFX
- name: PyTorch torch.compile TORCHSCRIPT Layer Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).PyTorch_FE.test
run: |
python3 -m pytest ${LAYER_TESTS_INSTALL_DIR}/pytorch_tests -m precommit_ts_backend --junitxml=${INSTALL_TEST_DIR}/TEST-pytorch.xml
env:
@@ -1038,6 +1098,7 @@ jobs:
PYTORCH_TRACING_MODE: TORCHSCRIPT
- name: ONNX Layer Tests
if: fromJSON(needs.smart_ci.outputs.affected_components).ONNX_FE.test
run: |
# requires 'unit_tests' from 'tools/mo'
export PYTHONPATH=${INSTALL_TEST_DIR}/mo:$PYTHONPATH
@@ -1047,6 +1108,7 @@ jobs:
TEST_PRECISION: FP16
- name: TensorFlow 1 Layer Tests - TF FE
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test
run: |
# requires 'unit_tests' from 'mo'
export PYTHONPATH=${INSTALL_TEST_DIR}/mo
@@ -1056,6 +1118,7 @@ jobs:
TEST_PRECISION: FP16
- name: TensorFlow 2 Layer Tests - TF FE
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test
run: |
# requires 'unit_tests' from 'mo'
export PYTHONPATH=${INSTALL_TEST_DIR}/mo
@@ -1065,20 +1128,24 @@ jobs:
TEST_PRECISION: FP16
- name: JAX Layer Tests - TF FE
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test
run: python3 -m pytest ${LAYER_TESTS_INSTALL_DIR}/jax_tests/ -m precommit --junitxml=${INSTALL_TEST_DIR}/TEST-jax.xml
env:
TEST_DEVICE: CPU
- name: TensorFlow 1 Layer Tests - Legacy FE
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test
run: python3 -m pytest ${LAYER_TESTS_INSTALL_DIR}/tensorflow_tests/test_tf_Roll.py --ir_version=10 --junitxml=${INSTALL_TEST_DIR}/TEST-tf_Roll.xml
- name: TensorFlow 2 Layer Tests - Legacy FE
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test
run: python3 -m pytest ${LAYER_TESTS_INSTALL_DIR}/tensorflow2_keras_tests/test_tf2_keras_activation.py --ir_version=11 -k "sigmoid" --junitxml=${INSTALL_TEST_DIR}/TEST-tf2_Activation.xml
env:
TEST_DEVICE: CPU
TEST_PRECISION: FP16
- name: TensorFlow Lite Layer Tests - TFL FE
if: fromJSON(needs.smart_ci.outputs.affected_components).TFL_FE.test
run: python3 -m pytest ${LAYER_TESTS_INSTALL_DIR}/tensorflow_lite_tests/ --junitxml=${INSTALL_TEST_DIR}/TEST-tfl_fe.xml
env:
TEST_DEVICE: CPU
@@ -1107,11 +1174,11 @@ jobs:
path: |
${{ env.INSTALL_TEST_DIR }}/TEST*.html
${{ env.INSTALL_TEST_DIR }}/TEST*.xml
if-no-files-found: 'error'
if-no-files-found: 'warn'
CPU_Functional_Tests:
name: CPU functional tests
needs: Build
needs: [Build, Smart_CI]
timeout-minutes: 25
defaults:
run:
@@ -1125,7 +1192,7 @@ jobs:
INSTALL_TEST_DIR: /__w/openvino/openvino/install/tests
PARALLEL_TEST_SCRIPT: /__w/openvino/openvino/install/tests/functional_test_utils/layer_tests_summary/run_parallel.py
PARALLEL_TEST_CACHE: /__w/openvino/openvino/install/tests/test_cache.lst
if: fromJSON(needs.smart_ci.outputs.affected_components).CPU.test
steps:
- name: Download OpenVINO package
uses: actions/download-artifact@v3
@@ -1207,7 +1274,7 @@ jobs:
TensorFlow_Hub_Models_Tests:
name: TensorFlow Hub Models tests
needs: Build
needs: [Build, Smart_CI]
defaults:
run:
shell: bash
@@ -1223,6 +1290,8 @@ jobs:
INSTALL_DIR: ${{ github.workspace }}/install
INSTALL_TEST_DIR: ${{ github.workspace }}/install/tests
MODEL_HUB_TESTS_INSTALL_DIR: ${{ github.workspace }}/install/tests/model_hub_tests
if: fromJSON(needs.smart_ci.outputs.affected_components).TF_FE.test ||
fromJSON(needs.smart_ci.outputs.affected_components).TFL_FE.test
steps:
- name: Check sudo
@@ -1291,7 +1360,7 @@ jobs:
PyTorch_Models_Tests:
name: PyTorch Models tests
needs: Build
needs: [Build, Smart_CI]
timeout-minutes: ${{ github.event_name == 'schedule' && 400 || 30 }}
defaults:
run:
@@ -1307,6 +1376,7 @@ jobs:
INSTALL_DIR: ${{ github.workspace }}/install
INSTALL_TEST_DIR: ${{ github.workspace }}/install/tests
MODEL_HUB_TESTS_INSTALL_DIR: ${{ github.workspace }}/install/tests/model_hub_tests
if: fromJSON(needs.smart_ci.outputs.affected_components).PyTorch_FE.test
steps:
- name: Check sudo
+1
View File
@@ -61,3 +61,4 @@ __pycache__
/tools/mo/*.svg
/src/plugins/intel_cpu/tools/commit_slider/*.json
/src/plugins/intel_cpu/tools/commit_slider/slider_cache/*
.github/GITHUB_OUTPUT