From b7f491897ccd6df2ca5d34e079c153cfdf15a1f5 Mon Sep 17 00:00:00 2001 From: Somay Jain Date: Mon, 13 Jul 2015 18:46:48 +0530 Subject: [PATCH] Support for more extensions and options in Git plugin Added the support for the following - * strategy and ff_mode in merge before build extension * more options for repository browsers * sparse checkout path extension * ignore commits with certain messages extension * force polling using workspace extension * force push option for git publisher Change-Id: I1fd5b73de32f3a4c10c89dacdddb377378c4128d --- jenkins_jobs/modules/publishers.py | 4 +- jenkins_jobs/modules/scm.py | 107 ++++++++++++++---- tests/publishers/fixtures/git001.xml | 1 + .../git-ignore-commits-with-messages01.xml | 46 ++++++++ .../git-ignore-commits-with-messages01.yaml | 6 + tests/scm/fixtures/git-sparse-checkout01.xml | 53 +++++++++ tests/scm/fixtures/git-sparse-checkout01.yaml | 8 ++ tests/scm/fixtures/git003.xml | 50 ++++++++ tests/scm/fixtures/git003.yaml | 11 ++ 9 files changed, 264 insertions(+), 22 deletions(-) create mode 100644 tests/scm/fixtures/git-ignore-commits-with-messages01.xml create mode 100644 tests/scm/fixtures/git-ignore-commits-with-messages01.yaml create mode 100644 tests/scm/fixtures/git-sparse-checkout01.xml create mode 100644 tests/scm/fixtures/git-sparse-checkout01.yaml create mode 100644 tests/scm/fixtures/git003.xml create mode 100644 tests/scm/fixtures/git003.yaml diff --git a/jenkins_jobs/modules/publishers.py b/jenkins_jobs/modules/publishers.py index 0b17640f0..78e309dd9 100644 --- a/jenkins_jobs/modules/publishers.py +++ b/jenkins_jobs/modules/publishers.py @@ -3250,6 +3250,7 @@ def git(parser, xml_parent, data): :arg bool push-only-if-success: Only push to remotes if the build succeeds - otherwise, nothing will be pushed. (Default: True) + :arg bool force-push: Add force option to git push (Default: False) :arg list tags: tags to push at the completion of the build :tag: * **remote** (`str`) remote repo name to push to @@ -3285,7 +3286,8 @@ def git(parser, xml_parent, data): :language: yaml """ mappings = [('push-merge', 'pushMerge', False), - ('push-only-if-success', 'pushOnlyIfSuccess', True)] + ('push-only-if-success', 'pushOnlyIfSuccess', True), + ('force-push', 'forcePush', False)] tag_mappings = [('remote', 'targetRepoName', 'origin'), ('name', 'tagName', None), diff --git a/jenkins_jobs/modules/scm.py b/jenkins_jobs/modules/scm.py index a442cd736..4fa2d3131 100644 --- a/jenkins_jobs/modules/scm.py +++ b/jenkins_jobs/modules/scm.py @@ -61,9 +61,9 @@ remoteName/\*') :Remote: * **url** (`string`) - url of remote repo * **refspec** (`string`) - refspec to fetch (optional) * **credentials-id** - ID of credential to use to connect, - which is the last field of the path of URL - (a 32-digit hexadecimal code) visible after you clicked - credential under Jenkins Global credentials. (optional) + which is the last field of the path of URL + (a 32-digit hexadecimal code) visible after you clicked + credential under Jenkins Global credentials. (optional) :arg list(str) branches: list of branch specifiers to build (default '**') :arg list(str) excluded-users: list of users to ignore revisions from when polling for changes. (if polling is enabled, optional) @@ -73,8 +73,13 @@ remoteName/\*') :arg dict merge: :merge: * **remote** (`string`) - name of repo that contains branch to - merge to (default 'origin') + merge to (default 'origin') * **branch** (`string`) - name of the branch to merge to + * **strategy** (`string`) - merge strategy. Can be one of + 'default', 'resolve', 'recursive', 'octopus', 'ours', + 'subtree'. (default 'default') + * **fast-forward-mode** (`string`) - merge fast-forward mode. + Can be one of 'FF', 'FF_ONLY' or 'NO_FF'. (default 'FF') :arg str basedir: location relative to the workspace root to clone to (default: workspace) :arg bool skip-tag: Skip tagging (default false) @@ -109,6 +114,7 @@ remoteName/\*') default '0.0') :arg str project-name: project name in Gitblit and ViewGit repobrowser (optional) + :arg str repo-name: repository name in phabricator repobrowser (optional) :arg str choosing-strategy: Jenkins class for selecting what to build (default 'default') :arg str git-config-name: Configure name for Git clone (optional) @@ -119,28 +125,39 @@ remoteName/\*') :arg dict changelog-against: :changelog-against: * **remote** (`string`) - name of repo that contains branch to - create changelog against (default 'origin') + create changelog against (default 'origin') * **branch** (`string`) - name of the branch to create - changelog against (default 'master') + changelog against (default 'master') :arg dict clean: :clean: * **after** (`bool`) - Clean the workspace after checkout * **before** (`bool`) - Clean the workspace before checkout + :arg list(str) ignore-commits-with-messages: Revisions committed with + messages matching these patterns will be ignored. (optional) + + :arg bool force-polling-using-workspace: Force polling using workspace + (default false) + + :arg dict sparse-checkout: + :sparse-checkout: + * **paths** (`list`) - List of paths to sparse checkout. + (optional) + :arg dict submodule: :submodule: * **disable** (`bool`) - By disabling support for submodules - you can still keep using basic git plugin functionality - and just have Jenkins to ignore submodules completely as - if they didn't exist. + you can still keep using basic git plugin functionality + and just have Jenkins to ignore submodules completely as + if they didn't exist. * **recursive** (`bool`) - Retrieve all submodules recursively - (uses '--recursive' option which requires git>=1.6.5) + (uses '--recursive' option which requires git>=1.6.5) * **tracking** (`bool`) - Retrieve the tip of the configured - branch in .gitmodules (Uses '--remote' option which - requires git>=1.8.2) + branch in .gitmodules (Uses '--remote' option which + requires git>=1.8.2) * **timeout** (`int`) - Specify a timeout (in minutes) for - submodules operations (default: 10). + submodules operations (default: 10). :arg str timeout: Timeout for git commands in minutes (optional) :arg bool wipe-workspace: Wipe out workspace before build @@ -148,15 +165,22 @@ remoteName/\*') :browser values: :auto: + :assemblaweb: :bitbucketweb: :cgit: :fisheye: :gitblit: :githubweb: + :gitiles: :gitlab: + :gitlist: :gitoriousweb: :gitweb: + :kiln: + :microsoft-tfs-2013: + :phabricator: :redmineweb: + :rhodecode: :stash: :viewgit: @@ -241,11 +265,23 @@ remoteName/\*') XML.SubElement(scm, 'excludedRegions').text = exclude_string if 'merge' in data: merge = data['merge'] + merge_strategies = ['default', 'resolve', 'recursive', 'octopus', + 'ours', 'subtree'] + fast_forward_modes = ['FF', 'FF_ONLY', 'NO_FF'] name = merge.get('remote', 'origin') branch = merge['branch'] urc = XML.SubElement(scm, 'userMergeOptions') XML.SubElement(urc, 'mergeRemote').text = name XML.SubElement(urc, 'mergeTarget').text = branch + strategy = merge.get('strategy', 'default') + if strategy not in merge_strategies: + raise InvalidAttributeError('strategy', strategy, merge_strategies) + XML.SubElement(urc, 'mergeStrategy').text = strategy + fast_forward_mode = merge.get('fast-forward-mode', 'FF') + if fast_forward_mode not in fast_forward_modes: + raise InvalidAttributeError('fast-forward-mode', fast_forward_mode, + fast_forward_modes) + XML.SubElement(urc, 'fastForwardMode').text = fast_forward_mode try: choosing_strategy = choosing_strategies[data.get('choosing-strategy', @@ -285,8 +321,9 @@ remoteName/\*') XML.SubElement(scm, 'localBranch').text = data['local-branch'] exts_node = XML.SubElement(scm, 'extensions') + impl_prefix = 'hudson.plugins.git.extensions.impl.' if 'changelog-against' in data: - ext_name = 'hudson.plugins.git.extensions.impl.ChangelogToBranch' + ext_name = impl_prefix + 'ChangelogToBranch' ext = XML.SubElement(exts_node, ext_name) opts = XML.SubElement(ext, 'options') change_remote = data['changelog-against'].get('remote', 'origin') @@ -306,13 +343,28 @@ remoteName/\*') clean_after = data['clean'].get('after', False) clean_before = data['clean'].get('before', False) if clean_after: - ext_name = 'hudson.plugins.git.extensions.impl.CleanCheckout' + ext_name = impl_prefix + 'CleanCheckout' ext = XML.SubElement(exts_node, ext_name) if clean_before: - ext_name = 'hudson.plugins.git.extensions.impl.CleanBeforeCheckout' + ext_name = impl_prefix + 'CleanBeforeCheckout' ext = XML.SubElement(exts_node, ext_name) + if 'ignore-commits-with-messages' in data: + for msg in data['ignore-commits-with-messages']: + ext_name = impl_prefix + 'MessageExclusion' + ext = XML.SubElement(exts_node, ext_name) + XML.SubElement(ext, 'excludedMessage').text = msg + if 'sparse-checkout' in data: + ext_name = impl_prefix + 'SparseCheckoutPaths' + ext = XML.SubElement(exts_node, ext_name) + sparse_co = XML.SubElement(ext, 'sparseCheckoutPaths') + sparse_paths = data['sparse-checkout'].get('paths') + if sparse_paths is not None: + path_tagname = impl_prefix + 'SparseCheckoutPath' + for path in sparse_paths: + path_tag = XML.SubElement(sparse_co, path_tagname) + XML.SubElement(path_tag, 'path').text = path if 'submodule' in data: - ext_name = 'hudson.plugins.git.extensions.impl.SubmoduleOption' + ext_name = impl_prefix + 'SubmoduleOption' ext = XML.SubElement(exts_node, ext_name) XML.SubElement(ext, 'disableSubmodules').text = str( data['submodule'].get('disable', False)).lower() @@ -323,27 +375,37 @@ remoteName/\*') XML.SubElement(ext, 'timeout').text = str( data['submodule'].get('timeout', 10)) if 'timeout' in data: - co = XML.SubElement(exts_node, - 'hudson.plugins.git.extensions.impl.' - 'CheckoutOption') + co = XML.SubElement(exts_node, impl_prefix + 'CheckoutOption') XML.SubElement(co, 'timeout').text = str(data['timeout']) + polling_using_workspace = str(data.get('force-polling-using-workspace', + False)).lower() + if polling_using_workspace == 'true': + ext_name = impl_prefix + 'DisableRemotePoll' + ext = XML.SubElement(exts_node, ext_name) # By default we wipe the workspace wipe_workspace = str(data.get('wipe-workspace', True)).lower() if wipe_workspace == 'true': - ext_name = 'hudson.plugins.git.extensions.impl.WipeWorkspace' + ext_name = impl_prefix + 'WipeWorkspace' ext = XML.SubElement(exts_node, ext_name) browser = data.get('browser', 'auto') browserdict = {'auto': 'auto', + 'assemblaweb': 'AssemblaWeb', 'bitbucketweb': 'BitbucketWeb', 'cgit': 'CGit', 'fisheye': 'FisheyeGitRepositoryBrowser', 'gitblit': 'GitBlitRepositoryBrowser', 'githubweb': 'GithubWeb', + 'gitiles': 'Gitiles', 'gitlab': 'GitLab', + 'gitlist': 'GitList', 'gitoriousweb': 'GitoriousWeb', 'gitweb': 'GitWeb', + 'kiln': 'KilnGit', + 'microsoft-tfs-2013': 'TFS2013GitRepositoryBrowser', + 'phabricator': 'Phabricator', 'redmineweb': 'RedmineWeb', + 'rhodecode': 'RhodeCode', 'stash': 'Stash', 'viewgit': 'ViewGitWeb'} if browser not in browserdict: @@ -362,6 +424,9 @@ remoteName/\*') if browser == 'gitlab': XML.SubElement(bc, 'version').text = str( data.get('browser-version', '0.0')) + if browser == 'phabricator': + XML.SubElement(bc, 'repo').text = str( + data.get('repo-name', '')) def repo(parser, xml_parent, data): diff --git a/tests/publishers/fixtures/git001.xml b/tests/publishers/fixtures/git001.xml index 866b0575a..93c44e7f2 100644 --- a/tests/publishers/fixtures/git001.xml +++ b/tests/publishers/fixtures/git001.xml @@ -5,6 +5,7 @@ 2 true false + false tagremotename diff --git a/tests/scm/fixtures/git-ignore-commits-with-messages01.xml b/tests/scm/fixtures/git-ignore-commits-with-messages01.xml new file mode 100644 index 000000000..6b58782b1 --- /dev/null +++ b/tests/scm/fixtures/git-ignore-commits-with-messages01.xml @@ -0,0 +1,46 @@ + + + + 2 + + + origin + +refs/heads/*:refs/remotes/origin/* + https://github.com/openstack-infra/jenkins-job-builder.git + + + + + ** + + + + + false + false + false + false + true + false + false + Default + + + + + + false + + false + false + + + (?s).*FOO.* + + + (?s).*BAR.* + + + + + \ No newline at end of file diff --git a/tests/scm/fixtures/git-ignore-commits-with-messages01.yaml b/tests/scm/fixtures/git-ignore-commits-with-messages01.yaml new file mode 100644 index 000000000..537a0ed70 --- /dev/null +++ b/tests/scm/fixtures/git-ignore-commits-with-messages01.yaml @@ -0,0 +1,6 @@ +scm: + - git: + url: https://github.com/openstack-infra/jenkins-job-builder.git + ignore-commits-with-messages: + - "(?s).*FOO.*" + - "(?s).*BAR.*" diff --git a/tests/scm/fixtures/git-sparse-checkout01.xml b/tests/scm/fixtures/git-sparse-checkout01.xml new file mode 100644 index 000000000..6d559b762 --- /dev/null +++ b/tests/scm/fixtures/git-sparse-checkout01.xml @@ -0,0 +1,53 @@ + + + + 2 + + + origin + +refs/heads/*:refs/remotes/origin/* + https://github.com/openstack-infra/jenkins-job-builder.git + + + + + ** + + + + + false + false + false + false + true + false + false + Default + + + + + + false + + false + false + + + + + path1 + + + path2 + + + path3 + + + + + + + \ No newline at end of file diff --git a/tests/scm/fixtures/git-sparse-checkout01.yaml b/tests/scm/fixtures/git-sparse-checkout01.yaml new file mode 100644 index 000000000..70d430414 --- /dev/null +++ b/tests/scm/fixtures/git-sparse-checkout01.yaml @@ -0,0 +1,8 @@ +scm: + - git: + url: https://github.com/openstack-infra/jenkins-job-builder.git + sparse-checkout: + paths: + - "path1" + - "path2" + - "path3" diff --git a/tests/scm/fixtures/git003.xml b/tests/scm/fixtures/git003.xml new file mode 100644 index 000000000..0c3b24eda --- /dev/null +++ b/tests/scm/fixtures/git003.xml @@ -0,0 +1,50 @@ + + + + 2 + + + origin + +refs/heads/*:refs/remotes/origin/* + https://github.com/openstack-infra/jenkins-job-builder.git + + + + + ** + + + + + repo_name + branch_name + recursive + FF_ONLY + + + false + false + false + false + true + false + false + Default + + + + + + false + + false + false + + + + + + http://github.com/foo/example.git + + + \ No newline at end of file diff --git a/tests/scm/fixtures/git003.yaml b/tests/scm/fixtures/git003.yaml new file mode 100644 index 000000000..a96318c5e --- /dev/null +++ b/tests/scm/fixtures/git003.yaml @@ -0,0 +1,11 @@ +scm: + - git: + url: https://github.com/openstack-infra/jenkins-job-builder.git + browser: rhodecode + browser-url: http://github.com/foo/example.git + force-polling-using-workspace: true + merge: + remote: repo_name + branch: branch_name + strategy: recursive + fast-forward-mode: FF_ONLY