feat(buildtrigger): allow use to specify dockerfile

users can only specify the folder and the
  dockerfile must be names "Dockerfile" this allows
  users to specify the file and it can be called
  "Dockerfile" or <some name>.Dockerfile
This commit is contained in:
Charlton Austin 2017-03-02 11:24:04 -05:00
parent aa2f88d321
commit e30cd931d1
12 changed files with 50 additions and 42 deletions

1
.gitignore vendored
View file

@ -22,3 +22,4 @@ htmlcov
.tox .tox
.cache .cache
.npm-debug.log .npm-debug.log
Dockerfile-e

View file

@ -1,4 +1,5 @@
import datetime import datetime
import os
import time import time
import logging import logging
import json import json
@ -122,9 +123,13 @@ class BuildComponent(BaseComponent):
# base_image: The image name and credentials to use to conduct the base image pull. # base_image: The image name and credentials to use to conduct the base image pull.
# username: The username for pulling the base image (if any). # username: The username for pulling the base image (if any).
# password: The password for pulling the base image (if any). # password: The password for pulling the base image (if any).
subdir, dockerfile_name = os.path.split(build_config.get('build_subdir', '/Dockerfile'))
build_arguments = { build_arguments = {
'build_package': build_job.get_build_package_url(self.user_files), 'build_package': build_job.get_build_package_url(self.user_files),
'sub_directory': build_config.get('build_subdir', ''), 'sub_directory': subdir,
'dockerfile_name': dockerfile_name,
'repository': repository_name, 'repository': repository_name,
'registry': self.registry_hostname, 'registry': self.registry_hostname,
'pull_token': build_job.repo_build.access_token.code, 'pull_token': build_job.repo_build.access_token.code,

View file

@ -276,6 +276,7 @@ class PopenExecutor(BuilderExecutor):
'DOCKER_TLS_VERIFY': os.environ.get('DOCKER_TLS_VERIFY', ''), 'DOCKER_TLS_VERIFY': os.environ.get('DOCKER_TLS_VERIFY', ''),
'DOCKER_CERT_PATH': os.environ.get('DOCKER_CERT_PATH', ''), 'DOCKER_CERT_PATH': os.environ.get('DOCKER_CERT_PATH', ''),
'DOCKER_HOST': os.environ.get('DOCKER_HOST', ''), 'DOCKER_HOST': os.environ.get('DOCKER_HOST', ''),
'PATH': "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
} }
logpipe = LogPipe(logging.INFO) logpipe = LogPipe(logging.INFO)

View file

@ -258,6 +258,11 @@ class BuildTriggerHandler(object):
can be called in a loop, so it should be as fast as possible. """ can be called in a loop, so it should be as fast as possible. """
pass pass
@classmethod
def path_is_dockerfile(cls, file_name):
""" Returns whether the file is named Dockerfile or follows the convention <name>.Dockerfile"""
return file_name.endswith(".Dockerfile") or u"Dockerfile" == file_name
@classmethod @classmethod
def service_name(cls): def service_name(cls):
""" """
@ -285,14 +290,7 @@ class BuildTriggerHandler(object):
def get_dockerfile_path(self): def get_dockerfile_path(self):
""" Returns the normalized path to the Dockerfile found in the subdirectory """ Returns the normalized path to the Dockerfile found in the subdirectory
in the config. """ in the config. """
subdirectory = self.config.get('subdir', '') return self.config.get('subdir', '')
if subdirectory == '/':
subdirectory = ''
else:
if not subdirectory.endswith('/'):
subdirectory = subdirectory + '/'
return subdirectory + 'Dockerfile'
def prepare_build(self, metadata, is_manual=False): def prepare_build(self, metadata, is_manual=False):
# Ensure that the metadata meets the scheme. # Ensure that the metadata meets the scheme.

View file

@ -1,23 +1,21 @@
import logging import logging
import os
import re import re
from calendar import timegm from calendar import timegm
import dateutil.parser import dateutil.parser
from bitbucket import BitBucket
from jsonschema import validate from jsonschema import validate
from app import app, get_app_url
from buildtrigger.basehandler import BuildTriggerHandler
from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException, from buildtrigger.triggerutil import (RepositoryReadException, TriggerActivationException,
TriggerDeactivationException, TriggerStartException, TriggerDeactivationException, TriggerStartException,
InvalidPayloadException, TriggerProviderException, InvalidPayloadException, TriggerProviderException,
determine_build_ref, raise_if_skipped_build, determine_build_ref, raise_if_skipped_build,
find_matching_branches) find_matching_branches)
from buildtrigger.basehandler import BuildTriggerHandler
from app import app, get_app_url
from bitbucket import BitBucket
from util.security.ssh import generate_ssh_keypair
from util.dict_wrappers import JSONPathDict, SafeDictSetter from util.dict_wrappers import JSONPathDict, SafeDictSetter
from util.security.ssh import generate_ssh_keypair
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -455,10 +453,7 @@ class BitbucketBuildTrigger(BuildTriggerHandler):
raise RepositoryReadException(err_msg) raise RepositoryReadException(err_msg)
files = set([f['path'] for f in data['files']]) files = set([f['path'] for f in data['files']])
if 'Dockerfile' in files: return ["/" + file_path for file_path in files if self.path_is_dockerfile(os.path.basename(file_path))]
return ['']
return []
def load_dockerfile_contents(self): def load_dockerfile_contents(self):
repository = self._get_repository_client() repository = self._get_repository_client()

View file

@ -1,6 +1,7 @@
import logging import logging
import os.path import os.path
import base64 import base64
import re
from calendar import timegm from calendar import timegm
from functools import wraps from functools import wraps
@ -348,9 +349,8 @@ class GithubBuildTrigger(BuildTriggerHandler):
default_commit = repo.get_branch(branches[0]).commit default_commit = repo.get_branch(branches[0]).commit
commit_tree = repo.get_git_tree(default_commit.sha, recursive=True) commit_tree = repo.get_git_tree(default_commit.sha, recursive=True)
return [os.path.dirname(elem.path) for elem in commit_tree.tree return [elem.path for elem in commit_tree.tree
if (elem.type == u'blob' and if (elem.type == u'blob' and self.path_is_dockerfile(os.path.basename(elem.path)))]
os.path.basename(elem.path) == u'Dockerfile')]
except GithubException as ghe: except GithubException as ghe:
message = ghe.data.get('message', 'Unable to list contents of repository: %s' % source) message = ghe.data.get('message', 'Unable to list contents of repository: %s' % source)
if message == 'Branch not found': if message == 'Branch not found':

View file

@ -1,4 +1,5 @@
import logging import logging
import os
from calendar import timegm from calendar import timegm
from functools import wraps from functools import wraps
@ -341,11 +342,7 @@ class GitLabBuildTrigger(BuildTriggerHandler):
msg = 'Unable to find GitLab repository tree for source: %s' % new_build_source msg = 'Unable to find GitLab repository tree for source: %s' % new_build_source
raise RepositoryReadException(msg) raise RepositoryReadException(msg)
for node in repo_tree: return ["/"+node['name'] for node in repo_tree if self.path_is_dockerfile(node['name'])]
if node['name'] == 'Dockerfile':
return ['']
return []
@_catch_timeouts @_catch_timeouts
def load_dockerfile_contents(self): def load_dockerfile_contents(self):

View file

@ -0,0 +1,15 @@
import pytest
from buildtrigger.basehandler import BuildTriggerHandler
@pytest.mark.parametrize('input,output', [
("Dockerfile", True),
("server.Dockerfile", True),
(u"Dockerfile", True),
(u"server.Dockerfile", True),
("bad file name", False),
(u"bad file name", False),
])
def test_path_is_dockerfile(input, output):
assert BuildTriggerHandler.path_is_dockerfile(input) == output

View file

@ -13,12 +13,12 @@ def bitbucket_trigger():
def test_list_build_subdirs(bitbucket_trigger): def test_list_build_subdirs(bitbucket_trigger):
assert bitbucket_trigger.list_build_subdirs() == [''] assert bitbucket_trigger.list_build_subdirs() == ["/Dockerfile"]
@pytest.mark.parametrize('subdir, contents', [ @pytest.mark.parametrize('subdir, contents', [
('', 'hello world'), ('/Dockerfile', 'hello world'),
('somesubdir', 'hi universe'), ('somesubdir/Dockerfile', 'hi universe'),
('unknownpath', None), ('unknownpath', None),
]) ])
def test_load_dockerfile_contents(subdir, contents): def test_load_dockerfile_contents(subdir, contents):

View file

@ -68,8 +68,8 @@ def test_handle_trigger_request(github_trigger, payload, expected_error, expecte
@pytest.mark.parametrize('subdir, contents', [ @pytest.mark.parametrize('subdir, contents', [
('', 'hello world'), ('/Dockerfile', 'hello world'),
('somesubdir', 'hi universe'), ('somesubdir/Dockerfile', 'hi universe'),
('unknownpath', None), ('unknownpath', None),
]) ])
def test_load_dockerfile_contents(subdir, contents): def test_load_dockerfile_contents(subdir, contents):
@ -86,4 +86,4 @@ def test_lookup_user(username, expected_response, github_trigger):
def test_list_build_subdirs(github_trigger): def test_list_build_subdirs(github_trigger):
assert github_trigger.list_build_subdirs() == ['', 'somesubdir'] assert github_trigger.list_build_subdirs() == ['Dockerfile', 'somesubdir/Dockerfile']

View file

@ -13,12 +13,12 @@ def gitlab_trigger():
def test_list_build_subdirs(gitlab_trigger): def test_list_build_subdirs(gitlab_trigger):
assert gitlab_trigger.list_build_subdirs() == [''] assert gitlab_trigger.list_build_subdirs() == ['/Dockerfile']
@pytest.mark.parametrize('subdir, contents', [ @pytest.mark.parametrize('subdir, contents', [
('', 'hello world'), ('/Dockerfile', 'hello world'),
('somesubdir', 'hi universe'), ('somesubdir/Dockerfile', 'hi universe'),
('unknownpath', None), ('unknownpath', None),
]) ])
def test_load_dockerfile_contents(subdir, contents): def test_load_dockerfile_contents(subdir, contents):

View file

@ -208,10 +208,6 @@ angular.module('quay').factory('TriggerService', ['UtilService', '$sanitize', 'K
return '//Dockerfile'; return '//Dockerfile';
} }
if (subdirectory[subdirectory.length - 1] != '/') {
subdirectory = subdirectory + '/';
}
return '//' + subdirectory.replace(new RegExp('(^\/+|\/+$)'), '') + 'Dockerfile'; return '//' + subdirectory.replace(new RegExp('(^\/+|\/+$)'), '') + 'Dockerfile';
}; };