Skip to content

Commit 8a439f6

Browse files
Style check directory case insensitive (#90)
* Use a git log command that works on git 1.8.x and 2.x * Use a git log command that works on git 1.8.x and 2.x * Use a git log command that works on git 1.8.x and 2.x * Use a git log command that works on git 1.8.x and 2.x * Use a git log command that works on git 1.8.x and 2.x * Add type check fixes. * Add type check fixes. * build fix * build fix * build fix * Add release tagging * Add release tagging Minor updates * Add release tagging * Add release tagging * Bandit checks * Git tagging fix * Git tagging fix * Git tagging fix * Make tagging work if ssh is setup by the screwdriver server setup. * Support the old package publish environment setting variable so old templates don't break. * Don't run the validation on centos 5 since it doesn't work. * Don't run the validation on centos 5 since it doesn't work. * Remove debug print * Don't override the package version * Display a message when changing the metadata in screwdriver. * - Make the release tagger use the Versioner class to get the metadata version so there aren't multiple implementations of the same thing. - Update the Versioner base class to allow specifying the meta command as an argument. To simplify writing tests. * Don't output the bytestring as output but the string instead * Don't run the validation on centos 5 since it doesn't work. * Type validation fix and codestyle fix * Don't run the validation on centos 5 since it doesn't work. * Don't run the validation on centos 5 since it doesn't work. * Don't run the validation on centos 5 since it doesn't work.
1 parent bd0935e commit 8a439f6

8 files changed

Lines changed: 145 additions & 14 deletions

File tree

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ screwdrivercd.documentation.plugin =
8686
[options.extras_require]
8787
documentation =
8888
dhubbard-sphinx-markdown-tables
89+
markdown<3.2 # This is only needed for the mkdocs-material package to install
8990
guzzle_sphinx_theme
9091
markdown-include
9192
mkdocs-bootstrap4
@@ -98,6 +99,7 @@ documentation =
9899
sphinx_rtd_theme
99100
doc_build =
100101
dhubbard-sphinx-markdown-tables
102+
markdown<3.2 # This is only needed for the mkdocs-material package to install
101103
guzzle_sphinx_theme
102104
markdown-include
103105
mkdocs-bootstrap4

src/screwdrivercd/documentation/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"""
66
class DocBuildError(Exception):
77
"""Generic Documentation Generation Error"""
8+
plugin: str=''
89

910

1011
class DocPublishError(Exception):
1112
"""Documentation Publication Error"""
13+
plugin: str=''

src/screwdrivercd/documentation/plugin.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ def build_documentation(self) -> str:
291291

292292
return self.build_dest
293293

294-
def publish_documentation(self, clear_before_build=True): # pragma: no cover
294+
def publish_documentation(self, clear_before_build=True, push=True): # pragma: no cover
295295
"""
296296
Build and publsh the documentation
297297
@@ -309,12 +309,15 @@ def publish_documentation(self, clear_before_build=True): # pragma: no cover
309309
# Build the documentation
310310
self.build_documentation()
311311

312+
if not push:
313+
return
314+
312315
# Make sure there is a clone url before trying to publish
313-
if not self.clone_url:
316+
if not self.clone_url: # pragma: no cover
314317
raise DocPublishError(f'Unable to determine a valid git clone url to publish to')
315318

316319
# Checkout the documentation branch into a temporary directory, add the docs and commit them
317-
with tempfile.TemporaryDirectory() as tempdir:
320+
with tempfile.TemporaryDirectory() as tempdir: # pragma: no cover
318321
os.chdir(tempdir)
319322
self.clone_documentation_branch()
320323
if clear_before_build:
@@ -391,7 +394,7 @@ def build_documentation(documentation_formats=None):
391394
logger.debug(build_log.read())
392395

393396

394-
def publish_documentation(documentation_formats=None):
397+
def publish_documentation(documentation_formats=None, push: bool=True): # pragma: no cover
395398
"""
396399
Publish documentation using all plugins that can generate documentation
397400
"""
@@ -401,7 +404,7 @@ def publish_documentation(documentation_formats=None):
401404
if documentation_plugin.documentation_is_present:
402405
print(f'Publishing {documentation_plugin.name!r} documentation: ', end='', flush=True)
403406
try:
404-
documentation_plugin.publish_documentation(clear_before_build=clear_before_build)
407+
documentation_plugin.publish_documentation(clear_before_build=clear_before_build, push=push)
405408
except (DocBuildError, DocPublishError) as error:
406409
print(colored('Failed', color='red'), flush=True)
407410
if documentation_plugin.build_log_filename and os.path.exists(documentation_plugin.build_log_filename):

src/screwdrivercd/utility/environment.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,21 @@ def standard_directories(command: str='') -> Dict[str, str]:
138138
os.makedirs(directory, exist_ok=True)
139139

140140
return directories
141+
142+
143+
def ins_filename(filename: str) -> str:
144+
"""
145+
Return the filename of an actual file or directory that case insensitively resolves to the filename given. If no
146+
matching files or directories exists, returns an empty string.
147+
"""
148+
dir = os.path.dirname(filename)
149+
contain_dir = dir
150+
base_name = os.path.basename(filename).lower()
151+
if not contain_dir:
152+
contain_dir = '.'
153+
if not os.path.exists(contain_dir):
154+
return ''
155+
for f in os.listdir(contain_dir):
156+
if base_name == f.lower():
157+
return os.path.join(dir, f)
158+
return ''

src/screwdrivercd/validation/validate_style.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
from termcolor import colored
2020

2121
from ..utility import create_artifact_directory
22+
from ..utility.environment import ins_filename
23+
from ..utility.output import print_error
2224
from ..utility.package import PackageMetadata
2325

2426

@@ -57,9 +59,16 @@ def validate_with_codestyle(report_dir):
5759

5860
# Add targets
5961
if src_dir not in ['', '.'] and src_dir != package_name:
60-
command.append(os.path.join(src_dir, package_name.replace('.', '/')))
62+
target = os.path.join(src_dir, package_name.replace('.', '/'))
6163
else:
62-
command.append(package_name.replace('.', '/'))
64+
target = package_name.replace('.', '/')
65+
66+
print(f'target: {target}')
67+
target = ins_filename(target)
68+
if not target:
69+
print_error(f'ERROR: Unable to find package directory for package {package_name!r}, target directory {target!r} does not exist')
70+
return 1
71+
command.append(target)
6372

6473
print('-' * 90 + '\nRunning:', ' '.join(command) + '\n' + '-' * 90, flush=True)
6574
rc = 0
@@ -110,7 +119,7 @@ def validate_codestyle():
110119
print(colored('OK: Code style validation successful', 'green'), flush=True)
111120

112121
if rc > 0:
113-
print(colored('ERROR: Type code style check failed', 'red'), file=sys.stderr, flush=True)
122+
print(colored('ERROR: Code style check failed', 'red'), file=sys.stderr, flush=True)
114123
return rc
115124

116125
return rc

tests/test_documentation_plugin.py

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Copyright 2019, Oath Inc.
22
# Licensed under the terms of the Apache 2.0 license. See the LICENSE file in the project root for terms
3+
import copy
34
import os
45
import tempfile
56
import unittest
67
from pathlib import Path
8+
79
import screwdrivercd.documentation.exceptions
810
import screwdrivercd.documentation.plugin
911
import screwdrivercd.documentation.mkdocs.plugin
@@ -12,6 +14,30 @@
1214
from . import ScrewdriverTestCase
1315

1416

17+
# Simple sphinx project directory
18+
sphinx_project = {
19+
'doc/source/conf.py': b"""# -*- coding: utf-8 -*-
20+
import os
21+
extensions = []
22+
templates_path = ['_templates']
23+
source_suffix = '.rst'
24+
master_doc = 'index'
25+
project = 'foo'
26+
copyright = ''
27+
version = '0.0.0'
28+
release = version
29+
""",
30+
'doc/source/index.rst': b"""Test file"""
31+
}
32+
33+
34+
mkdocs_project_config = {
35+
'mkdocs.yml': b'site_name: test\nstrict: true\nnav:\n - foo: foo.md\n',
36+
'docs/index.md': b"# Test file\n",
37+
'docs/foo.md': b"# Test file\n",
38+
}
39+
40+
1541
class PluginsTestCase(ScrewdriverTestCase):
1642

1743
def test__documentation_plugins__present(self):
@@ -66,14 +92,22 @@ def test_documentation_base_plugin_is_present(self):
6692
p = screwdrivercd.documentation.plugin.DocumentationPlugin()
6793
self.assertFalse(p.documentation_is_present)
6894

69-
def test_documentation_base__log_message(self):
95+
def test_documentation_base__log_message__default(self):
7096
p = self.plugin_class()
7197
p.build_log_filename = 'foo.log'
7298
p._log_message('foo', p.build_log_filename)
7399
self.assertTrue(os.path.exists('foo.log'))
74100
with open('foo.log') as log:
75101
self.assertEqual('foo\n', log.read())
76102

103+
def test_documentation_base__log_message__log_filename(self):
104+
p = self.plugin_class()
105+
p.build_log_filename = 'foo2.log'
106+
p._log_message('foo', log_filename='foo.log')
107+
self.assertTrue(os.path.exists('foo.log'))
108+
with open('foo.log') as log:
109+
self.assertEqual('foo\n', log.read())
110+
77111
def test_documentation_base__log_message__pass_end(self):
78112
p = self.plugin_class()
79113
p._log_message('foo', log_filename='logs/foo.log', end='\r\n')
@@ -105,6 +139,7 @@ def test_documentation__base__run_command__error(self):
105139

106140
def test__documentation__build(self):
107141
self._create_test_repo_contents()
142+
self.write_config_files(mkdocs_project_config)
108143
p = self.plugin_class()
109144
p.build_documentation()
110145
self.assertTrue(os.path.exists(f'{p.log_dir}/{p.name}.build.log'))
@@ -153,22 +188,32 @@ def test__copy_contents(self):
153188
self.assertTrue(dsttestfile.exists())
154189
self.assertTrue(dsttestdotfile.exists())
155190

191+
def test__documentation__publish(self):
192+
instance = self.plugin_class()
193+
instance.publish_documentation(push=False)
194+
156195

157196
class SphinxDocumentationPluginTestCase(DocumentationPluginTestCase):
158197
plugin_class = screwdrivercd.documentation.sphinx.plugin.SphinxDocumentationPlugin
159198

160199
def _create_test_repo_contents(self):
161-
os.makedirs('doc/source')
200+
pass
162201

163202
def test__documentation__build(self):
164203
pass
165204

205+
def test__documentation__publish(self):
206+
self.write_config_files(sphinx_project)
207+
super().test__documentation__publish()
208+
166209

167210
class MkdocsDocumentationPluginTestCase(DocumentationPluginTestCase):
168211
plugin_class = screwdrivercd.documentation.mkdocs.plugin.MkDocsDocumentationPlugin
169212

170213
def _create_test_repo_contents(self):
171-
os.makedirs('docs')
172-
173-
def test__documentation__build(self):
174214
pass
215+
216+
def test__documentation__publish(self):
217+
self._init_test_repo()
218+
self.write_config_files(mkdocs_project_config)
219+
super().test__documentation__publish()

tests/test_utility.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@
77
import time
88

99
from datetime import timedelta
10+
from pathlib import Path
1011
from pprint import pprint
1112

1213
from screwdrivercd.screwdriver.environment import update_job_status
1314
from screwdrivercd.utility.contextmanagers import InTemporaryDirectory, Timeout, revert_file, working_dir
14-
from screwdrivercd.utility.environment import env_bool, env_int, flush_terminals, interpreter_bin_command, standard_directories
15+
from screwdrivercd.utility.environment import env_bool, env_int, flush_terminals, ins_filename, interpreter_bin_command, standard_directories
1516
from screwdrivercd.utility.exceptions import TimeoutError
1617
from screwdrivercd.utility.output import header, print_error, status_message
1718
from screwdrivercd.utility.package import run_setup_command, setup_query, PackageMetadata
@@ -169,6 +170,26 @@ def test__create_artifact_directory_passed(self):
169170
create_artifact_directory(f'{self.tempdir.name}/test_artifacts')
170171
self.assertTrue(os.path.exists(f'{self.tempdir.name}/test_artifacts'))
171172

173+
def test__ins_filename__nodir(self):
174+
Path('foo').mkdir()
175+
result = ins_filename('foo')
176+
self.assertEqual(result, 'foo')
177+
178+
def test__ins_filename__nodir__differentcase(self):
179+
Path('Goo').mkdir()
180+
result = ins_filename('goo')
181+
self.assertEqual(result, 'Goo')
182+
183+
def test__ins_filename__fullpath(self):
184+
Path('foo').mkdir()
185+
fullpath = os.path.join(self.tempdir.name, 'foo')
186+
result = ins_filename(fullpath)
187+
self.assertEqual(result, fullpath)
188+
189+
def test__ins_filename__dirnoexist(self):
190+
result = ins_filename('foo')
191+
self.assertEqual(result, '')
192+
172193
def test__run__run_log_output__success(self):
173194
with InTemporaryDirectory():
174195
result = run_and_log_output(['echo', 'hello'], 'echo.log')

tests/test_validators.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ def test_dummy(self):
8787
mypyvalidator
8888
"""
8989

90+
# src dir has different case than package name
91+
working_config_case_different = copy.deepcopy(working_config)
92+
working_config_case_different['src/MyPyvalidator/__init__.py'] = working_config['src/mypyvalidator/__init__.py']
93+
del working_config_case_different['src/mypyvalidator/__init__.py']
94+
working_config_case_different['setup.cfg'].replace(b'\n mypyvalidator', b'\n MyPyvalidator')
95+
96+
# No source dir different case
97+
working_config_case_different_nosrc = copy.deepcopy(working_config_case_different)
98+
working_config_case_different_nosrc['MyPyvalidator/__init__.py'] = working_config_case_different_nosrc['src/MyPyvalidator/__init__.py']
99+
del working_config_case_different_nosrc['src/MyPyvalidator/__init__.py']
100+
90101
# Invalid package tree
91102
invalid_type_config = copy.deepcopy(working_config)
92103
invalid_type_config['src/mypyvalidator/__init__.py'] = b"""a: int='1'"""
@@ -180,6 +191,26 @@ def test__style__pass__nosrc(self):
180191
result = validate_codestyle()
181192
self.assertEqual(result, 0)
182193

194+
def test_style__pass__srcdir_wrong_case(self):
195+
os.environ['PACKAGE_DIR'] = 'src'
196+
self.write_config_files(working_config_case_different)
197+
os.system('ls -lR')
198+
result = validate_codestyle()
199+
self.assertEqual(result, 0)
200+
201+
def test_style__pass__srcdir_wrong_case__missing(self):
202+
os.environ['PACKAGE_DIR'] = 'srcz'
203+
self.write_config_files(working_config_case_different)
204+
os.system('ls -lR')
205+
result = validate_codestyle()
206+
self.assertNotEquals(result, 0)
207+
208+
def test_style__pass__nosrcdir_wrong_case(self):
209+
self.write_config_files(working_config_case_different_nosrc)
210+
os.system('ls -lR')
211+
result = validate_codestyle()
212+
self.assertEqual(result, 0)
213+
183214

184215
class TypeValidatorTestcase(ScrewdriverTestCase):
185216
validator_name = 'type_validation'

0 commit comments

Comments
 (0)