forked from Azure/azure-sdk-for-java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
precommit_local_build.py
143 lines (112 loc) · 6.11 KB
/
precommit_local_build.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# 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: Runs compilation, testing, and linting for the passed artifacts and POM artifacts.
#
# Parameters:
#
# '--artifacts'/'--a': A comma separated list of artifact identifiers (groupId:artifactId)
# '--poms'/'--p': A comma separated list of pom.xml paths
# '--skip-tests'/'--st': Skips running tests
# '--skip-javadocs'/'--sj': Skips javadoc generation
# '--skip-checkstyle'/'--sc': Skips checkstyle linting
# '--skip-spotbugs'/'--ss': Skips spotbugs linting
# '--skip-revapi'/'--sr': Skips revapi linting
# '--command-only'/'--co': Indicates that only the command should be generated and not ran
# '--debug'/'--d': Generates command with verbose logging
#
# Example: Run precommit for artifact com.azure:azure-core
#
# python eng/precommit_local_build.py --a "com.azure:azure-core"
#
# Example: Run precommit for aggregate JAR sdk/storage/pom.xml
#
# python eng/precommit_local_build.py --p "sdk/storage/pom.xml"
#
# Example: Run precommit for artifact com.azure and aggregate JAR sdk/storage/pom.xml and skip testing
#
# python eng/precommit_local_build.py --a "com.azure:azure-core" --p "sdk/storage/pom.xml" --st
#
# The script must be run at the root of azure-sdk-for-java.
import argparse
import os
import xml.etree.ElementTree as ET
base_command = 'mvn clean install -f pom.xml -pl "{}" -am "-Dgpg.skip=true" {}'
xml_namespace = '{http://maven.apache.org/POM/4.0.0}'
def get_artifacts_from_pom(pom_path: str, build_artifacts: list, debug: bool):
# Skip files that don't exist as there still may be artifacts to build.
if not os.path.exists(pom_path):
print("POM {} doesn't exist, skipping".format(pom_path))
return
# Turn the POM into an XML tree so we can walk it.
tree = ET.parse(pom_path)
modules_element = tree.getroot().find(xml_namespace + 'modules')
# If the POM has a <modules> tag assume that it is an aggregate POM.
if modules_element != None:
pom_basedir = os.path.dirname(pom_path)
for module_element in modules_element.iterfind(xml_namespace + 'module'):
module_name = module_element.text
module_pom_path = os.path.normpath(os.path.join(pom_basedir, module_name, 'pom.xml'))
if debug:
print('Getting module artifact for {} from aggregator POM {}'.format(module_name.split('/')[-1], pom_path))
get_artifacts_from_pom(module_pom_path, build_artifacts, debug)
# Otherwise grab its groupId and artifactId to determine the artifact identifier.
else:
group_id = tree.getroot().findtext(xml_namespace + "groupId")
artifact_id = tree.getroot().findtext(xml_namespace + "artifactId")
artifact_identifier = '{}:{}'.format(group_id, artifact_id)
if debug:
print('Adding artifact {} for POM file {}'.format(artifact_identifier, pom_path))
build_artifacts.append(artifact_identifier)
def main():
parser = argparse.ArgumentParser(description='Runs compilation, testing, and linting for the passed artifacts.')
parser.add_argument('--artifacts', '-a', type=str, default=None, help='Comma separated list of groupId:artifactId identifiers')
parser.add_argument('--poms', '-p', type=str, default=None, help='Comma separated list of POM paths')
parser.add_argument('--skip-tests', '-st', action='store_true', help='Skips running tests')
parser.add_argument('--skip-javadocs', '-sj', action='store_true', help='Skips javadoc generation')
parser.add_argument('--skip-checkstyle', '-sc', action='store_true', help='Skips checkstyle linting')
parser.add_argument('--skip-spotbugs', '-ss', action='store_true', help='Skips spotbugs linting')
parser.add_argument('--skip-revapi', '-sr', action='store_true', help='Skips revapi linting')
parser.add_argument('--skip-readme', '-smd', action='store_true', help='Skips README validation')
parser.add_argument('--skip-changelog', '-scl', action='store_true', help='Skips CHANGELOG validation')
parser.add_argument('--command-only', '-co', action='store_true', help='Indicates that only the command should be generated and not ran')
parser.add_argument('--debug', '-d', action='store_true', help='Generates command with verbose logging')
args = parser.parse_args()
if args.artifacts == None and args.poms == None:
raise ValueError('--artifacts/--a or --poms/--p must be passed.')
debug = args.debug
build_artifacts = []
if args.poms != None:
for pom in args.poms.split(','):
get_artifacts_from_pom(os.path.abspath(pom), build_artifacts, debug)
if args.artifacts != None:
build_artifacts.extend(args.artifacts.split(','))
# If all passed POMs are invalid fail.
if build_artifacts.count == 0:
raise ValueError('No build artifacts found.')
arguments = []
if args.skip_tests:
arguments.append('"-DskipTests=true"')
if args.skip_javadocs:
arguments.append('"-Dmaven.javadocs.skip=true"')
if args.skip_checkstyle:
arguments.append('"-Dcheckstyle.skip=true"')
if args.skip_spotbugs:
arguments.append('"-Dspotbugs.skip=true"')
if args.skip_revapi:
arguments.append('"-Drevapi.skip=true"')
if not args.skip_readme:
arguments.append('"-Dverify-readme"')
if not args.skip_changelog:
arguments.append('"-Dverify-changelog"')
# If Checkstyle, Spotbugs, or RevApi is being ran install sdk-build-tools to ensure the linting configuration is up-to-date.
if not args.skip_checkstyle or not args.skip_spotbugs or not args.skip_revapi:
if debug:
print('Installing sdk-build-tools as Checkstyle, Spotbugs, or RevApi linting is being performed.')
os.system('mvn install -f ' + os.path.join('eng', 'code-quality-reports', 'pom.xml'))
maven_command = base_command.format(','.join(list(set(build_artifacts))), ' '.join(arguments))
print('Running Maven command: {}'.format(maven_command))
if not args.command_only:
os.system(maven_command)
if __name__ == '__main__':
main()