From fc170d9f239a3ae704ea9fab7b74def88cd7b865 Mon Sep 17 00:00:00 2001 From: Shivam Kumar Jha Date: Sun, 9 Jun 2019 02:10:15 +0530 Subject: [PATCH] [FIX] Inconsistency In CI for Release Webhook (#297) Closes #295 --- .travis.yml | 2 +- Pipfile | 1 + mod_ci/controllers.py | 39 +++++++++++++----- tests/test_ci/TestControllers.py | 68 ++++++++++++++++++++++++++++++-- tests/test_ci/TestMarkdown.py | 1 - 5 files changed, 95 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index ff1908cb..535cef4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,10 +27,10 @@ install: - pip install Flask-Testing - pip install blinker script: - - nosetests --nocapture --with-cov --cov-config .coveragerc - dodgy - mypy mod_* - pydocstyle --config=./.pydocstylerc - isort -rc --check-only + - nosetests --nocapture --with-cov --cov-config .coveragerc after_success: - codecov diff --git a/Pipfile b/Pipfile index e17e11b5..6dbae801 100644 --- a/Pipfile +++ b/Pipfile @@ -14,6 +14,7 @@ pycodestyle = "*" isort = "*" dodgy = "*" mypy = "*" +blinker = "*" [packages] flask = "*" diff --git a/mod_ci/controllers.py b/mod_ci/controllers.py index 29dd99bf..e84538d0 100755 --- a/mod_ci/controllers.py +++ b/mod_ci/controllers.py @@ -705,25 +705,42 @@ def start_ci(): g.db.commit() elif event == "release": - g.log.debug("release update triggered") + g.log.debug("release webhook triggered") release_data = payload['release'] - prerelease = release_data['prerelease'] + action = payload['action'] + release_version = release_data['tag_name'] + if release_version[0] == 'v': + release_version = release_version[1:] # checking whether it is meant for production - if prerelease: + if action == "prereleased": g.log.debug("error, release event meant for pre-release") - else: - release_version = release_data['tag_name'] + elif action in ["deleted", "unpublished"]: + g.log.debug("received delete/unpublished action") + CCExtractorVersion.query.filter_by(version=release_version).delete() + g.db.commit() + g.log.info("succesfully deleted release {release_version} on {action} action".format( + release_version=release_version, + action=action + )) + elif action in ["edited", "published"]: # Github recommends adding v to the version - if release_version[0] == 'v': - release_version = release_version[1:] g.log.debug("latest release version is " + str(release_version)) release_commit = GeneralData.query.filter(GeneralData.key == 'last_commit').first().value release_date = release_data['published_at'] - release = CCExtractorVersion(release_version, release_date, release_commit) - g.db.add(release) + if action == "edited": + # below code assumes that only one entry per release is present + release = CCExtractorVersion.query.filter(CCExtractorVersion.version == release_version).one() + release.released = datetime.datetime.strptime(release_date, '%Y-%m-%dT%H:%M:%SZ').date() + release.commit = release_commit + else: + release = CCExtractorVersion(release_version, release_date, release_commit) + g.db.add(release) g.db.commit() - g.log.info("successfully updated release version") + g.log.info("successfully updated release version with webhook action '{action}'".format( + action=action + )) # adding test corresponding to last commit to the baseline regression results + # this is not altered when a release is deleted or unpulished since it's based on commit test = Test.query.filter(and_(Test.commit == release_commit, Test.platform == TestPlatform.linux)).first() test_result_file = g.db.query(TestResultFile).filter( @@ -738,6 +755,8 @@ def start_ci(): ).values(test_result.c.expected_rc) g.db.commit() g.log.info("successfully added tests for latest release!") + else: + g.log.warning("unsupported release action: {action}".format(action=action)) else: # Unknown type diff --git a/tests/test_ci/TestControllers.py b/tests/test_ci/TestControllers.py index 29088b3c..7c1a4686 100644 --- a/tests/test_ci/TestControllers.py +++ b/tests/test_ci/TestControllers.py @@ -353,7 +353,8 @@ def test_webhook_wrong_url(self, mock_request): """ import json with self.app.test_client() as c: - data = {'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': '0.0.1'}} + data = {'action': 'published', + 'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': '0.0.1'}} sig = self.generate_signature(str(json.dumps(data)).encode('utf-8'), g.github['ci_key']) headers = self.generate_git_api_header('ping', sig) # non github ip address @@ -370,7 +371,8 @@ def test_webhook_ping(self, mock_request): """ import json with self.app.test_client() as c: - data = {'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': '0.0.1'}} + data = {'action': 'published', + 'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': '0.0.1'}} sig = self.generate_signature(str(json.dumps(data)).encode('utf-8'), g.github['ci_key']) headers = self.generate_git_api_header('ping', sig) # one of ip address from github webhook @@ -389,7 +391,8 @@ def test_webhook_release(self, mock_request): import json with self.app.test_client() as c: # Full Release with version with 2.1 - data = {'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': 'v2.1'}} + data = {'action': 'published', + 'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': 'v2.1'}} sig = self.generate_signature(str(json.dumps(data)).encode('utf-8'), g.github['ci_key']) headers = self.generate_git_api_header('release', sig) # one of ip address from github webhook @@ -404,6 +407,62 @@ def test_webhook_release(self, mock_request): last_release = CCExtractorVersion.query.order_by(CCExtractorVersion.released.desc()).first() self.assertEqual(last_release.version, '2.1') + @mock.patch('requests.get', side_effect=mock_api_request_github) + def test_webhook_release_edited(self, mock_request): + """ + Check webhook action "edited" updates the specified version. + """ + import json + from datetime import datetime + with self.app.test_client() as c: + release = CCExtractorVersion('2.1', '2018-05-30T20:18:44Z', 'abcdefgh') + g.db.add(release) + g.db.commit() + # Full Release with version with 2.1 + data = {'action': 'edited', + 'release': {'prerelease': False, 'published_at': '2018-06-30T20:18:44Z', 'tag_name': 'v2.1'}} + sig = self.generate_signature(str(json.dumps(data)).encode('utf-8'), g.github['ci_key']) + headers = self.generate_git_api_header('release', sig) + # one of ip address from github webhook + wsgi_environment = {'REMOTE_ADDR': '192.30.252.0'} + last_commit = GeneralData.query.filter(GeneralData.key == 'last_commit').first() + # abcdefgh is the new commit after previous version defined in base.py + last_commit.value = 'abcdefgh' + g.db.commit() + response = c.post( + '/start-ci', environ_overrides=wsgi_environment, + data=json.dumps(data), headers=headers) + last_release = CCExtractorVersion.query.filter_by(version='2.1').first() + self.assertEqual(last_release.released, + datetime.strptime('2018-06-30T20:18:44Z', '%Y-%m-%dT%H:%M:%SZ').date()) + + @mock.patch('requests.get', side_effect=mock_api_request_github) + def test_webhook_release_deleted(self, mock_request): + """ + Check def add_CCExversion(self, c, version='v2.1', commit='abcdefgh', released='2018-05-30T20:18:44Z'): + """ + import json + with self.app.test_client() as c: + release = CCExtractorVersion('2.1', '2018-05-30T20:18:44Z', 'abcdefgh') + g.db.add(release) + g.db.commit() + # Delete full release with version with 2.1 + data = {'action': 'deleted', + 'release': {'prerelease': False, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': 'v2.1'}} + sig = self.generate_signature(str(json.dumps(data)).encode('utf-8'), g.github['ci_key']) + headers = self.generate_git_api_header('release', sig) + # one of ip address from github webhook + wsgi_environment = {'REMOTE_ADDR': '192.30.252.0'} + last_commit = GeneralData.query.filter(GeneralData.key == 'last_commit').first() + # abcdefgh is the new commit after previous version defined in base.py + last_commit.value = 'abcdefgh' + g.db.commit() + response = c.post( + '/start-ci', environ_overrides=wsgi_environment, + data=json.dumps(data), headers=headers) + last_release = CCExtractorVersion.query.order_by(CCExtractorVersion.released.desc()).first() + self.assertNotEqual(last_release.version, '2.1') + @mock.patch('requests.get', side_effect=mock_api_request_github) def test_webhook_prerelease(self, mock_request): """ @@ -412,7 +471,8 @@ def test_webhook_prerelease(self, mock_request): import json with self.app.test_client() as c: # Full Release with version with 2.1 - data = {'release': {'prerelease': True, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': 'v2.1'}} + data = {'action': 'prereleased', + 'release': {'prerelease': True, 'published_at': '2018-05-30T20:18:44Z', 'tag_name': 'v2.1'}} sig = self.generate_signature(str(json.dumps(data)).encode('utf-8'), g.github['ci_key']) headers = self.generate_git_api_header('release', sig) # one of ip address from github webhook diff --git a/tests/test_ci/TestMarkdown.py b/tests/test_ci/TestMarkdown.py index 1c0ca312..91796a91 100644 --- a/tests/test_ci/TestMarkdown.py +++ b/tests/test_ci/TestMarkdown.py @@ -107,7 +107,6 @@ def test_extra_task_list(self): """I'm a task\n\n""") html_test1 = markdown(mkdown_test1, extras=["task_list"]) - print(html_test1) assert expected_test1 == html_test1, "no target attribute added to anchor tag"