datadog-sdk-testing 0.4.9 → 0.5.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 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