elastic-apm 2.8.1 → 2.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/.ci/.jenkins_codecov.yml +5 -0
  3. data/.ci/.jenkins_exclude.yml +63 -0
  4. data/.ci/.jenkins_framework.yml +9 -0
  5. data/.ci/.jenkins_master_framework.yml +3 -0
  6. data/.ci/.jenkins_ruby.yml +11 -0
  7. data/.ci/Jenkinsfile +268 -0
  8. data/.ci/bin/check_paths_for_matches.py +80 -0
  9. data/.ci/downstreamTests.groovy +188 -0
  10. data/.ci/jobs/apm-agent-ruby-downstream.yml +37 -0
  11. data/.ci/jobs/apm-agent-ruby-linting-mbp.yml +38 -0
  12. data/.ci/jobs/apm-agent-ruby-mbp.yml +41 -0
  13. data/.ci/jobs/apm-agent-ruby.yml +4 -0
  14. data/.ci/jobs/defaults.yml +24 -0
  15. data/.ci/linting.groovy +32 -0
  16. data/.ci/prepare-git-context.sh +23 -0
  17. data/.pre-commit-config.yaml +22 -0
  18. data/.rspec +0 -1
  19. data/.rubocop.yml +3 -3
  20. data/CHANGELOG.md +59 -2
  21. data/docs/api.asciidoc +24 -7
  22. data/docs/configuration.asciidoc +43 -4
  23. data/docs/index.asciidoc +2 -0
  24. data/docs/log-correlation.asciidoc +96 -0
  25. data/docs/metrics.asciidoc +77 -6
  26. data/lib/elastic_apm.rb +37 -5
  27. data/lib/elastic_apm/agent.rb +29 -4
  28. data/lib/elastic_apm/central_config.rb +141 -0
  29. data/lib/elastic_apm/central_config/cache_control.rb +34 -0
  30. data/lib/elastic_apm/config.rb +165 -340
  31. data/lib/elastic_apm/config/bytes.rb +25 -0
  32. data/lib/elastic_apm/config/duration.rb +6 -8
  33. data/lib/elastic_apm/config/options.rb +134 -0
  34. data/lib/elastic_apm/config/regexp_list.rb +13 -0
  35. data/lib/elastic_apm/context_builder.rb +2 -0
  36. data/lib/elastic_apm/error/exception.rb +3 -1
  37. data/lib/elastic_apm/error_builder.rb +6 -3
  38. data/lib/elastic_apm/instrumenter.rb +6 -0
  39. data/lib/elastic_apm/metadata.rb +2 -1
  40. data/lib/elastic_apm/metrics.rb +2 -1
  41. data/lib/elastic_apm/metrics/vm.rb +60 -0
  42. data/lib/elastic_apm/normalizers/action_controller.rb +5 -2
  43. data/lib/elastic_apm/normalizers/action_mailer.rb +5 -2
  44. data/lib/elastic_apm/normalizers/action_view.rb +14 -9
  45. data/lib/elastic_apm/normalizers/active_record.rb +5 -2
  46. data/lib/elastic_apm/rails.rb +59 -0
  47. data/lib/elastic_apm/railtie.rb +11 -48
  48. data/lib/elastic_apm/span.rb +29 -7
  49. data/lib/elastic_apm/spies/faraday.rb +9 -2
  50. data/lib/elastic_apm/spies/http.rb +9 -2
  51. data/lib/elastic_apm/spies/mongo.rb +18 -3
  52. data/lib/elastic_apm/spies/net_http.rb +8 -2
  53. data/lib/elastic_apm/stacktrace/frame.rb +3 -1
  54. data/lib/elastic_apm/stacktrace_builder.rb +2 -2
  55. data/lib/elastic_apm/subscriber.rb +11 -3
  56. data/lib/elastic_apm/transport/connection.rb +17 -3
  57. data/lib/elastic_apm/transport/connection/proxy_pipe.rb +8 -1
  58. data/lib/elastic_apm/transport/filters/secrets_filter.rb +3 -1
  59. data/lib/elastic_apm/transport/serializers/error_serializer.rb +12 -2
  60. data/lib/elastic_apm/transport/serializers/metadata_serializer.rb +6 -1
  61. data/lib/elastic_apm/transport/serializers/span_serializer.rb +11 -3
  62. data/lib/elastic_apm/version.rb +1 -1
  63. metadata +26 -4
  64. data/Jenkinsfile +0 -280
  65. data/lib/elastic_apm/config/size.rb +0 -28
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11b66b86db45e066da0c6055bd5cb58894a5ba0eca8fb9d891b5b918fcd8d7c0
4
- data.tar.gz: 87bfdbcc9b57f128f032d8e617dfe4540fcf8afeea91f80621d5e1a6b476d47e
3
+ metadata.gz: 45fe1b55dccff365970dd59f2a4f58d9cb76141fd3651e7ce9c166b796bfce0a
4
+ data.tar.gz: 66a2df97b05471613e7d1b5eecdb739ccbf94514b15730cb065153c7128503da
5
5
  SHA512:
6
- metadata.gz: a514f4463ee2294d1e825fd9ba0b42a764d8380e9ea4ba90254acf92ebd7ffec8d4f2a329a77307732e7206a22009c3cb91218650e499235d8ca2cae3cf1d8ae
7
- data.tar.gz: 93e558bab35f323f77116031333ce065fa00b101871ea80e913b082612552857dadc9074c6c4219bf97010eddc6b9abc996fa2dac68454aed1dcb91048c9bd6c
6
+ metadata.gz: e542f184535be90fee811ceee0fd404f65b59575b0e90a8dc8023807ec5b535f9d1c084b7654f5c59fed9d5521a2cbf5f2bd70dac8691db009be1dd24b07be5f
7
+ data.tar.gz: 7d87ebdbbfc32727017f6f0fa8451640ac3fef289366bc3a077899d874bb346a3b94dbadafe96596f2b1a8163c42d79b1b41ce940c6e1fd8fb358fc96767ca84
@@ -0,0 +1,5 @@
1
+ ---
2
+ # Tuple of ruby version and frameworks which are in charge to send data to codecov.
3
+ # # is the separator between the ruby version and the framework.
4
+ ENABLED:
5
+ - ruby:2.6#rails-6.0
@@ -0,0 +1,63 @@
1
+ exclude:
2
+ # Tests fail, but we don't care
3
+ - RUBY_VERSION: jruby:9.2
4
+ FRAMEWORK: rails-4.2
5
+ - RUBY_VERSION: jruby:9.1
6
+ FRAMEWORK: rails-4.2
7
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-12-jdk
8
+ FRAMEWORK: rails-4.2
9
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-11-jdk
10
+ FRAMEWORK: rails-4.2
11
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-8-jdk
12
+ FRAMEWORK: rails-4.2
13
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.1-7-jdk
14
+ FRAMEWORK: rails-4.2
15
+
16
+ - RUBY_VERSION: ruby:2.4
17
+ FRAMEWORK: rails-6.0
18
+ - RUBY_VERSION: ruby:2.3
19
+ FRAMEWORK: rails-6.0
20
+ - RUBY_VERSION: jruby:9.1
21
+ FRAMEWORK: rails-6.0
22
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.1-7-jdk
23
+ FRAMEWORK: rails-6.0
24
+
25
+ # Only test master on newest ruby
26
+ - RUBY_VERSION: ruby:2.5
27
+ FRAMEWORK: rails-master
28
+ - RUBY_VERSION: ruby:2.4
29
+ FRAMEWORK: rails-master
30
+ - RUBY_VERSION: ruby:2.3
31
+ FRAMEWORK: rails-master
32
+ - RUBY_VERSION: jruby:9.2
33
+ FRAMEWORK: rails-master
34
+ - RUBY_VERSION: jruby:9.1
35
+ FRAMEWORK: rails-master
36
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-12-jdk
37
+ FRAMEWORK: rails-master
38
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-11-jdk
39
+ FRAMEWORK: rails-master
40
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-8-jdk
41
+ FRAMEWORK: rails-master
42
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.1-7-jdk
43
+ FRAMEWORK: rails-master
44
+
45
+ - RUBY_VERSION: ruby:2.5
46
+ FRAMEWORK: sinatra-master
47
+ - RUBY_VERSION: ruby:2.4
48
+ FRAMEWORK: sinatra-master
49
+ - RUBY_VERSION: ruby:2.3
50
+ FRAMEWORK: sinatra-master
51
+ - RUBY_VERSION: jruby:9.2
52
+ FRAMEWORK: sinatra-master
53
+ - RUBY_VERSION: jruby:9.1
54
+ FRAMEWORK: sinatra-master
55
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-12-jdk
56
+ FRAMEWORK: sinatra-master
57
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-11-jdk
58
+ FRAMEWORK: sinatra-master
59
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.2-8-jdk
60
+ FRAMEWORK: sinatra-master
61
+ - RUBY_VERSION: docker.elastic.co/observability-ci/jruby:9.1-7-jdk
62
+ FRAMEWORK: sinatra-master
63
+
@@ -0,0 +1,9 @@
1
+ FRAMEWORK:
2
+ - rails-6.0
3
+ - rails-5.2
4
+ - rails-5.1
5
+ - rails-5.0
6
+ - rails-4.2
7
+
8
+ - sinatra-2.0
9
+ - sinatra-1.4
@@ -0,0 +1,3 @@
1
+ FRAMEWORK:
2
+ - rails-master
3
+ - sinatra-master
@@ -0,0 +1,11 @@
1
+ RUBY_VERSION:
2
+ - ruby:2.6
3
+ - ruby:2.5
4
+ - ruby:2.4
5
+ - ruby:2.3
6
+ - jruby:9.2
7
+ - jruby:9.1
8
+ - docker.elastic.co/observability-ci/jruby:9.2-12-jdk
9
+ - docker.elastic.co/observability-ci/jruby:9.2-11-jdk
10
+ - docker.elastic.co/observability-ci/jruby:9.2-8-jdk
11
+ - docker.elastic.co/observability-ci/jruby:9.1-7-jdk
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env groovy
2
+ @Library('apm@current') _
3
+
4
+ import co.elastic.matrix.*
5
+ import groovy.transform.Field
6
+
7
+ /**
8
+ This is the parallel tasks generator,
9
+ it is need as field to store the results of the tests.
10
+ */
11
+ @Field def rubyTasksGen
12
+
13
+ pipeline {
14
+ agent { label 'linux && immutable' }
15
+ environment {
16
+ REPO = 'apm-agent-ruby'
17
+ BASE_DIR = "src/github.com/elastic/${env.REPO}"
18
+ PIPELINE_LOG_LEVEL='DEBUG'
19
+ NOTIFY_TO = credentials('notify-to')
20
+ JOB_GCS_BUCKET = credentials('gcs-bucket')
21
+ CODECOV_SECRET = 'secret/apm-team/ci/apm-agent-ruby-codecov'
22
+ DOCKER_REGISTRY = 'docker.elastic.co'
23
+ DOCKER_SECRET = 'secret/apm-team/ci/docker-registry/prod'
24
+ GITHUB_CHECK_ITS_NAME = 'Integration Tests'
25
+ ITS_PIPELINE = 'apm-integration-tests-selector-mbp/master'
26
+ RELEASE_SECRET = 'secret/apm-team/ci/apm-agent-ruby-rubygems-release'
27
+ }
28
+ options {
29
+ timeout(time: 2, unit: 'HOURS')
30
+ buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20', daysToKeepStr: '30'))
31
+ timestamps()
32
+ ansiColor('xterm')
33
+ disableResume()
34
+ durabilityHint('PERFORMANCE_OPTIMIZED')
35
+ rateLimitBuilds(throttle: [count: 60, durationName: 'hour', userBoost: true])
36
+ quietPeriod(10)
37
+ }
38
+ triggers {
39
+ issueCommentTrigger('(?i).*(?:jenkins\\W+)?run\\W+(?:the\\W+)?tests(?:\\W+please)?.*')
40
+ }
41
+ parameters {
42
+ booleanParam(name: 'Run_As_Master_Branch', defaultValue: false, description: 'Allow to run any steps on a PR, some steps normally only run on master branch.')
43
+ booleanParam(name: 'bench_ci', defaultValue: true, description: 'Enable run benchmarks.')
44
+ }
45
+ stages {
46
+ /**
47
+ Checkout the code and stash it, to use it on other stages.
48
+ */
49
+ stage('Checkout') {
50
+ agent { label 'immutable' }
51
+ options { skipDefaultCheckout() }
52
+ steps {
53
+ deleteDir()
54
+ gitCheckout(basedir: "${BASE_DIR}", githubNotifyFirstTimeContributor: true)
55
+ stash allowEmpty: true, name: 'source', useDefaultExcludes: false
56
+ }
57
+ }
58
+ stage('Sanity checks') {
59
+ agent { label 'linux && immutable && docker' }
60
+ when {
61
+ beforeAgent true
62
+ anyOf {
63
+ not { changeRequest() }
64
+ expression { return params.Run_As_Master_Branch }
65
+ }
66
+ }
67
+ options { skipDefaultCheckout() }
68
+ environment {
69
+ HOME = "${env.WORKSPACE}"
70
+ PATH = "${env.WORKSPACE}/bin:${env.PATH}"
71
+ }
72
+ steps {
73
+ withGithubNotify(context: 'Sanity checks') {
74
+ deleteDir()
75
+ unstash 'source'
76
+ dir(BASE_DIR) {
77
+ catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE', message: 'Sanity checks failed but keep running the build') {
78
+ preCommit(commit: "${GIT_BASE_COMMIT}", junit: true)
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ Execute unit tests.
86
+ */
87
+ stage('Test') {
88
+ agent { label 'linux && immutable' }
89
+ options { skipDefaultCheckout() }
90
+ steps {
91
+ withGithubNotify(context: 'Tests', tab: 'tests') {
92
+ deleteDir()
93
+ unstash "source"
94
+ dir("${BASE_DIR}"){
95
+ script {
96
+ def ruby = readYaml(file: '.ci/.jenkins_ruby.yml')
97
+ def testTasks = [:]
98
+ ruby['RUBY_VERSION'].each{ rubyVersion ->
99
+ testTasks[rubyVersion] = { runJob(rubyVersion) }
100
+ }
101
+ parallel(testTasks)
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
107
+ stage('Benchmarks') {
108
+ options { skipDefaultCheckout() }
109
+ when {
110
+ beforeAgent true
111
+ allOf {
112
+ anyOf {
113
+ branch 'master'
114
+ branch "\\d+\\.\\d+"
115
+ branch "v\\d?"
116
+ tag "v\\d+\\.\\d+\\.\\d+*"
117
+ expression { return params.Run_As_Master_Branch }
118
+ }
119
+ expression { return params.bench_ci }
120
+ }
121
+ }
122
+ stages {
123
+ stage('Clean Workspace') {
124
+ agent { label 'metal' }
125
+ steps {
126
+ echo "Cleaning Workspace"
127
+ }
128
+ post {
129
+ always {
130
+ cleanWs()
131
+ }
132
+ }
133
+ }
134
+ /**
135
+ Run the benchmarks and store the results on ES.
136
+ The result JSON files are also archive into Jenkins.
137
+ */
138
+ stage('Run Benchmarks') {
139
+ agent { label 'linux && immutable' }
140
+ steps {
141
+ withGithubNotify(context: 'Run Benchmarks') {
142
+ deleteDir()
143
+ unstash 'source'
144
+ dir("${BASE_DIR}"){
145
+ script {
146
+ def versions = readYaml(file: ".ci/.jenkins_ruby.yml")
147
+ def benchmarkTask = [:]
148
+ versions['RUBY_VERSION'].each{ v ->
149
+ benchmarkTask[v] = runBenchmark(v)
150
+ }
151
+ parallel(benchmarkTask)
152
+ }
153
+ }
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+ stage('Integration Tests') {
160
+ agent none
161
+ when {
162
+ beforeAgent true
163
+ allOf {
164
+ anyOf {
165
+ environment name: 'GIT_BUILD_CAUSE', value: 'pr'
166
+ expression { return !params.Run_As_Master_Branch }
167
+ }
168
+ }
169
+ }
170
+ steps {
171
+ log(level: 'INFO', text: 'Launching Async ITs')
172
+ build(job: env.ITS_PIPELINE, propagate: false, wait: false,
173
+ parameters: [string(name: 'AGENT_INTEGRATION_TEST', value: 'Ruby'),
174
+ string(name: 'BUILD_OPTS', value: "--ruby-agent-version ${env.GIT_BASE_COMMIT} --ruby-agent-version-state ${env.GIT_BUILD_CAUSE} --ruby-agent-repo ${env.CHANGE_FORK?.trim() ?: 'elastic'}/${env.REPO}"),
175
+ string(name: 'GITHUB_CHECK_NAME', value: env.GITHUB_CHECK_ITS_NAME),
176
+ string(name: 'GITHUB_CHECK_REPO', value: env.REPO),
177
+ string(name: 'GITHUB_CHECK_SHA1', value: env.GIT_BASE_COMMIT)]
178
+ )
179
+ githubNotify(context: "${env.GITHUB_CHECK_ITS_NAME}", description: "${env.GITHUB_CHECK_ITS_NAME} ...", status: 'PENDING', targetUrl: "${env.JENKINS_URL}search/?q=${env.ITS_PIPELINE.replaceAll('/','+')}")
180
+ }
181
+ }
182
+ stage('Release') {
183
+ options { skipDefaultCheckout() }
184
+ environment {
185
+ RUBY_DOCKER_TAG = 'ruby:2.6'
186
+ }
187
+ when {
188
+ beforeAgent true
189
+ anyOf {
190
+ tag pattern: 'v\\d+.*', comparator: 'REGEXP'
191
+ }
192
+ }
193
+ steps {
194
+ withGithubNotify(context: 'Release') {
195
+ deleteDir()
196
+ unstash 'source'
197
+ script {
198
+ dir(BASE_DIR){
199
+ docker.image("${env.RUBY_DOCKER_TAG}").inside('-v /etc/passwd:/etc/passwd -v ${HOME}/.ssh:${HOME}/.ssh') {
200
+ withEnv(["HOME=${env.WORKSPACE}/${env.BASE_DIR ?: ''}"]) {
201
+ rubygemsLogin.withApi(secret: "${env.RELEASE_SECRET}") {
202
+ sshagent(['f6c7695a-671e-4f4f-a331-acdce44ff9ba']) {
203
+ sh '.ci/prepare-git-context.sh'
204
+ sh 'gem install rake yard rspec'
205
+ sh 'rake release'
206
+ }
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+ }
216
+ post {
217
+ cleanup {
218
+ notifyBuildResult()
219
+ }
220
+ }
221
+ }
222
+
223
+ /**
224
+ Run benchmarks for a Ruby version, then report the results to the Elasticsearch server.
225
+ */
226
+ def runBenchmark(version){
227
+ return {
228
+ node('metal'){
229
+ // Transform the versions like:
230
+ // - docker.elastic.co/observability-ci/jruby:9.2-12-jdk to jruby-9.2-12-jdk
231
+ // - jruby:9.1 to jruby-9.1
232
+ def transformedVersion = version.replaceAll('.*/', '').replaceAll(':', '-')
233
+ env.HOME = "${env.WORKSPACE}/${transformedVersion}"
234
+ dir("${transformedVersion}"){
235
+ deleteDir()
236
+ unstash 'source'
237
+ dir("${BASE_DIR}"){
238
+ retry(2){
239
+ sleep randomNumber(min:10, max: 30)
240
+ dockerLogin(secret: "${DOCKER_SECRET}", registry: "${DOCKER_REGISTRY}")
241
+ }
242
+ try{
243
+ sh "./spec/scripts/benchmarks.sh ${version}"
244
+ } catch(e){
245
+ throw e
246
+ } finally {
247
+ archiveArtifacts(
248
+ allowEmptyArchive: true,
249
+ artifacts: "**/benchmark-${transformedVersion}.raw,**/benchmark-${transformedVersion}.error",
250
+ onlyIfSuccessful: false)
251
+ sendBenchmarks(file: "benchmark-${transformedVersion}.bulk",
252
+ index: "benchmark-ruby", archive: true)
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ }
259
+
260
+ def runJob(rubyVersion){
261
+ build( job: "apm-agent-ruby/apm-agent-ruby-downstream/${env.BRANCH_NAME}",
262
+ parameters: [
263
+ string(name: 'RUBY_VERSION', value: "${rubyVersion}"),
264
+ string(name: 'BRANCH_SPECIFIER', value: "${env.GIT_BASE_COMMIT}")
265
+ ],
266
+ quietPeriod: 15
267
+ )
268
+ }
@@ -0,0 +1,80 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Small wrapper script for jenkins to see if a regex pattern matches any of the
4
+ paths generated by diffing between two commits.
5
+ """
6
+ import argparse
7
+ import os
8
+ import re
9
+ import subprocess
10
+ import sys
11
+
12
+ debug = "DEBUG" in os.environ
13
+
14
+
15
+ def check_paths_for_matches(pattern, git_commit, git_previous_commit):
16
+ """Check if any paths between GIT_PREVIOUS_COMMIT and GIT_COMMIT match our pattern.
17
+
18
+ For merge commits only actual path changes are included rather than changes
19
+ from all parents. If GIT_PREVIOUS_COMMIT is not populated, use just the
20
+ paths that GIT_COMMIT represents. If GIT_PREVIOUS_COMMIT is not populated
21
+ and GIT_COMMIT is a merge commit, use all path changes from each parent. If
22
+ GIT_PREVIOUS_COMMIT is the same as GIT_COMMIT, that should generate no path
23
+ changes.
24
+ """
25
+ # Handle case where GIT_PREVIOUS_COMMIT isn't set (e.g. the first build),
26
+ if not git_previous_commit:
27
+ command = [
28
+ "git",
29
+ "diff-tree",
30
+ "-m",
31
+ "--no-commit-id",
32
+ "--name-only",
33
+ "-r",
34
+ git_commit,
35
+ ]
36
+ else:
37
+ command = ["git", "diff", "--name-only", git_previous_commit, git_commit]
38
+
39
+ # Run the command and populate paths.
40
+ completed_process = subprocess.run(
41
+ command, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
42
+ )
43
+ paths = completed_process.stdout.decode().strip().split("\n")
44
+
45
+ # Look for any matches of pattern -> path.
46
+ possible_matches = [(path, pattern.match(path)) for path in paths]
47
+ if any([match for path, match in possible_matches]):
48
+ if debug:
49
+ print("matching change(s) found for {}".format(git_commit))
50
+ for path, match in possible_matches:
51
+ if match:
52
+ print(path)
53
+ sys.stdout.write("match")
54
+ sys.stdout.flush()
55
+ exit(0)
56
+ else:
57
+ if debug:
58
+ print("no matching change(s) found for {}".format(git_commit))
59
+ exit(1)
60
+
61
+
62
+ if __name__ == "__main__":
63
+ # Change our working directory so we're in $WORKSPACE.
64
+ os.chdir(os.path.dirname(os.path.abspath(__file__)))
65
+
66
+ # Define and parse arguments.
67
+ parser = argparse.ArgumentParser()
68
+ parser.add_argument("--pattern", help="A regular expression pattern.")
69
+ parser.add_argument(
70
+ "--git-commit", help="The contents of the GIT_COMMIT environmental variable."
71
+ )
72
+ parser.add_argument(
73
+ "--git-previous-commit",
74
+ nargs="?",
75
+ help="The contents of the GIT_PREVIOUS_COMMIT environmental variable.",
76
+ )
77
+ args = parser.parse_args()
78
+
79
+ compiled_pattern = re.compile(args.pattern)
80
+ check_paths_for_matches(compiled_pattern, args.git_commit, args.git_previous_commit)