From 4e36cbee97dce3895f1e6e272fb5b65efa1f32b2 Mon Sep 17 00:00:00 2001 From: Tim Vink Date: Wed, 26 Feb 2020 17:45:11 +0100 Subject: [PATCH] Add unit test for shallow clones, see #10 --- .../util.py | 75 ++++++++++++++----- tests/test_basic.py | 63 +++++++++++++--- 2 files changed, 108 insertions(+), 30 deletions(-) diff --git a/mkdocs_git_revision_date_localized_plugin/util.py b/mkdocs_git_revision_date_localized_plugin/util.py index aa88e87..175ae78 100644 --- a/mkdocs_git_revision_date_localized_plugin/util.py +++ b/mkdocs_git_revision_date_localized_plugin/util.py @@ -4,10 +4,31 @@ from datetime import datetime from babel.dates import format_date + class Util: def __init__(self, path = "."): self.repo = Git(path) + + # Checks when running builds on CI + # See https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/issues/10 + if is_shallow_clone(self.repo): + n_commits = commit_count(self.repo) + + if os.environ.get('GITLAB_CI') and n_commits < 50: + logging.warning(""" + Running on a gitlab runner might lead to wrong git revision dates + due to a shallow git fetch depth. + Make sure to set GIT_DEPTH to 1000 in your .gitlab-ci.yml file. + (see https://docs.gitlab.com/ee/user/project/pipelines/settings.html#git-shallow-clone). + """) + if os.environ.get('GITHUB_ACTIONS') and n_commits == 1: + logging.warning(""" + Running on github actions might lead to wrong git revision dates + due to a shallow git fetch depth. + Try setting fetch-depth to 0 in your github action + (see https://github.com/actions/checkout). + """) @staticmethod def _date_formats(unix_timestamp, locale = 'en'): @@ -50,27 +71,43 @@ def get_revision_date_for_file(self, path, locale = 'en'): """ unix_timestamp = self.repo.log(path, n=1, date='short', format='%at') - - + if not unix_timestamp: - - if os.environ.get('GITLAB_CI'): - raise EnvironmentError("""Cannot access git commit for '%s'. - Try setting GIT_DEPTH to 1000 in your .gitlab-ci.yml file. - (see https://docs.gitlab.com/ee/user/project/pipelines/settings.html#git-shallow-clone). - Or disable mkdocs-git-revision-date-localized-plugin when using gitlab runners. - """ % path) - - if os.environ.get('GITHUB_ACTIONS'): - raise EnvironmentError("""Cannot access git commit for '%s'. - Try setting fetch-depth to 1 in your github action - (see https://github.com/actions/checkout). - Or disable mkdocs-git-revision-date-localized-plugin when using github actions. - """ % path) - unix_timestamp = datetime.utcnow().timestamp() logging.warning('%s has no git logs, using current timestamp' % path) - - return self._date_formats(unix_timestamp) + +def is_shallow_clone(repo): + """ + Helper function to determine if repository + is a shallow clone. + + References: + https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/issues/10 + https://stackoverflow.com/a/37203240/5525118 + + Args: + repo (git.Repo): Repository + + Returns: + bool: If a repo is shallow clone + """ + return os.path.exists(".git/shallow") + + +def commit_count(repo): + """ + Helper function to determine the number of commits in a repository + + Args: + repo (git.Repo): Repository + + Returns: + count (int): Number of commits + """ + refs = repo.for_each_ref().split('\n') + refs = [x.split()[0] for x in refs] + + counts = [int(repo.rev_list(x, count=True, first_parent=True)) for x in refs] + return max(counts) \ No newline at end of file diff --git a/tests/test_basic.py b/tests/test_basic.py index ce008d9..1309ad8 100644 --- a/tests/test_basic.py +++ b/tests/test_basic.py @@ -15,6 +15,7 @@ import shutil import pytest import git +import logging from mkdocs_git_revision_date_localized_plugin.util import Util @@ -44,6 +45,8 @@ def setup_clean_mkdocs_folder(mkdocs_yml_path, output_path): # Create empty 'testproject' folder if os.path.exists(testproject_path): + logging.warning("""This command does not work on windows. + Refactor your test to use setup_clean_mkdocs_folder() only once""") shutil.rmtree(testproject_path) # Copy correct mkdocs.yml file and our test 'docs/' @@ -62,6 +65,9 @@ def setup_commit_history(testproject_path): Args: testproject_path (Path): Path to test project + + Returns: + repo (repo): git.Repo object """ assert not os.path.exists(testproject_path / '.git') @@ -75,8 +81,19 @@ def setup_commit_history(testproject_path): try: repo.git.add('mkdocs.yml') repo.git.commit(message = 'add mkdocs', author = author) + repo.git.add('docs/first_page.md') repo.git.commit(message = 'first page', author = author) + file_name = os.path.join(testproject_path, 'docs/first_page.md') + with open(file_name, 'w+') as the_file: + the_file.write('Hello\n') + repo.git.add('docs/first_page.md') + repo.git.commit(message = 'first page update 1', author = author) + with open(file_name, 'w') as the_file: + the_file.write('# First Test Page Edited\n\nSome Lorem text') + repo.git.add('docs/first_page.md') + repo.git.commit(message = 'first page update 2', author = author) + repo.git.add('docs/second_page.md') repo.git.commit(message = 'second page', author = author) repo.git.add('docs/index.md') @@ -87,6 +104,8 @@ def setup_commit_history(testproject_path): except: os.chdir(cwd) raise + + return repo def build_docs_setup(testproject_path): """ @@ -225,23 +244,45 @@ def test_type_unknown(tmp_path): tmp_path, 'tests/basic_setup/mkdocs_unknown_type.yml') -def test_low_fetch_depth(tmp_path): +def test_low_fetch_depth(tmp_path, caplog): """ On gitlab and github runners, a GIT might have a low fetch depth, which means commits are not available. This should throw informative errors. """ - pass + testproject_path = setup_clean_mkdocs_folder('tests/basic_setup/mkdocs.yml', tmp_path) + repo = setup_commit_history(testproject_path) - # Test correct error messages when GIT is not available - #target_dir = os.path.join(tmp_path, 'nogit') - #shutil.copytree(os.path.join(os.getcwd(), 'test/basic_setup'), - # target_dir) + # Create a second, clean folder to clone to + cloned_folder = tmp_path.parent / 'clonedrepo' + if os.path.exists(cloned_folder): + shutil.rmtree(cloned_folder) + os.mkdir(cloned_folder) + + # Clone the local repo with fetch depth of 1 + repo = git.Repo.init(cloned_folder, bare = False) + origin = repo.create_remote('origin', testproject_path) + origin.fetch(depth=1, prune=True) + repo.create_head('master', origin.refs.master) # create local branch "master" from remote "master" + repo.heads.master.set_tracking_branch(origin.refs.master) # set local "master" to track remote "master + repo.heads.master.checkout() # checkout local "master" to working tree + + # should not raise warning + result = build_docs_setup(cloned_folder) + assert result.exit_code == 0 + + # should raise warning + os.environ["GITLAB_CI"] = "1" + result = build_docs_setup(cloned_folder) + assert result.exit_code == 0 + assert 'Running on a gitlab runner' in caplog.text + + del os.environ['GITLAB_CI'] + os.environ["GITHUB_ACTIONS"] = "1" + result = build_docs_setup(cloned_folder) + assert result.exit_code == 0 + assert 'Running on github actions might' in caplog.text - # ... - #result = build_docs_setup(os.path.join(target_dir,'mkdocs.yml'), target_dir) - #with pytest.warns(UserWarning): - # assert result.exit_code == 0, "'mkdocs build' command failed" - \ No newline at end of file +# TODO: Test correct error messages when GIT is not available \ No newline at end of file