diff --git a/cookiecutter.json b/cookiecutter.json index 5b3ee1a..efc909c 100644 --- a/cookiecutter.json +++ b/cookiecutter.json @@ -1,10 +1,11 @@ { - "full_name": "Audrey Roy Greenfeld", - "email": "audreyr@example.com", - "github_username": "audreyr", - "project_name": "Python Boilerplate", + "full_name": "Mark Sevelj", + "email": "mark@example.com", + "github_username": "imAsparky", + "project_name": "Python 3 Package Boilerplate", + "git_project_name": "{{ cookiecutter.project_name.lower().replace(' ', '-').replace('_', '-') }}", "project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}", - "project_short_description": "Python Boilerplate contains all the boilerplate you need to create a Python package.", + "project_short_description": "Python 3 Package Boilerplate contains all the boilerplate you need to create a Python package.", "pypi_username": "{{ cookiecutter.github_username }}", "version": "0.1.0", "use_pytest": "n", @@ -13,5 +14,7 @@ "command_line_interface": ["Click", "Argparse", "No command-line interface"], "create_author_file": "y", "create_conventional_commits_edit_message": "y", + "create_auto_CHANGELOG": "y", + "github_access_token": ["secrets.GITHUB_TOKEN", "secrets.CHANGELOG_UPDATE"], "open_source_license": ["MIT license", "BSD license", "ISC license", "Apache Software License 2.0", "GNU General Public License v3", "Not open source"] } diff --git a/docs/source/prompts.rst b/docs/source/prompts.rst index c5fbaa9..f4adcfe 100644 --- a/docs/source/prompts.rst +++ b/docs/source/prompts.rst @@ -26,6 +26,15 @@ project_name The name of your new Python package project. This is used in documentation, so spaces and any characters are fine here. +git_project_name +~~~~~~~~~~~~~~~~ +The name of the GitHub project repository you have created. + +If it is the same as your project_name but with hyphens instead of spaces leave +this blank. Your GitHub repository name will be generated with hyphens. + +If its different enter your project GitHub repository name here. + project_slug ~~~~~~~~~~~~ The namespace of your Python package. This should be Python import-friendly. @@ -67,9 +76,13 @@ project. Whether to create an authors file. **create_conventional_commits_edit_message** - Whether to use a commit message that helps you adhere to the - `Conventional Commits `_ - specification. + Whether to use a commit message that helps you adhere to the + `Conventional Commits `_ + specification. + + If you plan to use the create_auto_CHANGELOG feature, this template will + help you keep your messages in the correct format for the auto CHANGELOG + feature. .. important:: @@ -80,6 +93,25 @@ project. git config --local commit.template .github/.git-commit-template.txt +**create_auto_CHANGELOG** + create_auto_CHANGELOG will use GitHub actions to generate a changelog using + a cron job, scheduled daily. + +**github_access_token** + For new or small repositories, select `secrets.GITHUB_TOKEN`. + This is adequate for most small packages. + + For larger repositories, the `GITHUB_TOKEN` may error on the rate limit when + generating the CHANGELOG. If so you will need a PAT so + select `secrets.CHANGELOG_UPDATE`. + + After generating your GitHub PAT, ensure you use `CHANGELOG_UPDATE` as the + repository secret name. Be careful not to share the secret or commit it to + the repository accidentally. + + See `Encrypted Secrets `_ + for more information on generating secrets and repository security. + **open_source_license** Choose a `license `_. Options: diff --git a/docs/source/tutorial.rst b/docs/source/tutorial.rst index 7351394..942e304 100644 --- a/docs/source/tutorial.rst +++ b/docs/source/tutorial.rst @@ -15,12 +15,53 @@ top of the page at `GitHub Help`_. .. _`GitHub account`: https://github.com/ .. _`GitHub Help`: https://help.github.com/ +Step 1: Create a GitHub Repo +---------------------------- + +We do this step first to make sure that your new package name is available. + +Your GitHub package name can use a hyphen -, however, the module name must use +an underscore _. + +Don't worry; we have your back; go right ahead if you would like to use hyphens +in your package name. We generate your module names correctly using +underscores from the information gathered when you cookiecutter your new +project. + +.. todo:: + + #. Fix the git repo bash commands in Step 1 of the tutorial. + #. The git bash commands may be better lower down the list as well. + + See `Issue 69 `_. + +.. code-block:: bash + + cd mypackage + git init . + git add . + git config --local commit.template .github/.git-commit-template.txt + git commit -m "Initial skeleton." + git remote add origin git@github.com:myusername/mypackage.git + git push -u origin main + +Where ``myusername`` and ``mypackage`` are adjusted for your username and +package name. + +You will need an ssh key to push local changes to your repository. + +You can `Generate`_ a new key or `Add`_ an existing one. -Step 1: Install Cookiecutter +.. _`Generate`: https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ +.. _`Add`: https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/ + + +Step 2: Install Cookiecutter ---------------------------- First, you need to create and activate a virtualenv for the package project. -Use your favorite method, or create a virtualenv for your new package like this: +Use your favourite method, or create a virtualenv for your new package +like this: .. code-block:: bash @@ -34,8 +75,14 @@ Activate your environment: source bin/activate +or use the . source shortcut like this + +.. code-block:: bash + + . bin/activate + On Windows, activate it like this. You may find that using a Command Prompt -window works better than gitbash. +Terminal works better than gitbash. .. code-block:: powershell @@ -49,59 +96,29 @@ Install cookiecutter: pip install cookiecutter -Step 2: Generate Your Package +Step 3 : Generate Your Package ----------------------------- Now it's time to generate your Python package. -Use cookiecutter, pointing it at the cookiecutter-py3-package repo: +Use cookiecutter, pointing it to the cookiecutter-py3-package repository: .. code-block:: bash cookiecutter https://github.com/imAsparky/cookiecutter-py3-package.git -You'll be asked to enter a bunch of values to set the package up. -If you don't know what to enter, stick with the defaults. - - -Step 3: Create a GitHub Repo ----------------------------- - -Go to your GitHub account and create a new repo named ``mypackage``, where -``mypackage`` matches the ``[project_slug]`` from your answers to running -cookiecutter. This is so that Travis CI and pyup.io can find it when we get -to Step 5. - -``If your virtualenv folder is within your project folder, be sure to add the -virtualenv folder name to your .gitignore file.`` - -You will find one folder named after the ``[project_slug]``. Move into this -folder, and then setup git to use your GitHub repo and upload the code: - -.. code-block:: bash - - cd mypackage - git init . - git add . - git config --local commit.template .github/.git-commit-template.txt - git commit -m "Initial skeleton." - git remote add origin git@github.com:myusername/mypackage.git - git push -u origin main - -Where ``myusername`` and ``mypackage`` are adjusted for your username and package name. +Cookiecutter will ask questions to set your package up. +If you're unsure or don't know what to enter, stick with the defaults. -You'll need a ssh key to push the repo. You can `Generate`_ a key or `Add`_ an existing one. - -.. _`Generate`: https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/ -.. _`Add`: https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/ Step 4: Install Dev Requirements -------------------------------- -You should still be in the folder containing the ``requirements_dev.txt`` file. +You should still be in the root folder, the one containing the +``requirements_dev.txt`` file. -Your virtualenv should still be activated. If it isn't, activate it now. +Check your virtualenv is still activated. If it isn't, activate it now. Install the new project's local development requirements: .. code-block:: bash @@ -149,7 +166,7 @@ Install the new project's local development requirements: Step 5: Set Up Read the Docs ---------------------------- -`Read the Docs`_ hosts documentation for the open source community. Think of it +`Read the Docs`_ hosts documentation for the open-source community. Think of it as Continuous Documentation. Log into your account at `Read the Docs`_ . If you don't have one, create one @@ -162,6 +179,7 @@ repository and follow the directions. Now your documentation will get rebuilt when you make documentation changes to your package. + .. _`Read the Docs`: https://readthedocs.org/ Step 6: Set Up pyup.io @@ -177,11 +195,19 @@ Click on the green ``Add Repo`` button in the top left corner and select the repo you created in Step 3. A popup will ask you whether you want to pin your dependencies. Click on ``Pin`` to add the repo. -Once your repo is set up correctly, the pyup.io badge will show your current +When your repository is correctly set up, the pyup.io badge will show your current update status. + .. _`pyup.io`: https://pyup.io/ + +.. todo:: + + Add a tutorial to describe using Test Pypi. + + See `Issue 13 `_. + Step 7: Release on PyPI ----------------------- diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index a95e9e2..c5e7ddb 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -"""cookiecutter-p3-package post package generation jobs.""" +"""cookiecutter-py3-package post package generation jobs.""" import os PROJECT_DIRECTORY = os.path.realpath(os.path.curdir) @@ -25,3 +25,10 @@ def remove_file(filepath): if "{{ cookiecutter.create_conventional_commits_edit_message }}" != "y": remove_file(".github/.git-commit-template.txt") + + if "{{ cookiecutter.create_auto_CHANGELOG }}" != "y": + remove_file("CHANGELOG.md") + remove_file(".github/workflows/update-changelog.yaml") + + if "{{ cookiecutter.create_auto_CHANGELOG }}" == "y": + remove_file("HISTORY.rst") diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index 51485e0..dd1844e 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -9,9 +9,8 @@ if not re.match(MODULE_REGEX, MODULE_NAME): print( - "ERROR: The project slug (%s) is not a valid Python module name.\ - Please do not use a - and use _ instead" - % MODULE_NAME + f"ERROR: The project slug {MODULE_NAME} is not a valid Python module\ + name. Please do not use a - and use _ instead" ) # Exit to cancel project diff --git a/tests/test_bake_project.py b/tests/test_bake_project.py index 037fcb2..d251055 100644 --- a/tests/test_bake_project.py +++ b/tests/test_bake_project.py @@ -1,4 +1,4 @@ -"""Test suite for cookiecutter-py3-package.""" +"""cookiecutter-py3-package test suite.""" import datetime import importlib @@ -66,7 +66,7 @@ def test_year_compute_in_license_file(cookies): Check year exists in package license file. """ with bake_in_temp_dir(cookies) as result: - license_file_path = result.project.join('LICENSE') + license_file_path = result.project.join("LICENSE") now = datetime.datetime.now() assert str(now.year) in license_file_path.read() @@ -91,13 +91,10 @@ def test_bake_with_defaults(cookies): assert result.exception is None found_toplevel_files = [f.basename for f in result.project.listdir()] - assert 'setup.py' in found_toplevel_files - assert 'python_boilerplate' in found_toplevel_files - assert 'tox.ini' in found_toplevel_files - assert 'tests' in found_toplevel_files - - - + assert "setup.py" in found_toplevel_files + assert "python_3_package_boilerplate" in found_toplevel_files + assert "tox.ini" in found_toplevel_files + assert "tests" in found_toplevel_files def test_bake_and_run_tests(cookies): @@ -127,8 +124,7 @@ def test_bake_withspecialchars_and_run_tests(cookies): (expression-not-assigned) pre-commit pylint error. """ with bake_in_temp_dir( - cookies, - extra_context={'full_name': 'name "quote" name'} + cookies, extra_context={"full_name": 'name "quote" name'} ) as result: assert result.project.isdir() # run_inside_dir('python setup.py test', str(result.project)) == 0 @@ -144,10 +140,7 @@ def test_bake_with_apostrophe_and_run_tests(cookies): str(result.project)) == 0" is assigned to nothing (expression-not-assigned) pre-commit pylint error. """ - with bake_in_temp_dir( - cookies, - extra_context={'full_name': "O'connor"} - ) as result: + with bake_in_temp_dir(cookies, extra_context={"full_name": "O'connor"}) as result: assert result.project.isdir() # run_inside_dir('python setup.py test', str(result.project)) == 0 @@ -156,24 +149,21 @@ def test_bake_without_author_file(cookies): """ Test cookiecutter created the package without an author file. """ - with bake_in_temp_dir( - cookies, - extra_context={'create_author_file': 'n'} - ) as result: + with bake_in_temp_dir(cookies, extra_context={"create_author_file": "n"}) as result: found_toplevel_files = [f.basename for f in result.project.listdir()] - assert 'AUTHORS.rst' not in found_toplevel_files - doc_files = [f.basename for f in result.project.join('docs').listdir()] - assert 'authors.rst' not in doc_files + assert "AUTHORS.rst" not in found_toplevel_files + doc_files = [f.basename for f in result.project.join("docs").listdir()] + assert "authors.rst" not in doc_files # Assert there are no spaces in the toc tree - docs_index_path = result.project.join('docs/index.rst') + docs_index_path = result.project.join("docs/index.rst") with open(str(docs_index_path)) as index_file: - assert 'contributing\n history' in index_file.read() + assert "contributing\n history" in index_file.read() # Check that - manifest_path = result.project.join('MANIFEST.in') + manifest_path = result.project.join("MANIFEST.in") with open(str(manifest_path)) as manifest_file: - assert 'AUTHORS.rst' not in manifest_file.read() + assert "AUTHORS.rst" not in manifest_file.read() def test_make_help(cookies): @@ -183,12 +173,8 @@ def test_make_help(cookies): with bake_in_temp_dir(cookies) as result: # The supplied Makefile does not support win32 if sys.platform != "win32": - output = check_output_inside_dir( - 'make help', - str(result.project) - ) - assert b"check code coverage quickly with the default Python" in \ - output + output = check_output_inside_dir("make help", str(result.project)) + assert b"check code coverage quickly with the default Python" in output def test_bake_selecting_license(cookies): @@ -196,21 +182,19 @@ def test_bake_selecting_license(cookies): Test cookiecutter created the package with the correct license. """ license_strings = { - 'MIT license': 'MIT ', - 'BSD license': 'Redistributions of source code must retain the ' + - 'above copyright notice, this', - 'ISC license': 'ISC License', - 'Apache Software License 2.0': - 'Licensed under the Apache License, Version 2.0', - 'GNU General Public License v3': 'GNU GENERAL PUBLIC LICENSE', + "MIT license": "MIT ", + "BSD license": "Redistributions of source code must retain the " + + "above copyright notice, this", + "ISC license": "ISC License", + "Apache Software License 2.0": "Licensed under the Apache License, Version 2.0", + "GNU General Public License v3": "GNU GENERAL PUBLIC LICENSE", } for license, target_string in license_strings.items(): with bake_in_temp_dir( - cookies, - extra_context={'open_source_license': license} + cookies, extra_context={"open_source_license": license} ) as result: - assert target_string in result.project.join('LICENSE').read() - assert license in result.project.join('setup.py').read() + assert target_string in result.project.join("LICENSE").read() + assert license in result.project.join("setup.py").read() def test_bake_not_open_source(cookies): @@ -218,13 +202,12 @@ def test_bake_not_open_source(cookies): Test cookiecutter created the package as not open source. """ with bake_in_temp_dir( - cookies, - extra_context={'open_source_license': 'Not open source'} + cookies, extra_context={"open_source_license": "Not open source"} ) as result: found_toplevel_files = [f.basename for f in result.project.listdir()] - assert 'setup.py' in found_toplevel_files - assert 'LICENSE' not in found_toplevel_files - assert 'License' not in result.project.join('README.rst').read() + assert "setup.py" in found_toplevel_files + assert "LICENSE" not in found_toplevel_files + assert "License" not in result.project.join("README.rst").read() def test_using_pytest(cookies): @@ -237,16 +220,13 @@ def test_using_pytest(cookies): str(result.project)) == 0" is assigned to nothing (expression-not-assigned) pre-commit pylint error. """ - with bake_in_temp_dir( - cookies, - extra_context={'use_pytest': 'y'} - ) as result: + with bake_in_temp_dir(cookies, extra_context={"use_pytest": "y"}) as result: assert result.project.isdir() test_file_path = result.project.join( - 'tests/test_python_boilerplate.py' + "tests/test_python_3_package_boilerplate.py" ) lines = test_file_path.readlines() - assert "import pytest" in ''.join(lines) + assert "import pytest" in "".join(lines) # Test the new pytest target # run_inside_dir('pytest', str(result.project)) == 0 @@ -258,125 +238,104 @@ def test_not_using_pytest(cookies): with bake_in_temp_dir(cookies) as result: assert result.project.isdir() test_file_path = result.project.join( - 'tests/test_python_boilerplate.py' + "tests/test_python_3_package_boilerplate.py" ) lines = test_file_path.readlines() - assert "import unittest" in ''.join(lines) - assert "import pytest" not in ''.join(lines) - - -# def test_project_with_hyphen_in_module_name(cookies): -# result = cookies.bake( -# extra_context={'project_name': 'something-with-a-dash'} -# ) -# assert result.project is not None -# project_path = str(result.project) -# -# # when: -# travis_setup_cmd = ('python travis_pypi_setup.py' -# ' --repo audreyr/cookiecutter-pypackage' -# ' --password invalidpass') -# run_inside_dir(travis_setup_cmd, project_path) -# -# # then: -# result_travis_config = yaml.load( -# open(os.path.join(project_path, ".travis.yml")) -# ) -# assert "secure" in result_travis_config["deploy"]["password"],\ -# "missing password config in .travis.yml" + assert "import unittest" in "".join(lines) + assert "import pytest" not in "".join(lines) def test_bake_with_no_console_script(cookies): """ Test cookiecutter created the package without console script files. """ - context = {'command_line_interface': "No command-line interface"} + context = {"command_line_interface": "No command-line interface"} result = cookies.bake(extra_context=context) project_path, project_slug, project_dir = project_info(result) found_project_files = os.listdir(project_dir) assert "cli.py" not in found_project_files - setup_path = os.path.join(project_path, 'setup.py') - with open(setup_path, 'r') as setup_file: - assert 'entry_points' not in setup_file.read() + setup_path = os.path.join(project_path, "setup.py") + with open(setup_path, "r") as setup_file: + assert "entry_points" not in setup_file.read() def test_bake_with_console_script_files(cookies): """ Test cookiecutter created the package with console script files. """ - context = {'command_line_interface': 'click'} + context = {"command_line_interface": "click"} result = cookies.bake(extra_context=context) project_path, project_slug, project_dir = project_info(result) found_project_files = os.listdir(project_dir) assert "cli.py" in found_project_files - setup_path = os.path.join(project_path, 'setup.py') - with open(setup_path, 'r') as setup_file: - assert 'entry_points' in setup_file.read() + setup_path = os.path.join(project_path, "setup.py") + with open(setup_path, "r") as setup_file: + assert "entry_points" in setup_file.read() def test_bake_with_argparse_console_script_files(cookies): """ Test cookiecutter created the package with argparse console script files. """ - context = {'command_line_interface': 'argparse'} + context = {"command_line_interface": "argparse"} result = cookies.bake(extra_context=context) project_path, project_slug, project_dir = project_info(result) found_project_files = os.listdir(project_dir) assert "cli.py" in found_project_files - setup_path = os.path.join(project_path, 'setup.py') - with open(setup_path, 'r') as setup_file: - assert 'entry_points' in setup_file.read() + setup_path = os.path.join(project_path, "setup.py") + with open(setup_path, "r") as setup_file: + assert "entry_points" in setup_file.read() def test_bake_with_console_script_cli(cookies): """ Test cookiecutter created the package with console script cli files. """ - context = {'command_line_interface': 'click'} + context = {"command_line_interface": "click"} result = cookies.bake(extra_context=context) project_path, project_slug, project_dir = project_info(result) - module_path = os.path.join(project_dir, 'cli.py') - module_name = '.'.join([project_slug, 'cli']) + module_path = os.path.join(project_dir, "cli.py") + module_name = ".".join([project_slug, "cli"]) spec = importlib.util.spec_from_file_location(module_name, module_path) cli = importlib.util.module_from_spec(spec) spec.loader.exec_module(cli) runner = CliRunner() noarg_result = runner.invoke(cli.main) assert noarg_result.exit_code == 0 - noarg_output = ' '.join([ - 'Replace this message by putting your code into', - project_slug]) + noarg_output = " ".join( + ["Replace this message by putting your code into", project_slug] + ) assert noarg_output in noarg_result.output - help_result = runner.invoke(cli.main, ['--help']) + help_result = runner.invoke(cli.main, ["--help"]) assert help_result.exit_code == 0 - assert 'Show this message' in help_result.output + assert "Show this message" in help_result.output def test_bake_with_argparse_console_script_cli(cookies): """ Test cookiecutter created the package with argparse console script files. """ - context = {'command_line_interface': 'argparse'} + context = {"command_line_interface": "argparse"} result = cookies.bake(extra_context=context) project_path, project_slug, project_dir = project_info(result) - module_path = os.path.join(project_dir, 'cli.py') - module_name = '.'.join([project_slug, 'cli']) + module_path = os.path.join(project_dir, "cli.py") + module_name = ".".join([project_slug, "cli"]) spec = importlib.util.spec_from_file_location(module_name, module_path) cli = importlib.util.module_from_spec(spec) spec.loader.exec_module(cli) runner = CliRunner() noarg_result = runner.invoke(cli.main) assert noarg_result.exit_code == 0 - noarg_output = ' '.join([ - 'Replace this message by putting your code into', - project_slug]) + noarg_output = " ".join( + ["Replace this message by putting your code into", project_slug] + ) assert noarg_output in noarg_result.output - help_result = runner.invoke(cli.main, ['--help']) + help_result = runner.invoke(cli.main, ["--help"]) assert help_result.exit_code == 0 - assert 'Show this message' in help_result.output + assert "Show this message" in help_result.output @pytest.mark.parametrize("use_black,expected", [("y", True), ("n", False)]) @@ -384,23 +343,67 @@ def test_black(cookies, use_black, expected): """ Test cookiecutter created the package with black configured. """ - with bake_in_temp_dir( - cookies, - extra_context={'use_black': use_black} - ) as result: + with bake_in_temp_dir(cookies, extra_context={"use_black": use_black}) as result: assert result.project.isdir() - requirements_path = result.project.join('requirements_dev.txt') + requirements_path = result.project.join("requirements_dev.txt") assert ("black" in requirements_path.read()) is expected - makefile_path = result.project.join('Makefile') + makefile_path = result.project.join("Makefile") assert ("black --check" in makefile_path.read()) is expected + +def test_bake_with_conventional_commits_message(cookies): + """ + Test cookiecutter created the package with a conventional commits message. + """ + with bake_in_temp_dir( + cookies, extra_context={"create_conventional_commits_edit_message": "y"} + ) as result: + + git_with_files = [f.basename for f in result.project.join(".github").listdir()] + assert ".git-commit-template.txt" in git_with_files + + def test_bake_without_conventional_commits_message(cookies): + """ + Test cookiecutter created the package without conventional commits message. + """ with bake_in_temp_dir( cookies, extra_context={"create_conventional_commits_edit_message": "n"} ) as result: - git_files = [f.basename for f in result.project.join(".github").listdir()] - print("git files ", git_files) - assert ".git-commit-template.txt" not in git_files + git_without_files = [ + f.basename for f in result.project.join(".github").listdir() + ] + assert ".git-commit-template.txt" not in git_without_files + + +def test_bake_with_automatic_CHANGELOG(cookies): + """ + Test cookiecutter created the package with a auto changelog generation. + """ + with bake_in_temp_dir( + cookies, extra_context={"create_auto_CHANGELOG": "y"} + ) as result: + + change_log_with_files = [f.basename for f in result.project.listdir()] + assert "CHANGELOG.md" in change_log_with_files + assert "HISTORY.rst" not in change_log_with_files + + auto_workflow_with_files = [ + f.basename for f in result.project.join(".github/workflows").listdir() + ] + assert "update-changelog.yaml" in auto_workflow_with_files + + +def test_bake_without_automatic_CHANGELOG(cookies): + with bake_in_temp_dir( + cookies, extra_context={"create_auto_CHANGELOG": "n"} + ) as result: + change_log_without_files = [f.basename for f in result.project.listdir()] + assert "CHANGELOG.md" not in change_log_without_files + auto_workflow_without_files = [ + f.basename for f in result.project.join(".github/workflows").listdir() + ] + assert "update-changelog.yaml" not in auto_workflow_without_files diff --git a/tox.ini b/tox.ini index 05ff6e0..4a6d29d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,13 @@ - [tox] -envlist = py36, py37,py38, py39, py38 pypy, docs skipsdist = true skip_missing_interpreters = true +envlist = + py36 + py37 + py38 + py39 + py38 pypy + docs [testenv:docs] basepython=python @@ -25,12 +30,10 @@ PLATFORM = macos-latest: macos windows-latest: windows - [testenv] setenv = PYTHONPATH = {toxinidir} deps = -r{toxinidir}/requirements_dev.txt commands = - python -m pip install --upgrade pip - pytest + pytest -v {posargs:tests} diff --git a/{{cookiecutter.project_slug}}/.github/workflows/update-changelog.yaml b/{{cookiecutter.project_slug}}/.github/workflows/update-changelog.yaml new file mode 100644 index 0000000..3efda91 --- /dev/null +++ b/{{cookiecutter.project_slug}}/.github/workflows/update-changelog.yaml @@ -0,0 +1,36 @@ +name: Auto-generate CHANGELOG +on: + # release: + # types: [created, edited] + + # cron job is set for daily update at utc time + schedule: + - cron: "0 23 * * *" + # push: + # branches: + # - main + workflow_dispatch: + +jobs: + generate-changelog: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + - uses: BobAnkh/auto-generate-changelog@master + with: + REPO_NAME: "{{cookiecutter.github_username}}/\ + {{cookiecutter.git_project_name}}" + ACCESS_TOKEN: ${{cookiecutter.github_access_token}} + PATH: "/CHANGELOG.md" + COMMIT_MESSAGE: "docs(CHANGELOG): update release notes:docs" + TYPE: "chore:Chore,\ + feat:Feature,\ + fix:Bug Fixes,\ + docs:Documentation,\ + perf:Performance Improvements,\ + refactor:Refactor,\ + style:Styling,\ + test:Tests,\ + WIP:In Progress" diff --git a/{{cookiecutter.project_slug}}/CHANGELOG.md b/{{cookiecutter.project_slug}}/CHANGELOG.md new file mode 100644 index 0000000..a0cf709 --- /dev/null +++ b/{{cookiecutter.project_slug}}/CHANGELOG.md @@ -0,0 +1 @@ +# CHANGELOG diff --git a/{{cookiecutter.project_slug}}/MANIFEST.in b/{{cookiecutter.project_slug}}/MANIFEST.in index 11708e4..924c364 100644 --- a/{{cookiecutter.project_slug}}/MANIFEST.in +++ b/{{cookiecutter.project_slug}}/MANIFEST.in @@ -1,6 +1,12 @@ {% if cookiecutter.create_author_file == 'y' -%} include AUTHORS.rst {% endif -%} + +{% if cookiecutter.create_auto_CHANGELOG == 'y' -%} +include CHANGELOG.md +{% endif -%} + + include CONTRIBUTING.rst include HISTORY.rst include LICENSE