def _validate_markdown(self, ymlfile): '''ensure that fields are present in markdown file''' try: import yaml except: bot.error( 'Python yaml is required for testing yml/markdown files.') sys.exit(1) uid = os.path.basename(ymlfile).strip('.md') if os.path.exists(ymlfile): self.metadata = read_yaml(ymlfile) # Required fields for library fields = [ 'github', 'docker', 'web', 'name', 'tags', 'uid', 'maintainer' ] # Tests for all fields for field in fields: if field not in self.metadata: print('%s is missing field %s.' % (uid, field)) return False if self.metadata[field] in ['', None]: return False # Uid in file must match filename if self.metadata['uid'] != uid: print('Mismatch in file %s.md and %s.' % (ymlfile, self.metadata['uid'])) return False # Ensure that urls are from Docker Hub and Github if 'github' not in self.metadata['github']: return notvalid('%s: not a valid github repository' % name) if 'hub.docker.com' not in self.metadata['docker']: return notvalid('%s: not a valid github repository' % name) # Tags must be in a list if not isinstance(self.metadata['tags'], list): return notvalid('%s: tags must be a list' % name) # Validate that links are correct urls for key in ['web', 'github', 'docker']: url = self.metadata[key] if not validate_url(url): return notvalid('%s is not a valid URL.' % (url)) # Validate name bot.test(" Name: %s" % self.metadata['name']) name = self.metadata['name'].replace('/', '-') # okay to have / if not re.match("^[a-z0-9_-]*$", name): return notvalid('''invalid characters in %s, only lowercase and "-" or "_" allowed.''' % name) return True
def validate_url(self, url): bot.test('url: %s' % url) response = requests.get(url) if response.status_code == 404: bot.error('%s not found.' % url) return False return True
def clone(url, tmpdir=None, branch='master'): '''clone a repository from Github''' if tmpdir is None: tmpdir = tempfile.mkdtemp() name = os.path.basename(url).replace('.git', '') dest = '%s/%s-%s' % (tmpdir, name, branch) return_code = os.system('git clone -b %s %s %s' % (branch, url, dest)) if return_code == 0: return dest bot.error('Error cloning repo.') sys.exit(return_code)
def mkdir_p(path): '''mkdir_p attempts to get the same functionality as mkdir -p :param path: the path to create. ''' try: os.makedirs(path) except OSError as e: if e.errno == errno.EEXIST and os.path.isdir(path): pass else: bot.error("Error creating path %s, exiting." % path) sys.exit(1)
def validate(self, url): ''' takes in a Github repository for validation of preview and runtime (and possibly tests passing? ''' # Preview must provide the live URL of the repository if not url.startswith('http') or not 'github' in url: bot.error('Test of preview must be given a Github repostitory.') return False if not self._validate_preview(url): return False return True
def copy_directory(src, dest, force=False): ''' Copy an entire directory recursively ''' if os.path.exists(dest) and force is True: shutil.rmtree(dest) try: shutil.copytree(src, dest) except OSError as e: # If the error was caused because the source wasn't a directory if e.errno == errno.ENOTDIR: shutil.copy(src, dest) else: bot.error('Directory not copied. Error: %s' % e) sys.exit(1)
def getenv(variable_key, default=None, required=False, silent=True): '''getenv will attempt to get an environment variable. If the variable is not found, None is returned. :param variable_key: the variable name :param required: exit with error if not found :param silent: Do not print debugging information for variable ''' variable = os.environ.get(variable_key, default) if variable is None and required: bot.error("Cannot find environment variable %s, exiting." % variable_key) sys.exit(1) if not silent: if variable is not None: bot.verbose2("%s found as %s" % (variable_key, variable)) else: bot.verbose2("%s not defined (None)" % variable_key) return variable
def _validate_preview(self, url, clean_up=True): bot.test('Container url: %s' % url) org, repo = url.split('/')[-2:] if repo.endswith('.git'): repo = repo.replace('.git', '') github_pages = "https://%s.github.io/%s" % (org, repo) # Save Github pages for comparison with record self.github_pages = github_pages bot.test('Github Pages url: %s' % github_pages) response = requests.get(github_pages) if response.status_code == 404: bot.error('''Preview not found at %s. You must publish a static preview from the gh-pages branch of your repository to add to the library.''' % github_pages) return False index = response.text tmpdir = tempfile.mkdtemp() # Github Pages ghpages = clone(url, tmpdir, branch='gh-pages') contenders = glob('%s/*' % ghpages) # master master = clone(url, tmpdir, branch='master') license = False readme = False found = False tags = False valid = True # Required to have at least one latest manifest = False inspect = False # Testing Github Pages print('Testing Github Pages!') for test in contenders: print(' %s' % test) if os.path.basename(test) == "index.html": bot.test('Found index file in repository.') found = True if os.path.basename(test) == 'tags.json': bot.test('Found tags manifest in repository.') tags = True if os.path.basename(test) == 'manifest-latest.json': bot.test('Found latest manifest in repository.') manifest = True if os.path.basename(test) == 'inspect.json': bot.test('Found latest inspection in repository.') inspect = True contenders = glob('%s/*' % master) # Testing Main Repository print('Testing Main Repository master branch!') for test in contenders: print(' %s' % test) if "LICENSE" in os.path.basename(test): license = True if "README" in os.path.basename(test): readme = True # These are all required! if license is False: bot.warning("LICENSE file not found, please add a LICENSE") valid = False if readme is False: bot.warning("README file not found, please add a README") valid = False if tags is False: bot.warning("inspect-latest.json not found, required.") valid = False if manifest is False: bot.warning("manifest-latest.json not found, required") valid = False # Clean up, if desired if clean_up is True: shutil.rmtree(tmpdir) self._print_valid(valid) return valid