Repository: cookiecutter/cookiecutter-django

Issue:
Optionally generate a .gitlab-ci.yml
- It should be optional. In `cookiecutter.json` we should have `"use_gitlab_ci": "n",`
- It should be pre-configured to run the test suite upon commit
- Document how it works in:
  - `docs/project-generation-options.rst` (broadly)
  - `docs/ci-gitlab.rst` (in detail)
- Continuous deployment might be nice as well, at least for one of the deployment options



Discussion:
I have a Cookiecutter Django project using GitLab CI and Docker with compose and machine for continuous deployment.  The basic pipeline is pushes to all branches run the tests (including flake8 and coverage), pushes to master and production branches also automatically deploy to beta.{{cookiecutter.domain_name}} and {{cookiecutter.domain_name}}, respectively.

The [.gitlab-ci.yml](https://github.com/pydanny/cookiecutter-django/files/307021/default.gitlab-ci.yml.txt) looks something like this.

I can put together a PR with documentation if there's interest, unless someone beats me to it. :)


Resolving patch:
diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py
--- a/hooks/post_gen_project.py
+++ b/hooks/post_gen_project.py
@@ -70,7 +70,7 @@ def remove_heroku_files():
     for file_name in file_names:
         if (
             file_name == "requirements.txt"
-            and "{{ cookiecutter.use_travisci }}".lower() == "y"
+            and "{{ cookiecutter.ci_tool }}".lower() == "travis"
         ):
             # don't remove the file if we are using travisci but not using heroku
             continue
@@ -105,6 +105,10 @@ def remove_dottravisyml_file():
     os.remove(".travis.yml")
 
 
+def remove_dotgitlabciyml_file():
+    os.remove(".gitlab-ci.yml")
+
+
 def append_to_project_gitignore(path):
     gitignore_file_path = ".gitignore"
     with open(gitignore_file_path, "a") as gitignore_file:
@@ -349,9 +353,12 @@ def main():
         if "{{ cookiecutter.use_docker }}".lower() == "y":
             remove_celery_compose_dirs()
 
-    if "{{ cookiecutter.use_travisci }}".lower() == "n":
+    if "{{ cookiecutter.ci_tool }}".lower() != "travis":
         remove_dottravisyml_file()
 
+    if "{{ cookiecutter.ci_tool }}".lower() != "gitlab":
+        remove_dotgitlabciyml_file()
+
     print(SUCCESS + "Project initialized, keep up the good work!" + TERMINATOR)
 
 


Test patch:
diff --git a/tests/test_cookiecutter_generation.py b/tests/test_cookiecutter_generation.py
--- a/tests/test_cookiecutter_generation.py
+++ b/tests/test_cookiecutter_generation.py
@@ -140,7 +140,7 @@ def test_black_passes(cookies, context_combination):
 
 
 def test_travis_invokes_pytest(cookies, context):
-    context.update({"use_travisci": "y"})
+    context.update({"ci_tool": "Travis"})
     result = cookies.bake(extra_context=context)
 
     assert result.exit_code == 0
@@ -155,6 +155,24 @@ def test_travis_invokes_pytest(cookies, context):
             pytest.fail(e)
 
 
+def test_gitlab_invokes_flake8_and_pytest(cookies, context):
+    context.update({"ci_tool": "Gitlab"})
+    result = cookies.bake(extra_context=context)
+
+    assert result.exit_code == 0
+    assert result.exception is None
+    assert result.project.basename == context["project_slug"]
+    assert result.project.isdir()
+
+    with open(f"{result.project}/.gitlab-ci.yml", "r") as gitlab_yml:
+        try:
+            gitlab_config = yaml.load(gitlab_yml)
+            assert gitlab_config["flake8"]["script"] == ["flake8"]
+            assert gitlab_config["pytest"]["script"] == ["pytest"]
+        except yaml.YAMLError as e:
+            pytest.fail(e)
+
+
 @pytest.mark.parametrize("slug", ["project slug", "Project_Slug"])
 def test_invalid_slug(cookies, context, slug):
     """Invalid slug should failed pre-generation hook."""