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.
- checksums.yaml +4 -4
- data/.ci/.jenkins_codecov.yml +5 -0
- data/.ci/.jenkins_exclude.yml +63 -0
- data/.ci/.jenkins_framework.yml +9 -0
- data/.ci/.jenkins_master_framework.yml +3 -0
- data/.ci/.jenkins_ruby.yml +11 -0
- data/.ci/Jenkinsfile +268 -0
- data/.ci/bin/check_paths_for_matches.py +80 -0
- data/.ci/downstreamTests.groovy +188 -0
- data/.ci/jobs/apm-agent-ruby-downstream.yml +37 -0
- data/.ci/jobs/apm-agent-ruby-linting-mbp.yml +38 -0
- data/.ci/jobs/apm-agent-ruby-mbp.yml +41 -0
- data/.ci/jobs/apm-agent-ruby.yml +4 -0
- data/.ci/jobs/defaults.yml +24 -0
- data/.ci/linting.groovy +32 -0
- data/.ci/prepare-git-context.sh +23 -0
- data/.pre-commit-config.yaml +22 -0
- data/.rspec +0 -1
- data/.rubocop.yml +3 -3
- data/CHANGELOG.md +59 -2
- data/docs/api.asciidoc +24 -7
- data/docs/configuration.asciidoc +43 -4
- data/docs/index.asciidoc +2 -0
- data/docs/log-correlation.asciidoc +96 -0
- data/docs/metrics.asciidoc +77 -6
- data/lib/elastic_apm.rb +37 -5
- data/lib/elastic_apm/agent.rb +29 -4
- data/lib/elastic_apm/central_config.rb +141 -0
- data/lib/elastic_apm/central_config/cache_control.rb +34 -0
- data/lib/elastic_apm/config.rb +165 -340
- data/lib/elastic_apm/config/bytes.rb +25 -0
- data/lib/elastic_apm/config/duration.rb +6 -8
- data/lib/elastic_apm/config/options.rb +134 -0
- data/lib/elastic_apm/config/regexp_list.rb +13 -0
- data/lib/elastic_apm/context_builder.rb +2 -0
- data/lib/elastic_apm/error/exception.rb +3 -1
- data/lib/elastic_apm/error_builder.rb +6 -3
- data/lib/elastic_apm/instrumenter.rb +6 -0
- data/lib/elastic_apm/metadata.rb +2 -1
- data/lib/elastic_apm/metrics.rb +2 -1
- data/lib/elastic_apm/metrics/vm.rb +60 -0
- data/lib/elastic_apm/normalizers/action_controller.rb +5 -2
- data/lib/elastic_apm/normalizers/action_mailer.rb +5 -2
- data/lib/elastic_apm/normalizers/action_view.rb +14 -9
- data/lib/elastic_apm/normalizers/active_record.rb +5 -2
- data/lib/elastic_apm/rails.rb +59 -0
- data/lib/elastic_apm/railtie.rb +11 -48
- data/lib/elastic_apm/span.rb +29 -7
- data/lib/elastic_apm/spies/faraday.rb +9 -2
- data/lib/elastic_apm/spies/http.rb +9 -2
- data/lib/elastic_apm/spies/mongo.rb +18 -3
- data/lib/elastic_apm/spies/net_http.rb +8 -2
- data/lib/elastic_apm/stacktrace/frame.rb +3 -1
- data/lib/elastic_apm/stacktrace_builder.rb +2 -2
- data/lib/elastic_apm/subscriber.rb +11 -3
- data/lib/elastic_apm/transport/connection.rb +17 -3
- data/lib/elastic_apm/transport/connection/proxy_pipe.rb +8 -1
- data/lib/elastic_apm/transport/filters/secrets_filter.rb +3 -1
- data/lib/elastic_apm/transport/serializers/error_serializer.rb +12 -2
- data/lib/elastic_apm/transport/serializers/metadata_serializer.rb +6 -1
- data/lib/elastic_apm/transport/serializers/span_serializer.rb +11 -3
- data/lib/elastic_apm/version.rb +1 -1
- metadata +26 -4
- data/Jenkinsfile +0 -280
- data/lib/elastic_apm/config/size.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45fe1b55dccff365970dd59f2a4f58d9cb76141fd3651e7ce9c166b796bfce0a
|
4
|
+
data.tar.gz: 66a2df97b05471613e7d1b5eecdb739ccbf94514b15730cb065153c7128503da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e542f184535be90fee811ceee0fd404f65b59575b0e90a8dc8023807ec5b535f9d1c084b7654f5c59fed9d5521a2cbf5f2bd70dac8691db009be1dd24b07be5f
|
7
|
+
data.tar.gz: 7d87ebdbbfc32727017f6f0fa8451640ac3fef289366bc3a077899d874bb346a3b94dbadafe96596f2b1a8163c42d79b1b41ce940c6e1fd8fb358fc96767ca84
|
@@ -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,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
|
data/.ci/Jenkinsfile
ADDED
@@ -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)
|