Merge pull request #2398 from charltonaustin/add_different_filenames_for_dockerfile
feat(buildtrigger): allow user to specify dockerfile
This commit is contained in:
commit
b45dc07dce
12 changed files with 50 additions and 42 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -22,3 +22,4 @@ htmlcov
|
||||||
.tox
|
.tox
|
||||||
.cache
|
.cache
|
||||||
.npm-debug.log
|
.npm-debug.log
|
||||||
|
Dockerfile-e
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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':
|
||||||
|
|
|
@ -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):
|
||||||
|
|
15
buildtrigger/test/test_basehandler.py
Normal file
15
buildtrigger/test/test_basehandler.py
Normal 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
|
|
@ -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):
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in a new issue