idf_ci package
Subpackages
- idf_ci.idf_gitlab package
- Submodules
- Module contents
- idf_ci.idf_pytest package
- Submodules
GroupKey
GroupedPytestCases
PytestApp
PytestCase
PytestCase.KNOWN_ENV_MARKERS
PytestCase.all_markers
PytestCase.caseid
PytestCase.configs
PytestCase.env_markers
PytestCase.env_selector
PytestCase.from_item()
PytestCase.get_param()
PytestCase.get_skip_reason_if_not_built()
PytestCase.is_host_test
PytestCase.is_single_dut
PytestCase.name
PytestCase.path
PytestCase.runner_tags
PytestCase.target_selector
PytestCase.targets
IdfPytestPlugin
pytest_addoption()
pytest_configure()
pytest_unconfigure()
get_pytest_cases()
- Module contents
GroupedPytestCases
IdfPytestPlugin
PytestApp
PytestCase
PytestCase.KNOWN_ENV_MARKERS
PytestCase.all_markers
PytestCase.caseid
PytestCase.configs
PytestCase.env_markers
PytestCase.env_selector
PytestCase.from_item()
PytestCase.get_param()
PytestCase.get_skip_reason_if_not_built()
PytestCase.is_host_test
PytestCase.is_single_dut
PytestCase.name
PytestCase.path
PytestCase.runner_tags
PytestCase.target_selector
PytestCase.targets
get_pytest_cases()
- Submodules
- idf_ci.templates package
Submodules
- class idf_ci.scripts.ProcessedArgs(modified_files: List[str] | None, modified_components: List[str] | None, filter_expr: str | None, default_build_targets: List[str], test_related_apps: List[App] | None, non_test_related_apps: List[App] | None)
Bases:
object
Container for processed arguments with meaningful field names.
- default_build_targets: List[str]
- filter_expr: str | None
- modified_components: List[str] | None
- modified_files: List[str] | None
- idf_ci.scripts.build(*, paths: List[str] | None = None, target: str = 'all', parallel_count: int = 1, parallel_index: int = 1, modified_files: List[str] | None = None, modified_components: List[str] | None = None, only_test_related: bool | None = None, only_non_test_related: bool | None = None, dry_run: bool = False, build_system: UndefinedType | str = __UNDEF__, marker_expr: UndefinedType | str = __UNDEF__, filter_expr: str | None = None) Tuple[List[App], int]
Build applications based on specified parameters.
- Parameters:
paths – List of paths to search for applications
target – Target device(s) separated by commas
parallel_count – Total number of parallel jobs
parallel_index – Index of current parallel job (1-based)
modified_files – List of modified files
modified_components – List of modified components
only_test_related – Only build test-related applications
only_non_test_related – Only build non-test-related applications
dry_run – Do not actually build, just simulate
build_system – Filter the apps by build system. Can be “cmake”, “make” or a custom App class path
marker_expr – Pytest marker expression
filter_expr – Filter expression
- Returns:
Tuple of (built apps, build return code)
- idf_ci.scripts.get_all_apps(*, paths: List[str] | None = None, target: str = 'all', modified_files: List[str] | None = None, modified_components: List[str] | None = None, filter_expr: str | None = None, default_build_targets: List[str] | None = None, marker_expr: UndefinedType | str | None = __UNDEF__, compare_manifest_sha_filepath: str | None = None, build_system: UndefinedType | str | None = __UNDEF__) Tuple[List[App], List[App]]
Get test-related and non-test-related applications.
- Parameters:
paths – List of paths to search for applications
target – Target device(s) separated by commas
modified_files – List of modified files
modified_components – List of modified components
filter_expr – Pytest filter expression -k
default_build_targets – Default build targets to use
marker_expr – Pytest marker expression -m
compare_manifest_sha_filepath – Path to the manifest SHA file generated by idf-build-apps dump-manifest-sha
build_system – Filter the apps by build system. Can be “cmake”, “make” or a custom App class path
- Returns:
Tuple of (test_related_apps, non_test_related_apps)
- idf_ci.scripts.preprocess_args(modified_files: List[str] | None = None, modified_components: List[str] | None = None, filter_expr: str | None = None, default_build_targets: List[str] | None = None) ProcessedArgs
Set values according to the environment variables, .toml settings, and defaults.
- Parameters:
modified_files – List of modified files
modified_components – List of modified components
filter_expr – Pytest filter expression
default_build_targets – Default build targets to use
- Returns:
Processed arguments as a ProcessedArgs object
- idf_ci.utils.get_current_branch() str
Get the current Git branch by running git command.
- Returns:
The current Git ref (branch name or commit SHA)
- Raises:
RuntimeError – If not in a Git repository or git command fails
- idf_ci.utils.remove_subfolders(paths: List[str]) List[str]
Remove paths that are subfolders of other paths in the list.
- Parameters:
paths – List of directory paths as strings
- Returns:
Filtered list of paths with no subfolder/parent folder relationships
- idf_ci.utils.setup_logging(level: int | None = 20) None
Setup logging
- Parameters:
level – logging level
- idf_ci.utils.to_list(s: None) None
- idf_ci.utils.to_list(s: Iterable[_T]) List[_T]
- idf_ci.utils.to_list(s: _T) List[_T]
Turn all objects to lists
- Parameters:
s – anything
- Returns:
None
, ifs
is Noneitself, if
s
is a listlist(s)
, ifs
is a tuple or a set[s]
, ifs
is other type
Module contents
- pydantic settings idf_ci.CiSettings
Bases:
BaseSettings
Show JSON schema
{ "title": "CiSettings", "type": "object", "properties": { "component_mapping_regexes": { "default": [ "/components/(.+)/", "/common_components/(.+)/" ], "items": { "type": "string" }, "title": "Component Mapping Regexes", "type": "array" }, "extend_component_mapping_regexes": { "default": [], "items": { "type": "string" }, "title": "Extend Component Mapping Regexes", "type": "array" }, "component_ignored_file_extensions": { "default": [ ".md", ".rst", ".yaml", ".yml", ".py" ], "items": { "type": "string" }, "title": "Component Ignored File Extensions", "type": "array" }, "extend_component_ignored_file_extensions": { "default": [], "items": { "type": "string" }, "title": "Extend Component Ignored File Extensions", "type": "array" }, "built_app_list_filepatterns": { "default": [ "app_info_*.txt" ], "items": { "type": "string" }, "title": "Built App List Filepatterns", "type": "array" }, "collected_test_related_apps_filepath": { "default": "test_related_apps.txt", "title": "Collected Test Related Apps Filepath", "type": "string" }, "collected_non_test_related_apps_filepath": { "default": "non_test_related_apps.txt", "title": "Collected Non Test Related Apps Filepath", "type": "string" }, "preserve_test_related_apps": { "default": true, "title": "Preserve Test Related Apps", "type": "boolean" }, "preserve_non_test_related_apps": { "default": true, "title": "Preserve Non Test Related Apps", "type": "boolean" }, "extra_default_build_targets": { "default": [], "items": { "type": "string" }, "title": "Extra Default Build Targets", "type": "array" }, "ci_detection_envs": { "default": [ "CI", "GITHUB_ACTIONS", "CIRCLECI", "TRAVIS", "JENKINS_URL", "DRONE", "APPVEYOR", "BITBUCKET_COMMIT", "SEMAPHORE", "TEAMCITY_VERSION" ], "items": { "type": "string" }, "title": "Ci Detection Envs", "type": "array" }, "local_runtime_envs": { "additionalProperties": true, "default": {}, "title": "Local Runtime Envs", "type": "object" }, "ci_runtime_envs": { "additionalProperties": true, "default": {}, "title": "Ci Runtime Envs", "type": "object" }, "gitlab": { "$ref": "#/$defs/GitlabSettings", "default": { "project": "espressif/esp-idf", "known_failure_cases_bucket_name": "ignore-test-result-files", "artifacts": { "build_job_filepatterns": [ "app_info_*.txt", "build_summary_*.xml" ], "s3": { "debug": { "bucket": "idf-artifacts", "patterns": [ "**/build*/bootloader/*.map", "**/build*/bootloader/*.elf", "**/build*/*.map", "**/build*/*.elf", "**/build*/build.log" ] }, "flash": { "bucket": "idf-artifacts", "patterns": [ "**/build*/bootloader/*.bin", "**/build*/*.bin", "**/build*/partition_table/*.bin", "**/build*/flasher_args.json", "**/build*/flash_project_args", "**/build*/config/sdkconfig.json", "**/build*/sdkconfig", "**/build*/project_description.json" ] } }, "test_job_filepatterns": [ "pytest-embedded/", "XUNIT_RESULT*.xml" ] }, "build_pipeline": { "job_tags": [ "build" ], "job_template_jinja": "{{ settings.gitlab.build_pipeline.job_template_name }}:\n stage: build\n tags: {{ settings.gitlab.build_pipeline.job_tags }}\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.build_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n script:\n - idf-ci build run\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}", "job_template_name": ".default_build_settings", "jobs_jinja": "{%- if test_related_apps_count > 0 %}\nbuild_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if test_related_parallel_count > 1 %}\n parallel: {{ test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_TEST_RELATED_APPS: \"1\"\n{%- endif %}\n\n{%- if non_test_related_apps_count > 0 %}\nbuild_non_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if non_test_related_parallel_count > 1 %}\n parallel: {{ non_test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_NON_TEST_RELATED_APPS: \"1\"\n{%- endif %}", "pre_yaml_jinja": "", "presigned_json_job_name": "generate_presigned_json", "runs_per_job": 60, "workflow_name": "Build Child Pipeline", "yaml_filename": "build_child_pipeline.yml", "yaml_jinja": "{{ settings.gitlab.build_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.build_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.build_pipeline.job_template_jinja %}\n{{ job_template }}\n{%- endif %}\n\n{{ jobs }}\n\n{%- if test_related_apps_count > 0 %}\ngenerate_test_child_pipeline:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n needs:\n - build_test_related_apps\n artifacts:\n paths:\n - {{ settings.gitlab.test_pipeline.yaml_filename }}\n script:\n - idf-ci gitlab test-child-pipeline\n\ntest-child-pipeline:\n stage: .post\n needs:\n - generate_test_child_pipeline\n variables:\n PARENT_PIPELINE_ID: $PARENT_PIPELINE_ID\n trigger:\n include:\n - artifact: {{ settings.gitlab.test_pipeline.yaml_filename }}\n job: generate_test_child_pipeline\n strategy: depend\n{%- endif %}" }, "test_pipeline": { "job_tags": [], "job_template_jinja": "{{ settings.gitlab.test_pipeline.job_template_name }}:\n stage: test\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.test_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n variables:\n PYTEST_EXTRA_FLAGS: \"\"\n script:\n - pytest ${nodes}\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}\n --junitxml XUNIT_RESULT_${CI_JOB_NAME_SLUG}.xml\n ${PYTEST_EXTRA_FLAGS}", "job_template_name": ".default_test_settings", "jobs_jinja": "{% for job in jobs %}\n{{ job['name'] }}:\n extends:\n - {{ settings.gitlab.test_pipeline.job_template_name }}\n {%- for extra_extend in job.get('extra_extends', []) %}\n - {{ extra_extend }}\n {%- endfor %}\n tags: {{ job['tags'] }}\n{%- if job['parallel_count'] > 1 %}\n parallel: {{ job['parallel_count'] }}\n{%- endif %}\n variables:\n nodes: {{ job['nodes'] }}\n{% endfor %}", "pre_yaml_jinja": "", "presigned_json_job_name": "generate_presigned_json", "runs_per_job": 30, "workflow_name": "Test Child Pipeline", "yaml_filename": "test_child_pipeline.yml", "yaml_jinja": "{{ settings.gitlab.test_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.test_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.test_pipeline.job_template_jinja %}\n{{ default_template }}\n{%- endif %}\n\n{{ jobs }}" } } } }, "$defs": { "ArtifactSettings": { "additionalProperties": false, "properties": { "s3": { "additionalProperties": { "$ref": "#/$defs/S3FilePatternConfig" }, "default": { "debug": { "bucket": "idf-artifacts", "patterns": [ "**/build*/bootloader/*.map", "**/build*/bootloader/*.elf", "**/build*/*.map", "**/build*/*.elf", "**/build*/build.log" ] }, "flash": { "bucket": "idf-artifacts", "patterns": [ "**/build*/bootloader/*.bin", "**/build*/*.bin", "**/build*/partition_table/*.bin", "**/build*/flasher_args.json", "**/build*/flash_project_args", "**/build*/config/sdkconfig.json", "**/build*/sdkconfig", "**/build*/project_description.json" ] } }, "title": "S3", "type": "object" }, "build_job_filepatterns": { "default": [ "app_info_*.txt", "build_summary_*.xml" ], "items": { "type": "string" }, "title": "Build Job Filepatterns", "type": "array" }, "test_job_filepatterns": { "default": [ "pytest-embedded/", "XUNIT_RESULT*.xml" ], "items": { "type": "string" }, "title": "Test Job Filepatterns", "type": "array" } }, "title": "ArtifactSettings", "type": "object" }, "BuildPipelineSettings": { "additionalProperties": false, "properties": { "workflow_name": { "default": "Build Child Pipeline", "title": "Workflow Name", "type": "string" }, "presigned_json_job_name": { "default": "generate_presigned_json", "title": "Presigned Json Job Name", "type": "string" }, "job_template_name": { "default": ".default_build_settings", "title": "Job Template Name", "type": "string" }, "job_template_jinja": { "default": "{{ settings.gitlab.build_pipeline.job_template_name }}:\n stage: build\n tags: {{ settings.gitlab.build_pipeline.job_tags }}\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.build_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n script:\n - idf-ci build run\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}", "title": "Job Template Jinja", "type": "string" }, "job_tags": { "default": [ "build" ], "items": { "type": "string" }, "title": "Job Tags", "type": "array" }, "runs_per_job": { "default": 60, "title": "Runs Per Job", "type": "integer" }, "jobs_jinja": { "default": "{%- if test_related_apps_count > 0 %}\nbuild_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if test_related_parallel_count > 1 %}\n parallel: {{ test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_TEST_RELATED_APPS: \"1\"\n{%- endif %}\n\n{%- if non_test_related_apps_count > 0 %}\nbuild_non_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if non_test_related_parallel_count > 1 %}\n parallel: {{ non_test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_NON_TEST_RELATED_APPS: \"1\"\n{%- endif %}", "title": "Jobs Jinja", "type": "string" }, "pre_yaml_jinja": { "default": "", "title": "Pre Yaml Jinja", "type": "string" }, "yaml_jinja": { "default": "{{ settings.gitlab.build_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.build_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.build_pipeline.job_template_jinja %}\n{{ job_template }}\n{%- endif %}\n\n{{ jobs }}\n\n{%- if test_related_apps_count > 0 %}\ngenerate_test_child_pipeline:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n needs:\n - build_test_related_apps\n artifacts:\n paths:\n - {{ settings.gitlab.test_pipeline.yaml_filename }}\n script:\n - idf-ci gitlab test-child-pipeline\n\ntest-child-pipeline:\n stage: .post\n needs:\n - generate_test_child_pipeline\n variables:\n PARENT_PIPELINE_ID: $PARENT_PIPELINE_ID\n trigger:\n include:\n - artifact: {{ settings.gitlab.test_pipeline.yaml_filename }}\n job: generate_test_child_pipeline\n strategy: depend\n{%- endif %}", "title": "Yaml Jinja", "type": "string" }, "yaml_filename": { "default": "build_child_pipeline.yml", "title": "Yaml Filename", "type": "string" } }, "title": "BuildPipelineSettings", "type": "object" }, "GitlabSettings": { "additionalProperties": false, "properties": { "project": { "default": "espressif/esp-idf", "title": "Project", "type": "string" }, "known_failure_cases_bucket_name": { "default": "ignore-test-result-files", "title": "Known Failure Cases Bucket Name", "type": "string" }, "artifacts": { "$ref": "#/$defs/ArtifactSettings", "default": { "s3": { "debug": { "bucket": "idf-artifacts", "patterns": [ "**/build*/bootloader/*.map", "**/build*/bootloader/*.elf", "**/build*/*.map", "**/build*/*.elf", "**/build*/build.log" ] }, "flash": { "bucket": "idf-artifacts", "patterns": [ "**/build*/bootloader/*.bin", "**/build*/*.bin", "**/build*/partition_table/*.bin", "**/build*/flasher_args.json", "**/build*/flash_project_args", "**/build*/config/sdkconfig.json", "**/build*/sdkconfig", "**/build*/project_description.json" ] } }, "build_job_filepatterns": [ "app_info_*.txt", "build_summary_*.xml" ], "test_job_filepatterns": [ "pytest-embedded/", "XUNIT_RESULT*.xml" ] } }, "build_pipeline": { "$ref": "#/$defs/BuildPipelineSettings", "default": { "workflow_name": "Build Child Pipeline", "presigned_json_job_name": "generate_presigned_json", "job_template_name": ".default_build_settings", "job_template_jinja": "{{ settings.gitlab.build_pipeline.job_template_name }}:\n stage: build\n tags: {{ settings.gitlab.build_pipeline.job_tags }}\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.build_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n script:\n - idf-ci build run\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}", "job_tags": [ "build" ], "runs_per_job": 60, "jobs_jinja": "{%- if test_related_apps_count > 0 %}\nbuild_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if test_related_parallel_count > 1 %}\n parallel: {{ test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_TEST_RELATED_APPS: \"1\"\n{%- endif %}\n\n{%- if non_test_related_apps_count > 0 %}\nbuild_non_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if non_test_related_parallel_count > 1 %}\n parallel: {{ non_test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_NON_TEST_RELATED_APPS: \"1\"\n{%- endif %}", "pre_yaml_jinja": "", "yaml_jinja": "{{ settings.gitlab.build_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.build_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.build_pipeline.job_template_jinja %}\n{{ job_template }}\n{%- endif %}\n\n{{ jobs }}\n\n{%- if test_related_apps_count > 0 %}\ngenerate_test_child_pipeline:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n needs:\n - build_test_related_apps\n artifacts:\n paths:\n - {{ settings.gitlab.test_pipeline.yaml_filename }}\n script:\n - idf-ci gitlab test-child-pipeline\n\ntest-child-pipeline:\n stage: .post\n needs:\n - generate_test_child_pipeline\n variables:\n PARENT_PIPELINE_ID: $PARENT_PIPELINE_ID\n trigger:\n include:\n - artifact: {{ settings.gitlab.test_pipeline.yaml_filename }}\n job: generate_test_child_pipeline\n strategy: depend\n{%- endif %}", "yaml_filename": "build_child_pipeline.yml" } }, "test_pipeline": { "$ref": "#/$defs/TestPipelineSettings", "default": { "workflow_name": "Test Child Pipeline", "presigned_json_job_name": "generate_presigned_json", "job_template_name": ".default_test_settings", "job_template_jinja": "{{ settings.gitlab.test_pipeline.job_template_name }}:\n stage: test\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.test_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n variables:\n PYTEST_EXTRA_FLAGS: \"\"\n script:\n - pytest ${nodes}\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}\n --junitxml XUNIT_RESULT_${CI_JOB_NAME_SLUG}.xml\n ${PYTEST_EXTRA_FLAGS}", "job_tags": [], "runs_per_job": 30, "jobs_jinja": "{% for job in jobs %}\n{{ job['name'] }}:\n extends:\n - {{ settings.gitlab.test_pipeline.job_template_name }}\n {%- for extra_extend in job.get('extra_extends', []) %}\n - {{ extra_extend }}\n {%- endfor %}\n tags: {{ job['tags'] }}\n{%- if job['parallel_count'] > 1 %}\n parallel: {{ job['parallel_count'] }}\n{%- endif %}\n variables:\n nodes: {{ job['nodes'] }}\n{% endfor %}", "pre_yaml_jinja": "", "yaml_jinja": "{{ settings.gitlab.test_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.test_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.test_pipeline.job_template_jinja %}\n{{ default_template }}\n{%- endif %}\n\n{{ jobs }}", "yaml_filename": "test_child_pipeline.yml" } } }, "title": "GitlabSettings", "type": "object" }, "S3FilePatternConfig": { "properties": { "bucket": { "title": "Bucket", "type": "string" }, "patterns": { "items": { "type": "string" }, "title": "Patterns", "type": "array" }, "if_clause": { "title": "If Clause", "type": "string" } }, "required": [ "bucket", "patterns" ], "title": "S3FilePatternConfig", "type": "object" }, "TestPipelineSettings": { "additionalProperties": false, "properties": { "workflow_name": { "default": "Test Child Pipeline", "title": "Workflow Name", "type": "string" }, "presigned_json_job_name": { "default": "generate_presigned_json", "title": "Presigned Json Job Name", "type": "string" }, "job_template_name": { "default": ".default_test_settings", "title": "Job Template Name", "type": "string" }, "job_template_jinja": { "default": "{{ settings.gitlab.test_pipeline.job_template_name }}:\n stage: test\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.test_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n variables:\n PYTEST_EXTRA_FLAGS: \"\"\n script:\n - pytest ${nodes}\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}\n --junitxml XUNIT_RESULT_${CI_JOB_NAME_SLUG}.xml\n ${PYTEST_EXTRA_FLAGS}", "title": "Job Template Jinja", "type": "string" }, "job_tags": { "default": [], "items": { "type": "string" }, "title": "Job Tags", "type": "array" }, "runs_per_job": { "default": 30, "title": "Runs Per Job", "type": "integer" }, "jobs_jinja": { "default": "{% for job in jobs %}\n{{ job['name'] }}:\n extends:\n - {{ settings.gitlab.test_pipeline.job_template_name }}\n {%- for extra_extend in job.get('extra_extends', []) %}\n - {{ extra_extend }}\n {%- endfor %}\n tags: {{ job['tags'] }}\n{%- if job['parallel_count'] > 1 %}\n parallel: {{ job['parallel_count'] }}\n{%- endif %}\n variables:\n nodes: {{ job['nodes'] }}\n{% endfor %}", "title": "Jobs Jinja", "type": "string" }, "pre_yaml_jinja": { "default": "", "title": "Pre Yaml Jinja", "type": "string" }, "yaml_jinja": { "default": "{{ settings.gitlab.test_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.test_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.test_pipeline.job_template_jinja %}\n{{ default_template }}\n{%- endif %}\n\n{{ jobs }}", "title": "Yaml Jinja", "type": "string" }, "yaml_filename": { "default": "test_child_pipeline.yml", "title": "Yaml Filename", "type": "string" } }, "title": "TestPipelineSettings", "type": "object" } }, "additionalProperties": false }
- Fields:
- field built_app_list_filepatterns: List[str] = ['app_info_*.txt']
Glob patterns for files containing built app information.
- field ci_detection_envs: List[str] = ['CI', 'GITHUB_ACTIONS', 'CIRCLECI', 'TRAVIS', 'JENKINS_URL', 'DRONE', 'APPVEYOR', 'BITBUCKET_COMMIT', 'SEMAPHORE', 'TEAMCITY_VERSION']
Environment variables used to detect if running in CI.
- field ci_runtime_envs: Dict[str, Any] = {}
Environment variables to set in CI environment.
Path to file containing non-test-related apps.
Path to file containing test-related apps.
- field component_ignored_file_extensions: List[str] = ['.md', '.rst', '.yaml', '.yml', '.py']
File extensions to ignore when mapping files to components.
- field component_mapping_regexes: List[str] = ['/components/(.+)/', '/common_components/(.+)/']
List of regex patterns to extract component names from file paths.
- field extend_component_ignored_file_extensions: List[str] = []
Additional file extensions to ignore.
- field extend_component_mapping_regexes: List[str] = []
Additional component mapping regex patterns to extend the default list.
- field extra_default_build_targets: List[str] = []
Additional build targets to include by default.
- field gitlab: GitlabSettings = GitlabSettings(project='espressif/esp-idf', known_failure_cases_bucket_name='ignore-test-result-files', artifacts=ArtifactSettings(s3={'debug': {'bucket': 'idf-artifacts', 'patterns': ['**/build*/bootloader/*.map', '**/build*/bootloader/*.elf', '**/build*/*.map', '**/build*/*.elf', '**/build*/build.log']}, 'flash': {'bucket': 'idf-artifacts', 'patterns': ['**/build*/bootloader/*.bin', '**/build*/*.bin', '**/build*/partition_table/*.bin', '**/build*/flasher_args.json', '**/build*/flash_project_args', '**/build*/config/sdkconfig.json', '**/build*/sdkconfig', '**/build*/project_description.json']}}, build_job_filepatterns=['app_info_*.txt', 'build_summary_*.xml'], test_job_filepatterns=['pytest-embedded/', 'XUNIT_RESULT*.xml']), build_pipeline=BuildPipelineSettings(workflow_name='Build Child Pipeline', presigned_json_job_name='generate_presigned_json', job_template_name='.default_build_settings', job_template_jinja='{{ settings.gitlab.build_pipeline.job_template_name }}:\n stage: build\n tags: {{ settings.gitlab.build_pipeline.job_tags }}\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.build_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n script:\n - idf-ci build run\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}', job_tags=['build'], runs_per_job=60, jobs_jinja='{%- if test_related_apps_count > 0 %}\nbuild_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if test_related_parallel_count > 1 %}\n parallel: {{ test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_TEST_RELATED_APPS: "1"\n{%- endif %}\n\n{%- if non_test_related_apps_count > 0 %}\nbuild_non_test_related_apps:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n{%- if non_test_related_parallel_count > 1 %}\n parallel: {{ non_test_related_parallel_count }}\n{%- endif %}\n needs:\n - pipeline: $PARENT_PIPELINE_ID\n job: generate_build_child_pipeline\n - pipeline: $PARENT_PIPELINE_ID\n job: pipeline_variables\n variables:\n IDF_CI_BUILD_ONLY_NON_TEST_RELATED_APPS: "1"\n{%- endif %}', pre_yaml_jinja='', yaml_jinja='{{ settings.gitlab.build_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.build_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.build_pipeline.job_template_jinja %}\n{{ job_template }}\n{%- endif %}\n\n{{ jobs }}\n\n{%- if test_related_apps_count > 0 %}\ngenerate_test_child_pipeline:\n extends: {{ settings.gitlab.build_pipeline.job_template_name }}\n needs:\n - build_test_related_apps\n artifacts:\n paths:\n - {{ settings.gitlab.test_pipeline.yaml_filename }}\n script:\n - idf-ci gitlab test-child-pipeline\n\ntest-child-pipeline:\n stage: .post\n needs:\n - generate_test_child_pipeline\n variables:\n PARENT_PIPELINE_ID: $PARENT_PIPELINE_ID\n trigger:\n include:\n - artifact: {{ settings.gitlab.test_pipeline.yaml_filename }}\n job: generate_test_child_pipeline\n strategy: depend\n{%- endif %}', yaml_filename='build_child_pipeline.yml'), test_pipeline=TestPipelineSettings(workflow_name='Test Child Pipeline', presigned_json_job_name='generate_presigned_json', job_template_name='.default_test_settings', job_template_jinja='{{ settings.gitlab.test_pipeline.job_template_name }}:\n stage: test\n timeout: 1h\n artifacts:\n paths:\n {%- for path in settings.gitlab.artifacts.test_job_filepatterns %}\n - {{ path }}\n {%- endfor %}\n expire_in: 1 week\n when: always\n variables:\n PYTEST_EXTRA_FLAGS: ""\n script:\n - pytest ${nodes}\n --parallel-count ${CI_NODE_TOTAL:-1}\n --parallel-index ${CI_NODE_INDEX:-1}\n --junitxml XUNIT_RESULT_${CI_JOB_NAME_SLUG}.xml\n ${PYTEST_EXTRA_FLAGS}', job_tags=[], runs_per_job=30, jobs_jinja="{% for job in jobs %}\n{{ job['name'] }}:\n extends:\n - {{ settings.gitlab.test_pipeline.job_template_name }}\n {%- for extra_extend in job.get('extra_extends', []) %}\n - {{ extra_extend }}\n {%- endfor %}\n tags: {{ job['tags'] }}\n{%- if job['parallel_count'] > 1 %}\n parallel: {{ job['parallel_count'] }}\n{%- endif %}\n variables:\n nodes: {{ job['nodes'] }}\n{% endfor %}", pre_yaml_jinja='', yaml_jinja='{{ settings.gitlab.test_pipeline.pre_yaml_jinja }}\n\nworkflow:\n name: {{ settings.gitlab.test_pipeline.workflow_name }}\n rules:\n - when: always\n\n{%- if settings.gitlab.test_pipeline.job_template_jinja %}\n{{ default_template }}\n{%- endif %}\n\n{{ jobs }}', yaml_filename='test_child_pipeline.yml'))
GitLab-specific settings.
- field local_runtime_envs: Dict[str, Any] = {}
Environment variables to set in local development.
Whether to preserve non-test-related apps.
Whether to preserve test-related apps.
- classmethod read_apps_from_filepatterns(patterns: List[str]) List[App] | None
Helper method to read apps from files matching given patterns.
- Parameters:
patterns – List of file patterns to search for
- Returns:
List of App objects read from the files, or None if no files found
- classmethod read_apps_from_files(filepaths: Sequence[str | PathLike]) List[App] | None
Helper method to read apps from files.
- Parameters:
filepaths – List of file paths to read
- Returns:
List of App objects read from the files, or None if no files found
- get_built_apps_list() List[App] | None
Get the list of successfully built applications from the app info files.
- Returns:
List of App objects representing successfully built applications, or None if no files found
- get_modified_components(modified_files: Iterable[str]) Set[str]
Get the set of components that have been modified based on the provided files.
- Parameters:
modified_files – Iterable of file paths that have been modified
- Returns:
Set of component names that have been modified
- model_post_init(_CiSettings__context: Any) None
Override this method to perform additional initialization after __init__ and model_construct. This is useful if you want to do some validation that requires the entire model to be initialized.
- CONFIG_FILE_PATH: ClassVar[Path | None] = None
Path to the configuration file to be used (class variable).
- property all_component_mapping_regexes: Set[Pattern]
Get all component mapping regexes as compiled pattern objects.
- Returns:
Set of compiled regex patterns
- property is_in_ci: bool
Check if the code is running in a CI environment.
- Returns:
True if in CI environment, False otherwise
- pydantic settings idf_ci.GitlabEnvVars
Bases:
BaseSettings
Show JSON schema
{ "title": "GitlabEnvVars", "type": "object", "properties": { "CHANGED_FILES_SEMICOLON_SEPARATED": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Changed Files Semicolon Separated" }, "GITLAB_HTTPS_SERVER": { "default": "https://gitlab.com", "title": "Gitlab Https Server", "type": "string" }, "GITLAB_ACCESS_TOKEN": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Gitlab Access Token" }, "IDF_S3_SERVER": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Idf S3 Server" }, "IDF_S3_ACCESS_KEY": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Idf S3 Access Key" }, "IDF_S3_SECRET_KEY": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Idf S3 Secret Key" }, "IDF_PATH": { "default": "", "title": "Idf Path", "type": "string" }, "IDF_CI_IS_DEBUG_PIPELINE": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "title": "Idf Ci Is Debug Pipeline" }, "IDF_CI_SELECT_BY_FILTER_EXPR": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "title": "Idf Ci Select By Filter Expr" }, "IDF_CI_SELECT_ALL_PYTEST_CASES": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "title": "Idf Ci Select All Pytest Cases" }, "IDF_CI_BUILD_ONLY_TEST_RELATED_APPS": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "title": "Idf Ci Build Only Test Related Apps" }, "IDF_CI_BUILD_ONLY_NON_TEST_RELATED_APPS": { "anyOf": [ { "type": "boolean" }, { "type": "null" } ], "default": null, "title": "Idf Ci Build Only Non Test Related Apps" } }, "additionalProperties": false }
- Fields:
- field CHANGED_FILES_SEMICOLON_SEPARATED: str | None = None
Semicolon-separated list of changed files in the pipeline.
- field GITLAB_ACCESS_TOKEN: str | None = None
Access token for GitLab API authentication.
- field GITLAB_HTTPS_SERVER: str = 'https://gitlab.com'
GitLab server URL for API calls.
- field IDF_CI_BUILD_ONLY_NON_TEST_RELATED_APPS: bool | None = None
Flag indicating whether to build only non-test-related apps.
- field IDF_CI_BUILD_ONLY_TEST_RELATED_APPS: bool | None = None
Flag indicating whether to build only test-related apps.
- field IDF_CI_IS_DEBUG_PIPELINE: bool | None = None
Flag indicating whether this is a debug pipeline.
- field IDF_CI_SELECT_ALL_PYTEST_CASES: bool | None = None
Flag indicating whether to select all pytest cases.
- field IDF_CI_SELECT_BY_FILTER_EXPR: str | None = None
Filter expression for selecting pytest cases.
- field IDF_PATH: str = ''
Path to the ESP-IDF directory.
- field IDF_S3_ACCESS_KEY: str | None = None
S3 access key for authentication.
- field IDF_S3_SECRET_KEY: str | None = None
S3 secret key for authentication.
- field IDF_S3_SERVER: str | None = None
S3 server endpoint URL.
- model_post_init(_GitlabEnvVars__context: Any) None
Override this method to perform additional initialization after __init__ and model_construct. This is useful if you want to do some validation that requires the entire model to be initialized.
- property select_all_pytest_cases: bool
Determine if all pytest cases should be selected.
- Returns:
True if this is a full pipeline run, False otherwise
- property select_by_filter_expr: str | None
Get the filter expression for pytest cases.
- Returns:
The filter expression if set, None otherwise
- class idf_ci.IdfPytestPlugin(*, cli_target: str, sdkconfig_name: str | None = None)
Bases:
object
- build_dir(request: FixtureRequest, app_path: str, target: str | None, config: str | None) str
Find a valid build directory based on priority rules.
Checks local build directories in the following order:
build_<target>_<config>
build_<target>
build_<config>
build
- Parameters:
request – Pytest fixture request
app_path – Path to the application
target – Target being used
config – Configuration being used
- Returns:
Valid build directory name
- Raises:
ValueError – If no valid build directory is found
- config(request: FixtureRequest) str
Fixture that provides the configuration for tests.
- Parameters:
request – Pytest fixture request
- Returns:
Configuration string, defaults to ‘default’ if not specified
- static get_case_by_item(item: Item) PytestCase | None
Get the test case associated with a pytest item.
- Parameters:
item – The pytest test item
- Returns:
PytestCase object or None if not found
- pytest_collection_modifyitems(config: Config, items: List[Function])
Filter test cases based on target, sdkconfig, and available apps.
- Parameters:
config – Pytest configuration
items – Collected test items
- pytest_pycollect_makemodule(module_path: Path)
Handle module collection for pytest, mocking any missing modules.
This hook runs before module collection to prevent errors from missing dependencies by automatically mocking them.
- Parameters:
module_path – Path to the module being collected
- pytest_report_collectionfinish(items: List[Function]) None
- target(request: FixtureRequest) str
Fixture that provides the target for tests.
- Parameters:
request – Pytest fixture request
- Returns:
Target string
- Raises:
ValueError – If target parameter is not defined
- class idf_ci.PytestApp(path: str, target: str, config: str)
Bases:
object
Represents a pytest app.
- property build_dir: str
Returns the build directory for the app.
Note
Matches the build_dir (by default build_@t_@w) in the idf-build-apps config file.
- Returns:
The build directory for the app.
- class idf_ci.PytestCase(apps: List[PytestApp], item: Function)
Bases:
object
Represents a pytest test case.
- KNOWN_ENV_MARKERS: ClassVar[Set[str]] = {}
- property all_markers: Set[str]
- property caseid: str
- property configs: List[str]
- property env_markers: Set[str]
- property env_selector: str
- classmethod from_item(item: Function) PytestCase | None
Create a PytestCase from a pytest item.
- Parameters:
item – Pytest function item
- Returns:
PytestCase instance or None if targets not defined
- classmethod get_param(item: Function, key: str, default: Any = None) Any
Get parameter value from pytest item.
- Parameters:
item – Pytest function item
key – Parameter key to retrieve
default – Default value if key not found
- Returns:
Parameter value or default
- get_skip_reason_if_not_built(app_dirs: List[str] | None = None) str | None
Check if all binaries of the test case are built in the app lists.
- Parameters:
app_dirs – App folder paths to check
- Returns:
Skip reason string if not all binaries are built, None otherwise
- property is_host_test: bool
- property is_single_dut: bool
- property name: str
- property path: str
- property runner_tags: Tuple[str, ...]
- property target_selector: str
- property targets: List[str]
- idf_ci.build(*, paths: List[str] | None = None, target: str = 'all', parallel_count: int = 1, parallel_index: int = 1, modified_files: List[str] | None = None, modified_components: List[str] | None = None, only_test_related: bool | None = None, only_non_test_related: bool | None = None, dry_run: bool = False, build_system: UndefinedType | str = __UNDEF__, marker_expr: UndefinedType | str = __UNDEF__, filter_expr: str | None = None) Tuple[List[App], int]
Build applications based on specified parameters.
- Parameters:
paths – List of paths to search for applications
target – Target device(s) separated by commas
parallel_count – Total number of parallel jobs
parallel_index – Index of current parallel job (1-based)
modified_files – List of modified files
modified_components – List of modified components
only_test_related – Only build test-related applications
only_non_test_related – Only build non-test-related applications
dry_run – Do not actually build, just simulate
build_system – Filter the apps by build system. Can be “cmake”, “make” or a custom App class path
marker_expr – Pytest marker expression
filter_expr – Filter expression
- Returns:
Tuple of (built apps, build return code)
- idf_ci.get_all_apps(*, paths: List[str] | None = None, target: str = 'all', modified_files: List[str] | None = None, modified_components: List[str] | None = None, filter_expr: str | None = None, default_build_targets: List[str] | None = None, marker_expr: UndefinedType | str | None = __UNDEF__, compare_manifest_sha_filepath: str | None = None, build_system: UndefinedType | str | None = __UNDEF__) Tuple[List[App], List[App]]
Get test-related and non-test-related applications.
- Parameters:
paths – List of paths to search for applications
target – Target device(s) separated by commas
modified_files – List of modified files
modified_components – List of modified components
filter_expr – Pytest filter expression -k
default_build_targets – Default build targets to use
marker_expr – Pytest marker expression -m
compare_manifest_sha_filepath – Path to the manifest SHA file generated by idf-build-apps dump-manifest-sha
build_system – Filter the apps by build system. Can be “cmake”, “make” or a custom App class path
- Returns:
Tuple of (test_related_apps, non_test_related_apps)
- idf_ci.get_pytest_cases(*, paths: List[str] | None = None, target: str = 'all', sdkconfig_name: str | None = None, marker_expr: UndefinedType | str | None = __UNDEF__, filter_expr: str | None = None) List[PytestCase]
Collect pytest test cases from specified paths.
- Parameters:
paths – List of file system paths to collect test cases from
target – Filter by targets
sdkconfig_name – Filter tests whose apps are built with this sdkconfig name
marker_expr – Filter by pytest marker expression -m
filter_expr – Filter by pytest filter expression -k
- Returns:
List of collected PytestCase objects
- Raises:
RuntimeError – If pytest collection fails