Skip to content
40 changes: 32 additions & 8 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: 'build_scripts/windows/out/'

Expand Down Expand Up @@ -270,6 +271,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: 'build_scripts/windows/out/'

Expand Down Expand Up @@ -370,6 +372,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: $(Build.ArtifactStagingDirectory)
DockerImagesToScan: 'clibuild$BUILD_BUILDNUMBER:latest'
Expand Down Expand Up @@ -451,6 +454,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: $(Build.ArtifactStagingDirectory)

Expand Down Expand Up @@ -621,6 +625,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: $(Build.ArtifactStagingDirectory)

Expand Down Expand Up @@ -732,6 +737,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: $(Build.ArtifactStagingDirectory)

Expand Down Expand Up @@ -822,6 +828,7 @@ jobs:
filePath: scripts/release/rpm/pipeline.sh
- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: $(Build.ArtifactStagingDirectory)
- task: PublishPipelineArtifact@0
Expand Down Expand Up @@ -941,6 +948,7 @@ jobs:

- task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0
displayName: 'SBOM'
continueOnError: true
inputs:
BuildDropPath: $(Build.ArtifactStagingDirectory)

Expand Down Expand Up @@ -1126,8 +1134,9 @@ jobs:
exit 1
fi


- job: CodegenCoverage
condition: in(variables['Build.Reason'], 'BatchedCI', 'IndividualCI')
timeoutInMinutes: 180
displayName: "Codegen Coverage"
continueOnError: true
pool:
Expand All @@ -1147,14 +1156,29 @@ jobs:
azdev extension repo add ./azure-cli-extensions
pip install setuptools==70.0.0 wheel==0.30.0
azdev extension add "*"
pip install msrestazure markupsafe==2.0.1
# Some extension will change the dependence, so run `azdev setup` again after all extensions installed.
azdev setup -c $CLI_REPO_PATH -r ./azure-cli-extensions
# CLI repo only
azdev statistics list-command-table CLI --statistics-only
# CLI + EXT repos
pip install jinja2 -U
azdev statistics list-command-table --statistics-only > /tmp/codegen_report.json
python s/scripts/ci/codegen_report.py
azdev setup -c ./s -r ./azure-cli-extensions

mkdir -p /tmp/module_stats

find /mnt/vss/_work/1/s/src/azure-cli/azure/cli/command_modules/ -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | grep -v '^__pycache__$' > /mnt/vss/_work/1/s/scripts/ci/core_modules.txt
echo "=== Core Modules ==="
cat /mnt/vss/_work/1/s/scripts/ci/core_modules.txt

find /mnt/vss/_work/1/azure-cli-extensions/src/ -mindepth 1 -maxdepth 1 -type d -printf "%f\n" | grep -v '^__pycache__$' > /mnt/vss/_work/1/s/scripts/ci/extension_modules.txt
echo "=== Extension Modules ==="
cat /mnt/vss/_work/1/s/scripts/ci/extension_modules.txt

for module in $(cat /mnt/vss/_work/1/s/scripts/ci/core_modules.txt); do
azdev statistics list-command-table $module --statistics-only > /tmp/module_stats/${module}.json || true
done

for module in $(cat /mnt/vss/_work/1/s/scripts/ci/extension_modules.txt); do
azdev statistics list-command-table $module --statistics-only > /tmp/module_stats/${module}.json || true
done
azdev statistics list-command-table --statistics-only > /tmp/codegen_report.json || true
python /mnt/vss/_work/1/s/scripts/ci/codegen_report.py
env:
BUILD_ID: $(Build.BuildId)
BUILD_BRANCH: $(Build.SourceBranchName)
Expand Down
2 changes: 0 additions & 2 deletions doc/sphinx/azhelpgen/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import pkg_resources
pkg_resources.declare_namespace(__name__)
2 changes: 0 additions & 2 deletions doc/sphinx/cligroup/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import pkg_resources
pkg_resources.declare_namespace(__name__)
88 changes: 86 additions & 2 deletions scripts/ci/codegen_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,88 @@
BUILD_ID = os.environ.get('BUILD_ID', None)
BUILD_BRANCH = os.environ.get('BUILD_BRANCH', None)

def load_module_stats():
stats_dir = "/tmp/module_stats"
all_stats = {}

with open("/mnt/vss/_work/1/s/scripts/ci/core_modules.txt", "r") as f:
core_modules = [line.strip() for line in f.readlines()]

with open("/mnt/vss/_work/1/s/scripts/ci/extension_modules.txt", "r") as f:
extension_modules = [line.strip() for line in f.readlines()]

for module in core_modules + extension_modules:
stats_file = os.path.join(stats_dir, f"{module}.json")
if os.path.exists(stats_file):
with open(stats_file, "r") as f:
try:
stats = json.load(f)
codegenV1 = stats.get("codegenV1", 0)
codegenV2 = stats.get("codegenV2", 0)
total = stats.get("total", 0)
manual = total - codegenV1 - codegenV2
all_stats[module] = {
"codegenV1": codegenV1,
"codegenV2": codegenV2,
"manual": manual,
"total": total,
"type": "core" if module in core_modules else "extension"
}
except json.JSONDecodeError:
print(f"Warning: Could not parse {stats_file}")
return all_stats

def analyze_stats(all_stats):
counters = {
"manual": {"core": 0, "extension": 0},
"mixed": {"core": 0, "extension": 0},
"codegen": {"core": 0, "extension": 0},
"codegenV1": {"core": 0, "extension": 0},
"total": {"core": 0, "extension": 0}
}
for _, stats in all_stats.items():
module_type = stats["type"]
counters["total"][module_type] += 1
if stats["manual"] > 0 and (stats["codegenV1"] > 0 or stats["codegenV2"] > 0):
counters["mixed"][module_type] += 1
if stats["codegenV1"] > 0 or stats["codegenV2"] > 0:
counters["codegen"][module_type] += 1
if stats["codegenV1"] > 0:
counters["codegenV1"][module_type] += 1
counters["manual"]["core"] = counters["total"]["core"] - counters["codegen"]["core"]
counters["manual"]["extension"] = counters["total"]["extension"] - counters["codegen"]["extension"]
return counters

def print_results(counters):
logger.info("\n===== Codegen Coverage Report =====")
logger.info("\n1. Manual Modules:")
logger.info(f" Core: {counters['manual']['core']}")
logger.info(f" Extension: {counters['manual']['extension']}")
logger.info("\n2. Mixed Modules:")
logger.info(f" Core: {counters['mixed']['core']}")
logger.info(f" Extension: {counters['mixed']['extension']}")
logger.info("\n3. Codegen Modules:")
logger.info(f" Core: {counters['codegen']['core']}")
logger.info(f" Extension: {counters['codegen']['extension']}")
logger.info("\n4. CodegenV1 Modules:")
logger.info(f" Core: {counters['codegenV1']['core']}")
logger.info(f" Extension: {counters['codegenV1']['extension']}")
logger.info("\n5. Total Modules:")
logger.info(f" Core: {counters['total']['core']}")
logger.info(f" Extension: {counters['total']['extension']}")

def analyze_and_report():
all_stats = load_module_stats()
counters = analyze_stats(all_stats)
print_results(counters)
output = {
"detailed_stats": all_stats,
"summary": counters
}
logger.info("\n=== Detailed JSON Output ===")
logger.info(json.dumps(output, indent=2))
with open("/tmp/module_stats_summary.json", "w") as f:
json.dump(output, f, indent=2)

def generate_csv():
data = []
Expand All @@ -31,9 +113,11 @@ def generate_csv():
is_release = True if BUILD_BRANCH == 'release' else False
date = (datetime.datetime.utcnow() + datetime.timedelta(hours=8)).strftime("%Y-%m-%d")
data.append([BUILD_ID, manual, codegenv1, codegenv2, total, is_release, date])
logger.info(f'Finish generate data for codegen report: {data}')
logger.info('Finish generate data for codegen report:')
logger.info("BUILD_ID, manual, codegenv1, codegenv2, total, is_release, date")
logger.info(f'{data}')
return data


if __name__ == '__main__':
analyze_and_report()
generate_csv()
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import pkg_resources
pkg_resources.declare_namespace(__name__)
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,3 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------
import pkg_resources
pkg_resources.declare_namespace(__name__)
4 changes: 2 additions & 2 deletions tools/automation/verify/verify_packages.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import filecmp
import logging
import unittest
from pkg_resources import working_set
from importlib.metadata import distributions

import automation.utilities.path as automation_path
from automation.utilities.const import COMMAND_MODULE_PREFIX
Expand Down Expand Up @@ -48,7 +48,7 @@ def test_azure_cli_installation(self):
def test_azure_cli_module_installation(self):
expected_modules = set([n for n, _ in automation_path.get_command_modules_paths(include_prefix=True)])

installed_command_modules = [dist.key for dist in list(working_set) if dist.key.startswith(COMMAND_MODULE_PREFIX)]
installed_command_modules = [dist.metadata['Name'] for dist in distributions() if dist.metadata['Name'].startswith(COMMAND_MODULE_PREFIX)]

logger.info('Installed command modules %s', installed_command_modules)

Expand Down
Loading