new method: check_jenkinsfile_syntax (with tests)

Change-Id: I77a04c95ee3e4d9184bb418853ae414957bf0280
This commit is contained in:
Marcos Diez 2019-09-17 10:16:44 -03:00
parent 306a40b3b4
commit f222797332
3 changed files with 83 additions and 0 deletions

View File

@ -110,6 +110,7 @@ CONFIG_JOB = '%(folder_url)sjob/%(short_name)s/config.xml'
DELETE_JOB = '%(folder_url)sjob/%(short_name)s/doDelete'
ENABLE_JOB = '%(folder_url)sjob/%(short_name)s/enable'
DISABLE_JOB = '%(folder_url)sjob/%(short_name)s/disable'
CHECK_JENKINSFILE_SYNTAX = 'pipeline-model-converter/validateJenkinsfile'
SET_JOB_BUILD_NUMBER = '%(folder_url)sjob/%(short_name)s/nextbuildnumber/submit'
COPY_JOB = '%(from_folder_url)screateItem?name=%(to_short_name)s&mode=copy&from=%(from_short_name)s'
RENAME_JOB = '%(from_folder_url)sjob/%(from_short_name)s/doRename?newName=%(to_short_name)s'
@ -1182,6 +1183,22 @@ class Jenkins(object):
else:
self.create_job(name, config_xml)
def check_jenkinsfile_syntax(self, jenkinsfile):
'''Checks if a Pipeline Jenkinsfile has a valid syntax
:param jenkinsfile: Jenkinsfile text, ``str``
:returns: List of errors in the Jenkinsfile. Empty list if no errors.
'''
# https://jenkins.io/doc/book/pipeline/development/#linter
# JENKINS_CRUMB=`curl "$JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"
# curl -X POST -H $JENKINS_CRUMB -F "jenkinsfile=<Jenkinsfile" $JENKINS_URL/pipeline-model-converter/val
url = self._build_url(CHECK_JENKINSFILE_SYNTAX, locals())
the_data = {
"jenkinsfile": jenkinsfile
}
response = self.jenkins_request(requests.Request('POST', url, data=the_data))
return response.json().get("data", {}).get("errors", [])
def create_job(self, name, config_xml):
'''Create a new Jenkins job

View File

@ -104,5 +104,6 @@ def build_response_mock(status_code, json_body=None, headers=None,
# and accessed by key
response.headers = real_response.headers
response.content = text
response.json = lambda: json_body
return response

View File

@ -0,0 +1,65 @@
from mock import patch
from tests.base import JenkinsTestBase
from tests.helper import build_response_mock
class JenkinsCheckJenkinsfileSyntax(JenkinsTestBase):
@patch('jenkins.requests.Session.send', autospec=True)
def test_check_syntax_of_a_valid_file(self, session_send_mock):
valid_jenkinsfile_content = """
pipeline {
agent any ;
stages {
stage("blah")
{
stexps {
sh("pwd")
}
}
}
}
"""
valid_response = {
"status": "ok",
"data": {
"result": "success"
}
}
session_send_mock.side_effect = iter([
build_response_mock(200, self.crumb_data), # crumb
build_response_mock(200, valid_response) # request
])
response = self.j.check_jenkinsfile_syntax(valid_jenkinsfile_content)
self.assertEqual(response, [])
@patch('jenkins.requests.Session.send', autospec=True)
def test_check_syntax_of_an_invalid_file(self, session_send_mock):
invalid_jenkinsfile_content = """node { "pwd" } """
invalid_response = {
"status": "ok",
"data": {
"result": "failure",
"errors": [
{
"error": [
"Unknown stage section \"stexps\". Starting with version 0.5, steps in a stage must be" +
" in a \"steps\" block. @ line 5, column 9.",
"Expected one of \"steps\", \"stages\", or \"parallel\" for stage \"blah\" @ line 5, column 9."
]
}
]
}
}
session_send_mock.side_effect = iter([
build_response_mock(200, self.crumb_data), # crumb
build_response_mock(200, invalid_response) # request
])
response = self.j.check_jenkinsfile_syntax(invalid_jenkinsfile_content)
self.assertEqual(response, invalid_response["data"]["errors"])