-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate pom file for aggregate code coverage #29035
Merged
Merged
Changes from 17 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
f14c06c
Generate pom file for aggregate code coverage
srnagar 62a9ba8
fix version tag
srnagar 082b8cc
fix parent path
srnagar 8042b4f
ignore multi-release source files
srnagar 0d36cd6
fix coverage path
srnagar d5d3ec5
update coverage file location
srnagar 6a63324
update coverage file location
srnagar 40efefd
list target directory
srnagar 15b51a0
list all files
srnagar aa2f3cc
fix local of coverage report
srnagar b00cba3
fix location of coverage report
srnagar 518542b
skip resourcemanagerhybrid path
srnagar 4068543
run pom generation step
srnagar 2464aa6
remove condition
srnagar 76ae327
remove profile
srnagar a5b4111
sorted modules
srnagar 8c08282
update copy source path
srnagar 69e6ad4
Merge remote-tracking branch 'upstream/main' into aggregate-coverage
srnagar e47c408
update .gitignore
srnagar ce33320
address pr comments
srnagar File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -66,7 +66,6 @@ stages: | |
publishJUnitResults: false | ||
goals: 'clean package' | ||
|
||
|
||
- task: Maven@3 | ||
displayName: 'Generate Aggregate JavaDocs' | ||
inputs: | ||
|
@@ -79,17 +78,25 @@ stages: | |
publishJUnitResults: false | ||
goals: 'javadoc:aggregate' | ||
|
||
# Generate the pom file with all the modules required for creating an aggregate code coverage report | ||
- task: PythonScript@0 | ||
displayName: 'Generate pom for aggregate code coverage report' | ||
inputs: | ||
scriptPath: 'eng/scripts/generate_aggregate_coverage_pom.py' | ||
arguments: '--groups com.azure' | ||
workingDirectory: '$(System.DefaultWorkingDirectory)' | ||
|
||
- task: Maven@3 | ||
displayName: 'Generate Aggregate JaCoCo coverage report' | ||
inputs: | ||
mavenPomFile: pom.xml | ||
options: '$(DefaultOptions) -T 2C -Dinclude-non-shipping-modules -Dgpg.skip=true -Drevapi.skip=true -Dcodesnippet.skip=true -Pjacoco -Dcheckstyle.skip=true -Dmaven.javadoc.skip=true -Dspotbugs.skip=true -DskipCompile=true -DskipTestCompile=true' | ||
mavenPomFile: aggregate-coverage-pom.xml | ||
options: '$(DefaultOptions) -T 2C -Dinclude-non-shipping-modules -Dgpg.skip=true -Drevapi.skip=true -Dcodesnippet.skip=true -Dcheckstyle.skip=true -Dmaven.javadoc.skip=true -Dspotbugs.skip=true -DskipCompile=true -DskipTestCompile=true' | ||
mavenOptions: '$(MemoryOptions) $(LoggingOptions)' | ||
javaHomeOption: 'JDKVersion' | ||
jdkVersionOption: $(JavaBuildVersion) | ||
jdkArchitectureOption: 'x64' | ||
publishJUnitResults: false | ||
goals: 'verify jacoco:report-aggregate' | ||
goals: 'jacoco:report-aggregate' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm just curious, why was the verify target removed here? |
||
|
||
- task: PublishTestResults@2 | ||
condition: succeededOrFailed() | ||
|
@@ -120,7 +127,7 @@ stages: | |
|
||
- pwsh: | | ||
Copy-Item -Path target/site/apidocs -Destination $(Build.ArtifactStagingDirectory)/staging/apidocs -Force -Recurse | ||
Copy-Item -Path eng/jacoco-test-coverage/target/site/test-coverage -Destination $(Build.ArtifactStagingDirectory)/staging/test-coverage -Force -Recurse | ||
Copy-Item -Path target/site/test-coverage -Destination $(Build.ArtifactStagingDirectory)/staging/test-coverage -Force -Recurse | ||
Copy-Item eng/code-quality-reports/src/main/resources/index.html $(Build.ArtifactStagingDirectory) | ||
Copy-Item eng/code-quality-reports/src/main/resources/dependency-allowlist.html $(Build.ArtifactStagingDirectory)/staging | ||
Copy-Item data.js $(Build.ArtifactStagingDirectory)/staging | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
# Copyright (c) Microsoft Corporation. All rights reserved. | ||
# Licensed under the MIT License. | ||
|
||
# Python version 3.4 or higher is required to run this script. | ||
|
||
# Use case: Creates an aggregate POM which contains all modules for which aggregate code coverage will be reported. | ||
# | ||
# Flags | ||
# --project-list/--pl: List of projects included in the generated pom. If no projects are specified all projects defined in version_client.txt will be included | ||
# --groups/--g: List of comma-separate Maven groups to include in generated pom. If no groups are specified all track 2 groups (com.azure, com.azure.resourcemanager and com.azure.spring) will be included. | ||
# | ||
# For example: To create an aggregate POM for Azure Storage | ||
# python eng/scripts/generate_aggregate_coverage_pom.py --pl com.azure:azure-storage-blob,com.azure:azure-storage-common,... | ||
# | ||
# The script must be run at the root of azure-sdk-for-java. | ||
|
||
import argparse | ||
from datetime import timedelta | ||
import os | ||
import time | ||
from typing import Dict | ||
from pom_helper import * | ||
|
||
# azure-client-sdk-parent valid parent POMs for Track 2 libraries. | ||
valid_parents = ['com.azure:azure-client-sdk-parent'] | ||
|
||
# List of parent POMs that should be retained as projects to create POM. | ||
parent_pom_identifiers = ['com.azure:azure-sdk-parent', 'com.azure:azure-client-sdk-parent'] | ||
|
||
include_groups = [] | ||
|
||
# From this file get to the root path of the repo. | ||
root_path = os.path.normpath(os.path.abspath(__file__) + '/../../../') | ||
|
||
# From the root of the repo get to the version_client.txt file in eng/versioning. | ||
client_versions_path = os.path.normpath(root_path + '/eng/versioning/version_client.txt') | ||
|
||
external_dependency_versions_path = os.path.normpath(root_path + '/eng/versioning/external_dependencies.txt') | ||
|
||
# File path where the aggregate POM will be written. | ||
client_aggregate_pom_path = os.path.join(root_path, 'aggregate-coverage-pom.xml') | ||
|
||
jacoco_artifact_id = 'org.jacoco:jacoco-maven-plugin' | ||
|
||
jacoco_build = ''' | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.jacoco</groupId> | ||
<artifactId>jacoco-maven-plugin</artifactId> | ||
<version>{}</version> | ||
<configuration> | ||
<outputDirectory>target/site/test-coverage</outputDirectory> | ||
<excludes> | ||
<exclude>META-INF/**</exclude> | ||
</excludes> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
''' | ||
|
||
|
||
def create_aggregate_coverage_pom(project_list: str, groups: str): | ||
|
||
if groups is None: | ||
include_groups.append('com.azure') | ||
include_groups.append('com.azure.spring') | ||
include_groups.append('com.azure.resourcemanager') | ||
else: | ||
for group in groups.split(','): | ||
include_groups.append(group) | ||
|
||
# Get the artifact identifiers from client_versions.txt to act as our source of truth. | ||
artifact_identifier_to_version = load_client_artifact_identifiers() | ||
|
||
if project_list is None: | ||
project_list = ','.join(artifact_identifier_to_version.keys()) | ||
|
||
project_list_identifiers = project_list.split(',') | ||
|
||
external_dependency_version = load_external_dependency_version() | ||
|
||
projects = create_projects(project_list_identifiers, artifact_identifier_to_version) | ||
|
||
with open(file=client_aggregate_pom_path, mode='w') as aggregateCoveragePom: | ||
aggregateCoveragePom.write(pom_file_start.format('azure-sdk-aggregate-coverage')) | ||
aggregateCoveragePom.write(start_modules) | ||
dependencies = '' | ||
|
||
for project in sorted(projects.values(), key=lambda x: x.module_path): | ||
project_id = project.identifier | ||
if project_id not in project_list_identifiers: | ||
continue | ||
|
||
aggregateCoveragePom.write(' <module>{}</module>\n'.format(project.module_path)) | ||
|
||
dependency_id = artifact_identifier_to_version[project_id] | ||
dependencies += dependency_template.format(dependency_id.group_id, dependency_id.artifact_id, dependency_id.current_version) | ||
|
||
aggregateCoveragePom.write(end_modules) | ||
aggregateCoveragePom.write(start_dependencies) | ||
aggregateCoveragePom.write(dependencies) | ||
aggregateCoveragePom.write(end_dependencies) | ||
aggregateCoveragePom.write(jacoco_build.format(external_dependency_version[jacoco_artifact_id])) | ||
aggregateCoveragePom.write(pom_file_end) | ||
|
||
|
||
# Function that creates the Projects within the repository. | ||
# Projects contain a Maven identifier, module path, parent POM | ||
def create_projects(project_list_identifiers: list, artifact_identifier_to_version: Dict[str, ArtifactVersion]) -> Dict[str, Project]: | ||
projects: Dict[str, Project] = {} | ||
|
||
for root, _, files in os.walk(root_path): | ||
# Ignore sdk/resourcemanagerhybrid | ||
if 'resourcemanagerhybrid' in root: | ||
continue | ||
|
||
for file_name in files: | ||
file_path = root + os.sep + file_name | ||
|
||
# Only parse files that are pom.xml files. | ||
if (file_name.startswith('pom') and file_name.endswith('.xml')): | ||
project = create_project_for_pom(file_path, project_list_identifiers) | ||
if project is not None: | ||
projects[project.identifier] = project | ||
|
||
return projects | ||
|
||
|
||
def create_project_for_pom(pom_path: str, project_list_identifiers: list): | ||
if 'eng' in pom_path.split(os.sep): | ||
return | ||
|
||
tree = ET.parse(pom_path) | ||
tree_root = tree.getroot() | ||
|
||
project_identifier = create_artifact_identifier(tree_root) | ||
module_path = pom_path.replace(root_path, '').replace('\\', '/') | ||
directory_path = module_path[:module_path.rindex('/')] | ||
parent_pom = get_parent_pom(tree_root) | ||
|
||
group_id = element_find(tree_root, 'groupId') | ||
|
||
# If the project isn't a track 2 POM skip it and not one of the project list identifiers. | ||
if not project_identifier in project_list_identifiers \ | ||
or parent_pom not in valid_parents \ | ||
or group_id.text not in include_groups: | ||
return | ||
|
||
project = Project(project_identifier, directory_path, module_path, parent_pom) | ||
return project | ||
|
||
|
||
# Function that loads and parses client_versions.txt into an artifact identifier - source version mapping. | ||
def load_client_artifact_identifiers() -> Dict[str, ArtifactVersion]: | ||
artifact_identifiers: Dict[str, str] = {} | ||
with open(file=client_versions_path, mode='r') as f: | ||
for line in f: | ||
stripped_line = line.strip() | ||
|
||
# Skip empty, comment, and non-standard version lines. | ||
if not stripped_line or stripped_line.startswith('#') or line.startswith('beta_') or line.startswith('unreleased_'): | ||
continue | ||
|
||
# Split the version line on ';' which should create 3 substrings of artifact identifier - released version - source version. | ||
splitVersionLine = stripped_line.split(";") | ||
|
||
|
||
group_artifact = splitVersionLine[0].split(":") | ||
# From the split lines create the artifact identifier - source version map entry. | ||
artifact_identifiers[splitVersionLine[0]] = ArtifactVersion(group_artifact[0], group_artifact[1], splitVersionLine[1], splitVersionLine[2]) | ||
|
||
return artifact_identifiers | ||
|
||
|
||
def load_external_dependency_version() -> Dict[str, str]: | ||
dependency_versions: Dict[str, str] = {} | ||
with open(file=external_dependency_versions_path, mode='r') as f: | ||
for line in f: | ||
stripped_line = line.strip() | ||
|
||
# Skip empty, comment, and non-standard version lines. | ||
if not stripped_line or stripped_line.startswith('#'): | ||
continue | ||
|
||
splitVersionLine = stripped_line.split(";") | ||
dependency_versions[splitVersionLine[0]] = splitVersionLine[1] | ||
|
||
return dependency_versions | ||
|
||
|
||
def main(): | ||
parser = argparse.ArgumentParser(description='Generated a POM for creating an aggregate code coverage report.') | ||
parser.add_argument('--project-list', '--pl', type=str) | ||
parser.add_argument('--groups', '--g', type=str) | ||
args = parser.parse_args() | ||
start_time = time.time() | ||
create_aggregate_coverage_pom(args.project_list, args.groups) | ||
elapsed_time = time.time() - start_time | ||
|
||
print('Effective POM File for aggregate code coverage') | ||
with open(file=client_aggregate_pom_path, mode='r') as aggregateCoveragePom: | ||
print(aggregateCoveragePom.read()) | ||
|
||
print('elapsed_time={}'.format(elapsed_time)) | ||
print('Total time for replacement: {} seconds'.format(str(timedelta(seconds=elapsed_time)))) | ||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the aggregate report, then shouldn't we be looking at all track 2 groups which would also include com.azure.resourcemanager and com.azure.spring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, they will be added to this report as well when the jacoco issues are resolved for mgmt and spring libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment into the yml about this and create bugs to track the jacoco issues for spring and management otherwise it'll never get done.