datadog-sdk-testing 0.4.9 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12fb89df2cbbf6335c470b7b02af1a7548682c2e
4
- data.tar.gz: f72745ecd4294db59b42f7ba4fc223238c08399a
3
+ metadata.gz: e44e65983bc61091e09056f2a4c0915ef278bd26
4
+ data.tar.gz: ac179c9a1273e47e0224c21caa1de6762cd431fa
5
5
  SHA512:
6
- metadata.gz: 50afee3a43b62656b0a681913ca997bdfc22182d3e3a15596d7bffd2b3a9cca7f88269ddc051c47d1c5e5bdfcbcffe8412a4cc5ea6666d8145484935cdcb6205
7
- data.tar.gz: eac46f3572c5a28fa6f15d6fa0f3934ac3a5eef22222839487a1d465b06d0fb63cf53e5501da0ad005e1f0e541051e08f9d2603f158d533d284ce82d98675931
6
+ metadata.gz: d763f040338c25d0db5ad817055906dfff23f2103428b6ae322ef4b9b43829acadbab321fc29ef7dc3cb8f0a7494e6c171ee0efa9edf34795da45b7d83f13402
7
+ data.tar.gz: aacc3d99aeb93c3badb7564f10afbf47cd9352c7eb73fb2bdfa8d3541a30ce11c60c61fd1d5eeda1da8c86ba0d8bdba4ea96ce4bdf10540d91b32852d159ffd3
data/README.md CHANGED
@@ -30,3 +30,9 @@ ENV['SDK_HOME'] = File.dirname(__FILE__)
30
30
  spec = Gem::Specification.find_by_name 'datadog-sdk-testing'
31
31
  load "#{spec.gem_dir}/lib/tasks/sdk.rake"
32
32
  ```
33
+
34
+ if you wish to enable the remote facilities for the requirement conflict checking [tool](https://github.com/DataDog/datadog-sdk-testing/blob/master/lib/tasks/ci/hooks/pre-commit.py) you will have to install [github3.py](https://github.com/sigmavirus24/github3.p://github.com/sigmavirus24/github3.py) (pre-release):
35
+ ```
36
+ pip install --pre github3.py
37
+ ```
38
+ By default this tool is designed to be used as a pre-commit hook and runs only on local repos. Due to the duration of the validation runs it's not recommended to enable remote repos when using as a pre-commit hook. We perform requirement validation in our continuous integration environment, so it's definitely not mandatory.
@@ -0,0 +1,8 @@
1
+ # CHANGELOG - Skeleton
2
+
3
+ 0.1.0/ Unreleased
4
+ ==================
5
+
6
+ ### Changes
7
+
8
+ * [FEATURE] adds skeleton integration.
@@ -175,6 +175,7 @@ def generate_skeleton(integration)
175
175
  copy_skeleton('lib/config/metadata.csv', 'metadata.csv', integration)
176
176
  copy_skeleton('lib/config/requirements.txt', 'requirements.txt', integration)
177
177
  copy_skeleton('lib/config/README.md', 'README.md', integration)
178
+ copy_skeleton('lib/config/CHANGELOG.md', 'CHANGELOG.md', integration)
178
179
  copy_skeleton('lib/config/conf.yaml.example', 'conf.yaml.example', integration)
179
180
  end
180
181
 
@@ -260,6 +261,28 @@ class Wait
260
261
  end
261
262
  end
262
263
 
264
+ def travis_pr?
265
+ !ENV['TRAVIS'].nil? && ENV['TRAVIS_EVENT_TYPE'] == 'pull_request'
266
+ end
267
+
268
+ def can_skip?
269
+ return false, [] unless travis_pr?
270
+
271
+ modified_checks = []
272
+ puts "Comparing #{ENV['TRAVIS_PULL_REQUEST_SHA']} with #{ENV['TRAVIS_BRANCH']}"
273
+ git_output = `git diff --name-only #{ENV['TRAVIS_BRANCH']}...#{ENV['TRAVIS_PULL_REQUEST_SHA']}`
274
+ puts "Git diff: \n#{git_output}"
275
+ git_output.each_line do |filename|
276
+ filename.strip!
277
+ puts filename
278
+ return false, [] if filename.split('/').length < 2
279
+
280
+ check_name = filename.split('/')[0]
281
+ modified_checks << check_name unless modified_checks.include? check_name
282
+ end
283
+ [true, modified_checks]
284
+ end
285
+
263
286
  namespace :ci do
264
287
  namespace :common do
265
288
  task :before_install do |t|
@@ -323,8 +346,8 @@ namespace :ci do
323
346
  flavors = attr[:flavor]
324
347
  sdkhome = ENV['SDK_HOME'] || Dir.pwd
325
348
  filter = ENV['NOSE_FILTER'] || '1'
326
- nose_command = in_venv ? 'venv/bin/nosetests' : 'nosetests'
327
349
 
350
+ nose_command = in_venv ? 'venv/bin/nosetests' : 'nosetests'
328
351
  nose = if flavors.include?('default')
329
352
  "(not requires) and #{filter}"
330
353
  else
@@ -4,62 +4,196 @@ import fnmatch
4
4
  import os
5
5
  import sys
6
6
 
7
- OK = 0
7
+ try:
8
+ import github3
9
+ except ImportError:
10
+ github3 = None
11
+
12
+
8
13
  ERR = 1
9
14
 
10
- def get_files(fname):
11
- matches = []
12
- for root, dirnames, filenames in os.walk('.'):
13
- for filename in fnmatch.filter(filenames, fname):
14
- matches.append(os.path.join(root, filename))
15
+ ENV_TOKEN = 'GITHUB_TOKEN'
16
+ ENV_USER = 'GITHUB_USER'
17
+ ENV_PASS = 'GITHUB_PASS'
18
+
19
+
20
+ class BadGithubRepo(Exception):
21
+ pass
22
+
15
23
 
16
- return matches
24
+ def two_fa():
25
+ code = ''
26
+ while not code:
27
+ code = raw_input('Enter Github 2FA Code: ')
17
28
 
29
+ return code
18
30
 
19
- def process_requirements(reqs, fname):
31
+
32
+ class RequirementsAnalyzer(object):
20
33
  SPECIFIERS = ['==', '!=' '<=', '>=', '<', '>']
21
34
 
22
- print "processing... {}".format(fname)
23
- with open(fname) as f:
24
- content = f.readlines()
35
+ def __init__(self, remote, local, patterns=['requirements.txt'], verbose=False):
36
+ self.api = None
37
+ self.remote_sources = remote
38
+ self.local_sources = local
39
+ self.req_patterns = patterns
40
+ self.verbose = verbose
41
+
42
+ if github3:
43
+ if os.environ.get(ENV_TOKEN):
44
+ self.api = github3.login(
45
+ token=os.environ.get(ENV_TOKEN)
46
+ )
47
+ elif os.environ.get(ENV_USER) and os.environ.get(ENV_PASS):
48
+ self.api = github3.login(
49
+ os.environ.get(ENV_USER),
50
+ os.environ(ENV_PASS),
51
+ two_factor_callback=two_fa
52
+ )
53
+
54
+ def get_repo_requirements(self, repo):
55
+ reqs = {}
56
+
57
+ _repo = repo.split('/')
58
+ if len(_repo) is not 2:
59
+ raise BadGithubRepo
25
60
 
26
- for line in content:
27
- line = "".join(line.split())
28
- for specifier in SPECIFIERS:
29
- idx = line.find(specifier)
30
- if idx < 0:
61
+ org = _repo[0]
62
+ repository = _repo[1]
63
+ gh_repo = self.api.repository(org, repository)
64
+
65
+ contents = gh_repo.directory_contents('/', return_as=dict)
66
+ files = {}
67
+ for entry, content in contents.iteritems():
68
+ if content.type != "dir":
69
+ files[content.name] = content
31
70
  continue
32
71
 
33
- req = line[:idx]
34
- specifier = line[idx:]
35
-
36
- if req in reqs and reqs[req][0] != specifier:
37
- # version mismatch
38
- print "There's a version mismatch with {req} " \
39
- " {spec} and {prev_spec} defined in {src}.".format(
40
- req=req,
41
- spec=specifier,
42
- prev_spec=reqs[req][0],
43
- src=reqs[req][1]
44
- )
45
- sys.exit(ERR)
46
- elif req not in reqs:
47
- reqs[req] = (specifier, fname)
48
- break
49
-
50
-
51
- requirements = {}
52
- files = get_files('requirements.txt')
53
-
54
- for f in files:
55
- process_requirements(requirements, f)
56
-
57
- print "No requirement version conflicts found. Looking good... ;)"
58
- for req, spec in requirements.iteritems():
59
- print "{req}{spec} first found in {fname}".format(
60
- req=req,
61
- spec=spec[0],
62
- fname=spec[1]
63
- )
64
-
65
- sys.exit(OK)
72
+ req = gh_repo.file_contents("/{}/requirements.txt".format(entry))
73
+ reqs[entry] = req.decoded
74
+
75
+ fmatches = []
76
+ for pattern in self.req_patterns:
77
+ fmatches.extend(fnmatch.filter(files.keys(), pattern))
78
+
79
+ for match in fmatches:
80
+ req = gh_repo.file_contents(files[match].path)
81
+ reqs[match] = req.decoded
82
+
83
+ return reqs
84
+
85
+ def get_local_files(self):
86
+ matches = []
87
+ for src in self.local_sources:
88
+ for pattern in self.req_patterns:
89
+ for root, dirnames, filenames in os.walk(src):
90
+ for filename in fnmatch.filter(filenames, pattern):
91
+ matches.append(os.path.join(root, filename))
92
+
93
+ return matches
94
+
95
+ def get_local_contents(self, files):
96
+ local_reqs = {}
97
+ for fname in files:
98
+ with open(fname) as f:
99
+ content = f.read()
100
+
101
+ local_reqs[fname] = content
102
+
103
+ return local_reqs
104
+
105
+ def get_all_requirements(self):
106
+ reqs = {}
107
+ if self.api:
108
+ for repo in self.remote_sources:
109
+ try:
110
+ requirements = self.get_repo_requirements(repo)
111
+ if requirements:
112
+ reqs[repo] = requirements
113
+ except BadGithubRepo:
114
+ print 'Unable to get repo requirements for {} - skipping.'.format(repo)
115
+ else:
116
+ print 'No Github API set (missing creds?) cant crawl remotes.'
117
+
118
+ for local in self.local_sources:
119
+ requirements = self.get_local_contents(self.get_local_files())
120
+ reqs[local] = requirements
121
+
122
+ return reqs
123
+
124
+ def process_requirements(self, sources):
125
+ err = 0
126
+ reqs = {}
127
+
128
+ for source, requirements in sources.iteritems():
129
+ for integration, content in requirements.iteritems():
130
+ if self.verbose:
131
+ print "processing... {}/{}".format(source, integration)
132
+ mycontent = content.splitlines()
133
+
134
+ for line in mycontent:
135
+ line = "".join(line.split())
136
+ for specifier in self.SPECIFIERS:
137
+ idx = line.find(specifier)
138
+ if idx < 0:
139
+ continue
140
+
141
+ req = line[:idx]
142
+ specifier = line[idx:]
143
+
144
+ if req in reqs and reqs[req][0] != specifier:
145
+ # version mismatch
146
+ print "There's a version mismatch with {req} " \
147
+ " {spec} and {prev_spec} defined in {src} " \
148
+ "@ {repo}.".format(
149
+ req=req,
150
+ spec=specifier,
151
+ prev_spec=reqs[req][0],
152
+ src=reqs[req][1],
153
+ repo=reqs[req][2]
154
+ )
155
+ err = ERR
156
+ break
157
+ elif req not in reqs:
158
+ reqs[req] = (specifier, integration, source)
159
+ break
160
+
161
+ return err, reqs
162
+
163
+
164
+ def str2bool(v):
165
+ return v.lower() in ("yes", "true", "t", "1")
166
+
167
+ def main(args):
168
+ remote = local = []
169
+ verbose = str2bool(os.environ.get('VERBOSE', 'false'))
170
+ if not len(args):
171
+ remote = [repo.strip() for repo in os.environ.get('REQ_REMOTES', '').split(',')]
172
+ local = [repo.strip() for repo in os.environ.get('REQ_LOCALS', '').split(',')]
173
+ elif len(args) == 1:
174
+ local = [repo.strip() for repo in args[0].split(',')]
175
+ elif len(args) == 2:
176
+ local = [repo.strip() for repo in args[0].split(',')]
177
+ remote = [repo.strip() for repo in args[1].split(',')]
178
+ else:
179
+ local = ['.']
180
+
181
+ analyzer = RequirementsAnalyzer(
182
+ remote=remote, local=local, patterns=['requirements*.txt'], verbose=verbose)
183
+
184
+ err, reqs = analyzer.process_requirements(analyzer.get_all_requirements())
185
+ if not err:
186
+ print "No requirement version conflicts found. Looking good... ;)"
187
+ if verbose:
188
+ for requirement, spec in reqs.iteritems():
189
+ print "{req}{spec} first found in {fname} @ {source}".format(
190
+ req=requirement,
191
+ spec=spec[0],
192
+ fname=spec[1],
193
+ source=spec[2]
194
+ )
195
+
196
+ sys.exit(err)
197
+
198
+ if __name__ == "__main__":
199
+ main(sys.argv[1:])
data/lib/tasks/sdk.rake CHANGED
@@ -147,8 +147,15 @@ namespace :ci do
147
147
  check_env
148
148
  puts 'Assuming you are running these tests locally' unless ENV['TRAVIS']
149
149
  flavor = args[:flavor] || ENV['TRAVIS_FLAVOR'] || 'default'
150
+ can_skip, checks = can_skip?
151
+ can_skip &&= !%w(default).include?(flavor)
152
+
150
153
  flavors = flavor.split(',')
151
154
  flavors.each do |f|
155
+ if can_skip && !checks.include?(flavor)
156
+ puts "skipping #{flavor} tests, not affected by the change".yellow
157
+ next
158
+ end
152
159
  Rake::Task["ci:#{f}:execute"].invoke
153
160
  end
154
161
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datadog-sdk-testing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.9
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jaime Fullaondo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-03 00:00:00.000000000 Z
11
+ date: 2017-02-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Datadog Integration SDK testing/scaffolding gem
14
14
  email: jaime.fullaondo@datadoghq.com
@@ -18,6 +18,7 @@ extra_rdoc_files: []
18
18
  files:
19
19
  - LICENSE
20
20
  - README.md
21
+ - lib/config/CHANGELOG.md
21
22
  - lib/config/README.md
22
23
  - lib/config/check.py
23
24
  - lib/config/ci/skeleton.rake