Merge branch 'ci/fix-deploy-jobs-rules' into 'master'

ci: improve deploy rules

Closes IDFCI-2938

See merge request espressif/esp-idf!39068
This commit is contained in:
Fu Hanxi
2025-05-14 15:11:10 +08:00
9 changed files with 91 additions and 110 deletions

View File

@@ -314,6 +314,7 @@ build_child_pipeline:
PARENT_PIPELINE_ID: $CI_PIPELINE_ID PARENT_PIPELINE_ID: $CI_PIPELINE_ID
BUILD_AND_TEST_ALL_APPS: $BUILD_AND_TEST_ALL_APPS BUILD_AND_TEST_ALL_APPS: $BUILD_AND_TEST_ALL_APPS
REPORT_EXIT_CODE: $REPORT_EXIT_CODE REPORT_EXIT_CODE: $REPORT_EXIT_CODE
OOCD_DISTRO_URL: $OOCD_DISTRO_URL
# https://gitlab.com/gitlab-org/gitlab/-/issues/214340 # https://gitlab.com/gitlab-org/gitlab/-/issues/214340
inherit: inherit:
variables: false variables: false

View File

@@ -3,7 +3,6 @@
image: $ESP_ENV_IMAGE image: $ESP_ENV_IMAGE
tags: [ deploy ] tags: [ deploy ]
# Check this before push_to_github
check_submodule_sync: check_submodule_sync:
extends: extends:
- .deploy_job_template - .deploy_job_template
@@ -31,8 +30,9 @@ push_to_github:
extends: extends:
- .deploy_job_template - .deploy_job_template
- .before_script:minimal - .before_script:minimal
- .rules:push_to_github - .rules:protected:deploy
needs: needs:
# submodule must be synced before pushing to github
- check_submodule_sync - check_submodule_sync
tags: [ brew, github_sync ] tags: [ brew, github_sync ]
variables: variables:
@@ -50,7 +50,7 @@ deploy_update_SHA_in_esp-dockerfiles:
extends: extends:
- .deploy_job_template - .deploy_job_template
- .before_script:minimal - .before_script:minimal
- .rules:protected-no_label-always - .rules:protected:deploy
dependencies: [] dependencies: []
variables: variables:
GIT_DEPTH: 2 GIT_DEPTH: 2

View File

@@ -19,12 +19,9 @@
.patterns-docs-preview: &patterns-docs-preview .patterns-docs-preview: &patterns-docs-preview
- "docs/**/*" - "docs/**/*"
.if-protected: &if-protected .if-protected-check: &if-protected-check
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/)' if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/)'
.if-protected-no_label: &if-protected-no_label
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
.if-qa-test-tag: &if-qa-test-tag .if-qa-test-tag: &if-qa-test-tag
if: '$CI_COMMIT_TAG =~ /^qa-test/' if: '$CI_COMMIT_TAG =~ /^qa-test/'
@@ -41,7 +38,7 @@
rules: rules:
- <<: *if-qa-test-tag - <<: *if-qa-test-tag
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build_docs - <<: *if-label-build_docs
- <<: *if-label-docs_full - <<: *if-label-docs_full
- <<: *if-dev-push - <<: *if-dev-push
@@ -64,7 +61,7 @@ check_readme_links:
tags: ["build", "amd64", "internet"] tags: ["build", "amd64", "internet"]
allow_failure: true allow_failure: true
rules: rules:
- <<: *if-protected - <<: *if-protected-check
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-example-readme changes: *patterns-example-readme
script: script:
@@ -188,8 +185,7 @@ deploy_docs_production:
# The DOCS_PROD_* variables used by this job are "Protected" so these branches must all be marked "Protected" in Gitlab settings # The DOCS_PROD_* variables used by this job are "Protected" so these branches must all be marked "Protected" in Gitlab settings
extends: extends:
- .deploy_docs_template - .deploy_docs_template
rules: - .rules:protected:deploy
- <<: *if-protected-no_label
stage: post_deploy stage: post_deploy
dependencies: # set dependencies to null to avoid missing artifacts issue dependencies: # set dependencies to null to avoid missing artifacts issue
needs: # ensure runs after push_to_github succeeded needs: # ensure runs after push_to_github succeeded
@@ -208,8 +204,7 @@ deploy_docs_production:
check_doc_links: check_doc_links:
extends: extends:
- .build_docs_template - .build_docs_template
rules: - .rules:protected:deploy
- <<: *if-protected-no_label
stage: post_deploy stage: post_deploy
needs: needs:
- job: deploy_docs_production - job: deploy_docs_production

View File

@@ -1,7 +1,11 @@
generate_failed_jobs_report: .post_deploy_template:
stage: post_deploy stage: post_deploy
tags: [build, shiny]
image: $ESP_ENV_IMAGE image: $ESP_ENV_IMAGE
generate_failed_jobs_report:
extends:
- .post_deploy_template
tags: [build, shiny]
when: always when: always
dependencies: [] # Do not download artifacts from the previous stages dependencies: [] # Do not download artifacts from the previous stages
artifacts: artifacts:
@@ -13,12 +17,13 @@ generate_failed_jobs_report:
- python tools/ci/dynamic_pipelines/scripts/generate_report.py --report-type job - python tools/ci/dynamic_pipelines/scripts/generate_report.py --report-type job
sync_support_status: sync_support_status:
stage: post_deploy
extends: extends:
- .rules:sync_support_status - .post_deploy_template
- .rules:master:push
tags: [ brew, github_sync ]
needs: needs:
- push_to_github - push_to_github
image: $ESP_ENV_IMAGE cache: []
tags: [ brew, github_sync ] before_script: []
script: script:
- curl --fail --request POST --form token="$IDF_STATUS_TRIG_TOKEN" --form ref="$IDF_STATUS_BRANCH" --form "variables[UPLOAD_TO_S3]=true" "$IDF_STATUS_TRIG_URL" - curl --fail --request POST --form token="$IDF_STATUS_TRIG_TOKEN" --form ref="$IDF_STATUS_BRANCH" --form "variables[UPLOAD_TO_S3]=true" "$IDF_STATUS_TRIG_URL"

View File

@@ -10,7 +10,7 @@ check_version:
# esp_idf_version.h in a branch before tagging the next version. # esp_idf_version.h in a branch before tagging the next version.
extends: extends:
- .pre_check_template - .pre_check_template
- .rules:protected - .rules:protected:check
tags: [ brew, github_sync ] tags: [ brew, github_sync ]
variables: variables:
# need a full clone to get the latest tag # need a full clone to get the latest tag

View File

@@ -167,22 +167,19 @@
############## ##############
# if anchors # # if anchors #
############## ##############
.if-ref-master: &if-ref-master .if-master-push: &if-master-push
if: '$CI_COMMIT_REF_NAME == "master"' if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "push"'
.if-ref-master-no_label: &if-ref-master-no_label .if-release-tag: &if-release-tag
if: '$CI_COMMIT_REF_NAME == "master" && $BOT_TRIGGER_WITH_LABEL == null'
.if-tag-release: &if-tag-release
if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/' if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/'
.if-protected: &if-protected .if-protected-check: &if-protected-check
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) || $CI_COMMIT_TAG =~ /^qa-test/' if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) || $CI_COMMIT_TAG =~ /^qa-test/'
.if-protected-no_label: &if-protected-no_label .if-protected-deploy: &if-protected-deploy
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null' if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "api")'
.if-protected-ref-push: &if-protected-ref-push .if-protected-branch-push: &if-protected-branch-push
# rules:changes always evaluates to true for new branch pipelines or when there is no Git push event # rules:changes always evaluates to true for new branch pipelines or when there is no Git push event
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"' if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
@@ -192,9 +189,6 @@
.if-dev-push: &if-dev-push .if-dev-push: &if-dev-push
if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event")' if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event")'
.if-schedule: &if-schedule
if: '$CI_PIPELINE_SOURCE == "schedule"'
.if-schedule-nightly: &if-schedule-nightly .if-schedule-nightly: &if-schedule-nightly
if: '$CI_PIPELINE_SOURCE == "schedule" && $INCLUDE_NIGHTLY_RUN == "1"' if: '$CI_PIPELINE_SOURCE == "schedule" && $INCLUDE_NIGHTLY_RUN == "1"'
@@ -214,51 +208,41 @@
# Rules # # Rules #
######### #########
### Branches ### ### Branches ###
.rules:protected: .rules:protected:check:
rules: rules:
- <<: *if-protected - <<: *if-protected-check
.rules:push_to_github: .rules:protected:deploy:
rules: rules:
- <<: *if-qa-test-tag - <<: *if-qa-test-tag
when: never when: never
- <<: *if-protected-no_label - <<: *if-protected-deploy
# Not uploading on release branches .rules:master:push:
.rules:sync_support_status:
rules: rules:
- <<: *if-ref-master-no_label - <<: *if-master-push
.rules:protected-no_label-always:
rules:
- <<: *if-qa-test-tag
when: never
- <<: *if-protected-no_label
when: always
.rules:tag:release: .rules:tag:release:
rules: rules:
- <<: *if-tag-release - <<: *if-release-tag
.rules:dev-push: .rules:dev-push:
rules: rules:
- <<: *if-dev-push - <<: *if-dev-push
# Do not upload caches on dev branches by default
.rules:upload-python-cache: .rules:upload-python-cache:
rules: rules:
- <<: *if-tag-release - <<: *if-release-tag
- <<: *if-schedule-nightly - <<: *if-schedule-nightly
- <<: *if-protected-ref-push - <<: *if-protected-branch-push
changes: *patterns-python-cache changes: *patterns-python-cache
- <<: *if-label-upload_cache - <<: *if-label-upload_cache
when: manual when: manual
.rules:upload-submodule-cache: .rules:upload-submodule-cache:
rules: rules:
# Needn't upload submodule cache in schedule pipeline - <<: *if-release-tag
- <<: *if-tag-release - <<: *if-protected-branch-push
- <<: *if-protected-ref-push
changes: *patterns-submodule changes: *patterns-submodule
- <<: *if-label-upload_cache - <<: *if-label-upload_cache
when: manual when: manual
@@ -266,11 +250,10 @@
### Patterns ### ### Patterns ###
.rules:patterns:clang_tidy: .rules:patterns:clang_tidy:
rules: rules:
- <<: *if-protected - <<: *if-protected-check
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-c-files changes: *patterns-c-files
#.rules:patterns:static-code-analysis-preview: #.rules:patterns:static-code-analysis-preview:
# rules: # rules:
# - <<: *if-dev-push # - <<: *if-dev-push
@@ -282,7 +265,7 @@
.rules:patterns:idf-pytest-plugin: .rules:patterns:idf-pytest-plugin:
rules: rules:
- <<: *if-protected - <<: *if-protected-check
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-idf-pytest-plugin changes: *patterns-idf-pytest-plugin
@@ -326,7 +309,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build - <<: *if-label-build
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-build_components changes: *patterns-build_components
@@ -339,7 +322,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build - <<: *if-label-build
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-build_check changes: *patterns-build_check
@@ -354,7 +337,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build - <<: *if-label-build
- <<: *if-label-docker - <<: *if-label-docker
- <<: *if-dev-push - <<: *if-dev-push
@@ -370,7 +353,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build - <<: *if-label-build
- <<: *if-label-macos - <<: *if-label-macos
- <<: *if-label-macos_test - <<: *if-label-macos_test
@@ -385,7 +368,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build - <<: *if-label-build
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-build_components changes: *patterns-build_components
@@ -415,7 +398,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build-only - <<: *if-label-build-only
when: never when: never
- <<: *if-label-host_test - <<: *if-label-host_test
@@ -426,7 +409,7 @@
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch
when: never when: never
- <<: *if-protected - <<: *if-protected-check
- <<: *if-label-build-only - <<: *if-label-build-only
when: never when: never
- <<: *if-label-submodule - <<: *if-label-submodule

View File

@@ -85,7 +85,7 @@ clang_tidy_check:
#code_quality_report: #code_quality_report:
# extends: # extends:
# - .sonar_scan_template # - .sonar_scan_template
# - .rules:protected # - .rules:protected:check
# allow_failure: true # it's using exit code to indicate the code analysis result, # allow_failure: true # it's using exit code to indicate the code analysis result,
# # we don't want to block ci when critical issues founded # # we don't want to block ci when critical issues founded
# script: # script:

View File

@@ -37,6 +37,7 @@ Pytest Target Test Jobs:
needs: needs:
- generate_pytest_child_pipeline - generate_pytest_child_pipeline
variables: variables:
OOCD_DISTRO_URL: $OOCD_DISTRO_URL
PARENT_PIPELINE_ID: $PARENT_PIPELINE_ID PARENT_PIPELINE_ID: $PARENT_PIPELINE_ID
REPORT_EXIT_CODE: $REPORT_EXIT_CODE REPORT_EXIT_CODE: $REPORT_EXIT_CODE
# https://gitlab.com/gitlab-org/gitlab/-/issues/214340 # https://gitlab.com/gitlab-org/gitlab/-/issues/214340

View File

@@ -1,30 +1,24 @@
#!/usr/bin/env python #!/usr/bin/env python
# #
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import argparse import argparse
import inspect import inspect
import os import os
import sys import sys
import typing as t
from collections import defaultdict from collections import defaultdict
from itertools import product from itertools import product
import yaml import yaml
from idf_ci_utils import GitlabYmlConfig
from idf_ci_utils import IDF_PATH from idf_ci_utils import IDF_PATH
from idf_ci_utils import GitlabYmlConfig
try: if t.TYPE_CHECKING:
import pygraphviz as pgv import pygraphviz as pgv
except ImportError: # used when pre-commit, skip generating image
pass
try:
from typing import Union
except ImportError: # used for type hint
pass
def _list(str_or_list): # type: (Union[str, list]) -> list def _list(str_or_list: t.Union[str, t.List]) -> t.List:
if isinstance(str_or_list, str): if isinstance(str_or_list, str):
return [str_or_list] return [str_or_list]
elif isinstance(str_or_list, list): elif isinstance(str_or_list, list):
@@ -33,7 +27,7 @@ def _list(str_or_list): # type: (Union[str, list]) -> list
raise ValueError('Wrong type: {}. Only supports str or list.'.format(type(str_or_list))) raise ValueError('Wrong type: {}. Only supports str or list.'.format(type(str_or_list)))
def _format_nested_dict(_dict, f_tuple): # type: (dict[str, dict], tuple[str, ...]) -> dict[str, dict] def _format_nested_dict(_dict: t.Dict[str, t.Dict], f_tuple: t.Tuple[str, ...]) -> t.Dict[str, t.Dict]:
res = {} res = {}
for k, v in _dict.items(): for k, v in _dict.items():
k = k.split('__')[0] k = k.split('__')[0]
@@ -47,7 +41,7 @@ def _format_nested_dict(_dict, f_tuple): # type: (dict[str, dict], tuple[str, .
return res return res
def _format_nested_list(_list, f_tuple): # type: (list[str], tuple[str, ...]) -> list[str] def _format_nested_list(_list: t.List[str], f_tuple: t.Tuple[str, ...]) -> t.List[str]:
res = [] res = []
for item in _list: for item in _list:
if isinstance(item, list): if isinstance(item, list):
@@ -61,26 +55,23 @@ def _format_nested_list(_list, f_tuple): # type: (list[str], tuple[str, ...]) -
class RulesWriter: class RulesWriter:
AUTO_GENERATE_MARKER = inspect.cleandoc(r''' AUTO_GENERATE_MARKER = inspect.cleandoc(r"""
################## ##################
# Auto Generated # # Auto Generated #
################## ##################
''') """)
LABEL_TEMPLATE = inspect.cleandoc(r''' LABEL_TEMPLATE = inspect.cleandoc(r"""
.if-label-{0}: &if-label-{0} .if-label-{0}: &if-label-{0}
if: '$BOT_LABEL_{1} || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*{0}(?:,[^,\n\r]+)*$/i' if: '$BOT_LABEL_{1} || $CI_MERGE_REQUEST_LABELS =~ /^(?:[^,\n\r]+,)*{0}(?:,[^,\n\r]+)*$/i'
''') """)
RULE_PROTECTED = ' - <<: *if-protected' RULE_PROTECTED_CHECK = ' - <<: *if-protected-check'
RULE_PROTECTED_NO_LABEL = ' - <<: *if-protected-no_label' RULE_PROTECTED_PUSH = ' - <<: *if-protected-push'
RULE_BUILD_ONLY = ' - <<: *if-label-build-only\n' \ RULE_BUILD_ONLY = ' - <<: *if-label-build-only\n when: never'
' when: never' RULE_REVERT_BRANCH = ' - <<: *if-revert-branch\n when: never'
RULE_REVERT_BRANCH = ' - <<: *if-revert-branch\n' \
' when: never'
RULE_LABEL_TEMPLATE = ' - <<: *if-label-{0}' RULE_LABEL_TEMPLATE = ' - <<: *if-label-{0}'
RULE_PATTERN_TEMPLATE = ' - <<: *if-dev-push\n' \ RULE_PATTERN_TEMPLATE = ' - <<: *if-dev-push\n changes: *patterns-{0}'
' changes: *patterns-{0}'
SPECIFIC_RULE_TEMPLATE = ' - <<: *{0}' SPECIFIC_RULE_TEMPLATE = ' - <<: *{0}'
RULES_TEMPLATE = inspect.cleandoc(r""" RULES_TEMPLATE = inspect.cleandoc(r"""
.rules:{0}: .rules:{0}:
@@ -120,7 +111,7 @@ class RulesWriter:
return res return res
@staticmethod @staticmethod
def _expand_matrix(name, cfg): # type: (str, dict) -> dict def _expand_matrix(name: str, cfg: t.Dict[str, t.Any]) -> t.Dict[str, t.Any]:
""" """
Expand matrix into multi keys Expand matrix into multi keys
:param cfg: single rule dict :param cfg: single rule dict
@@ -138,7 +129,7 @@ class RulesWriter:
res.update(_format_nested_dict(default, comb)) res.update(_format_nested_dict(default, comb))
return res return res
def expand_rules(self): # type: () -> dict[str, dict[str, list]] def expand_rules(self) -> t.Dict[str, t.Dict[str, t.List[str]]]:
res = defaultdict(lambda: defaultdict(set)) # type: dict[str, dict[str, set]] res = defaultdict(lambda: defaultdict(set)) # type: dict[str, dict[str, set]]
for k, v in self.cfg.items(): for k, v in self.cfg.items():
if not v: if not v:
@@ -169,13 +160,13 @@ class RulesWriter:
continue continue
res[item]['patterns'].add(_pat) res[item]['patterns'].add(_pat)
sorted_res = defaultdict(lambda: defaultdict(list)) # type: dict[str, dict[str, list]] sorted_res = defaultdict(lambda: defaultdict(list)) # type: t.Dict[str, t.Dict[str, t.List[str]]]
for k, v in res.items(): for k, v in res.items():
for vk, vv in v.items(): for vk, vv in v.items():
sorted_res[k][vk] = sorted(vv) sorted_res[k][vk] = sorted(vv)
return sorted_res return sorted_res
def new_labels_str(self): # type: () -> str def new_labels_str(self) -> str:
_labels = set([]) _labels = set([])
for k, v in self.cfg.items(): for k, v in self.cfg.items():
if not v: if not v:
@@ -191,14 +182,14 @@ class RulesWriter:
return res return res
@classmethod @classmethod
def _format_label(cls, label): # type: (str) -> str def _format_label(cls, label: str) -> str:
return cls.LABEL_TEMPLATE.format(label, cls.bot_label_str(label)) return cls.LABEL_TEMPLATE.format(label, cls.bot_label_str(label))
@staticmethod @staticmethod
def bot_label_str(label): # type: (str) -> str def bot_label_str(label: str) -> str:
return label.upper().replace('-', '_') return label.upper().replace('-', '_')
def new_rules_str(self): # type: () -> str def new_rules_str(self) -> str:
res = [] res = []
for k, v in sorted(self.rules.items()): for k, v in sorted(self.rules.items()):
if k.startswith('pattern'): if k.startswith('pattern'):
@@ -211,13 +202,13 @@ class RulesWriter:
res.append(self.RULES_TEMPLATE.format(k, self._format_rule(k, v))) res.append(self.RULES_TEMPLATE.format(k, self._format_rule(k, v)))
return '\n\n'.join(res) return '\n\n'.join(res)
def _format_rule(self, name, cfg): # type: (str, dict) -> str def _format_rule(self, name: str, cfg: t.Dict[str, t.Any]) -> str:
_rules = [self.RULE_REVERT_BRANCH] _rules = [self.RULE_REVERT_BRANCH]
if name.endswith('-production'): if name.endswith('-production'):
_rules.append(self.RULE_PROTECTED_NO_LABEL) _rules.append(self.RULE_PROTECTED_PUSH)
else: else:
if not (name.endswith('-preview') or name.startswith('labels:')): if not (name.endswith('-preview') or name.startswith('labels:')):
_rules.append(self.RULE_PROTECTED) _rules.append(self.RULE_PROTECTED_CHECK)
if name.startswith('test:'): if name.startswith('test:'):
_rules.append(self.RULE_BUILD_ONLY) _rules.append(self.RULE_BUILD_ONLY)
@@ -235,7 +226,7 @@ class RulesWriter:
print('WARNING: pattern {} not exists'.format(pattern)) print('WARNING: pattern {} not exists'.format(pattern))
return '\n'.join(_rules) return '\n'.join(_rules)
def update_rules_yml(self): # type: () -> bool def update_rules_yml(self) -> bool:
with open(self.rules_yml) as fr: with open(self.rules_yml) as fr:
file_str = fr.read() file_str = fr.read()
@@ -255,7 +246,9 @@ PATTERN_COLOR = 'cyan'
RULE_COLOR = 'blue' RULE_COLOR = 'blue'
def build_graph(rules_dict): # type: (dict[str, dict[str, list]]) -> pgv.AGraph def build_graph(rules_dict: t.Dict[str, t.Dict[str, t.List[str]]]) -> 'pgv.AGraph':
from pygraphviz import pgv
graph = pgv.AGraph(directed=True, rankdir='LR', concentrate=True) graph = pgv.AGraph(directed=True, rankdir='LR', concentrate=True)
for k, v in rules_dict.items(): for k, v in rules_dict.items():
@@ -281,7 +274,7 @@ def build_graph(rules_dict): # type: (dict[str, dict[str, list]]) -> pgv.AGraph
return graph return graph
def output_graph(graph, output_path='output.png'): # type: (pgv.AGraph, str) -> None def output_graph(graph: 'pgv.AGraph', output_path: str = 'output.png') -> None:
graph.layout('dot') graph.layout('dot')
if output_path.endswith('.png'): if output_path.endswith('.png'):
img_path = output_path img_path = output_path
@@ -292,13 +285,16 @@ def output_graph(graph, output_path='output.png'): # type: (pgv.AGraph, str) ->
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__) parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('rules_yml', nargs='?', default=os.path.join(IDF_PATH, '.gitlab', 'ci', 'rules.yml'), parser.add_argument(
help='rules.yml file path') 'rules_yml', nargs='?', default=os.path.join(IDF_PATH, '.gitlab', 'ci', 'rules.yml'), help='rules.yml file path'
parser.add_argument('dependencies_yml', nargs='?', default=os.path.join(IDF_PATH, '.gitlab', 'ci', 'dependencies', )
'dependencies.yml'), parser.add_argument(
help='dependencies.yml file path') 'dependencies_yml',
parser.add_argument('--graph', nargs='?',
help='Specify PNG image output path. Use this argument to generate dependency graph') default=os.path.join(IDF_PATH, '.gitlab', 'ci', 'dependencies', 'dependencies.yml'),
help='dependencies.yml file path',
)
parser.add_argument('--graph', help='Specify PNG image output path. Use this argument to generate dependency graph')
args = parser.parse_args() args = parser.parse_args()
writer = RulesWriter(args.rules_yml, args.dependencies_yml) writer = RulesWriter(args.rules_yml, args.dependencies_yml)