Skip to content
This repository has been archived by the owner on Apr 15, 2020. It is now read-only.

Commit

Permalink
Merged in feature/ordered-deploy (pull request #54)
Browse files Browse the repository at this point in the history
Deploy providers can be ordered

Approved-by: Xiaohong Zhao <mrluanma@gmail.com>
Approved-by: Lusheng Lv <lusheng.lv@bosondata.com.cn>
  • Loading branch information
Lusheng Lv committed Jun 7, 2017
2 parents 82e9f81 + 2557cd3 commit 7529114
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 27 deletions.
15 changes: 6 additions & 9 deletions badwolf/deploy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,24 @@ class Deployer(object):
'pypi': PypiProvider,
}

def __init__(self, context, spec, working_dir=None):
def __init__(self, context, spec, providers, working_dir=None):
self.context = context
self.spec = spec
self.working_dir = working_dir or context.clone_path

deploy_config = spec.deploy.copy()
deploy_config.pop('branch', None)
deploy_config.pop('tag', None)
self.config = deploy_config
self.providers = providers

def deploy(self):
if not self.config:
logger.info('No deploy provider configured')
if not self.providers:
logger.info('No deploy provider active')
return

commit_hash = self.context.source['commit']['hash']
run_after_deploy = False
notification = self.spec.notification
slack_webhook = notification.slack_webhook

for provider_name, provider_config in self.config.items():
for provider_config in self.providers:
provider_name = provider_config.provider
provider_class = self.PROVIDERS.get(provider_name)
if not provider_class:
logger.warning('Provider %s not found', provider_name)
Expand Down
2 changes: 1 addition & 1 deletion badwolf/deploy/providers/script.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ScriptProvider(Provider):

def deploy(self):
exit_codes, outputs = [], []
for script in self.config:
for script in self.config.script:
exit_code, output = run_command(script, include_errors=True, cwd=self.working_dir, shell=True)
exit_codes.append(exit_code)
outputs.append(output)
Expand Down
15 changes: 8 additions & 7 deletions badwolf/pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,16 @@ def deploy(self):
if not self.spec.deploy or self.context.type not in {'branch', 'tag'}:
return

providers = []
branch = self.context.source['branch']['name']
if self.context.type == 'branch' and branch not in self.spec.deploy.branch:
for provider in self.spec.deploy:
if (self.context.type == 'branch' and branch in provider.branch) or \
(self.context.type == 'tag' and provider.tag):
providers.append(provider)
if not providers:
return

if self.context.type == 'tag' and not self.spec.deploy.tag:
return

logger.info('Running deploy for repository %s', self.context.repository)
Deployer(self.context, self.spec).deploy()
logger.info('Running %d deploy(s) for repository %s', len(providers), self.context.repository)
Deployer(self.context, self.spec, providers).deploy()

def clean(self):
'''Clean local files'''
Expand Down
29 changes: 21 additions & 8 deletions badwolf/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from flask import render_template
from marshmallow import Schema, fields, pre_load, post_load, ValidationError, validate
from marshmallow.utils import is_collection
from marshmallow_oneofschema import OneOfSchema

from badwolf.utils import ObjectDict, to_text, to_binary
from badwolf.security import SecureToken
Expand Down Expand Up @@ -138,18 +139,30 @@ def _postprocess(self, data):
return ObjectDict(data)


class PypiDeploySchema(ObjectDictSchema):
class DeployProviderSchema(ObjectDictSchema):
provider = fields.String()
branch = SetField(fields.String(), missing=set) # 开启部署的 git 分支,空则不触发部署
tag = fields.Boolean(missing=False) # 是否开启 git tag 的部署


class ScriptDeploySchema(DeployProviderSchema):
script = ListField(SecureField())


class PypiDeploySchema(DeployProviderSchema):
username = SecureField()
password = SecureField()
repository = SecureField(missing='https://pypi.python.org/pypi')
distributions = fields.String(missing='dist/*')


class DeploySchema(ObjectDictSchema):
branch = SetField(fields.String(), missing=set) # 开启部署的 git 分支,空则不触发部署
tag = fields.Boolean(missing=False) # 是否开启 git tag 的部署
script = ListField(SecureField(), required=False)
pypi = fields.Nested(PypiDeploySchema, required=False)
class AnyDeploySchema(OneOfSchema):
type_field = 'provider'
type_field_remove = False
type_schemas = {
'script': ScriptDeploySchema,
'pypi': PypiDeploySchema,
}


class SpecificationSchema(Schema):
Expand All @@ -165,7 +178,7 @@ class SpecificationSchema(Schema):
after_failure = ListField(SecureField(), missing=list)
notification = fields.Nested(NotificationSchema)
linters = fields.Nested(LinterSchema, load_from='linter', many=True, missing=list)
deploy = fields.Nested(DeploySchema, missing=dict)
deploy = ListField(fields.Nested(AnyDeploySchema), missing=list)
after_deploy = ListField(SecureField(), missing=list)

@pre_load
Expand Down Expand Up @@ -213,7 +226,7 @@ def __init__(self):
self.environments = []
self.linters = []
self.privileged = False
self.deploy = {}
self.deploy = []
self.after_deploy = []

@classmethod
Expand Down
25 changes: 23 additions & 2 deletions docs/deploy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
============================= ===================== ===================================================================
选项名 类型 说明
============================= ===================== ===================================================================
deploy.provider string 部署服务提供方,如 script, pypi 等
deploy.branch string/list 开启部署的分支,默认为空
deploy.tag boolean 是否开启 tag 部署
deploy.script string/list script deploy 参数
deploy.pypi object 参考下面的文档
after_deploy string/list 部署成功后运行的命令
============================= ===================== ===================================================================

Expand All @@ -31,6 +30,7 @@ script
deploy:
tag: true
provider: script
script:
- echo 'Deploying'
- etc.
Expand Down Expand Up @@ -61,8 +61,29 @@ repository string Pypi 仓库,默认为官
after_success: python setup.py sdist bdist_wheel > /dev/null
deploy:
tag: true
provider: pypi
username: pypi
password:
secure: my_secure_token
repository: https://pypi.example.com
配置多个 provider
-------------------

.. code-block:: yaml
after_success: python setup.py sdist bdist_wheel > /dev/null
deploy:
- tag: true
provider: script
script:
- echo 'Deploying'
- etc.
- branch: master
provider: pypi
username: pypi
password:
secure: my_secure_token
以上多个 deploy provider 将有序执行。
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ flake8-import-order>=0.9.2
deansi>=1.2
cryptography>=1.7.1
marshmallow>=2.12.2
marshmallow-oneofschema
twine
flake8-bugbear
55 changes: 55 additions & 0 deletions tests/test_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,58 @@ class ListSchema(Schema):
data = {'services': ['redis-server']}
result = schema.load(data)
assert result.data['services'] == ['redis-server']


def test_deploy_single_provider_object(app):
s = """deploy:
provider: script
script: echo test
tag: true"""
f = io.StringIO(s)
spec = Specification.parse_file(f)
assert len(spec.deploy) == 1
deploy = spec.deploy[0]
assert deploy.tag
assert not deploy.branch
assert deploy.provider == 'script'
assert deploy.script == ['echo test']


def test_deploy_single_provider_list(app):
s = """deploy:
- provider: script
script: echo test"""
f = io.StringIO(s)
spec = Specification.parse_file(f)
assert len(spec.deploy) == 1
deploy = spec.deploy[0]
assert not deploy.tag
assert not deploy.branch
assert deploy.provider == 'script'
assert deploy.script == ['echo test']


def test_deploy_multiple_provider(app):
s = """deploy:
- provider: script
script: echo test
- provider: pypi
username: test
password: test
tag: true"""
f = io.StringIO(s)
spec = Specification.parse_file(f)
assert len(spec.deploy) == 2

script = spec.deploy[0]
assert not script.tag
assert not script.branch
assert script.provider == 'script'
assert script.script == ['echo test']

pypi = spec.deploy[1]
assert pypi.tag
assert not pypi.branch
assert pypi.provider == 'pypi'
assert pypi.username == 'test'
assert pypi.password == 'test'

0 comments on commit 7529114

Please sign in to comment.