diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..84b4b4411 --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +exclude = docs +max-line-length = 119 diff --git a/.github/CONTRIBUTORS-template.md b/.github/CONTRIBUTORS-template.md index d8ba28c63..bc0928478 100644 --- a/.github/CONTRIBUTORS-template.md +++ b/.github/CONTRIBUTORS-template.md @@ -22,8 +22,8 @@ accept and merge pull requests. {%- endfor %} -*Audrey is also the creator of Cookiecutter. Audrey and Daniel are on -the Cookiecutter core team.* +_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on +the Cookiecutter core team._ ## Other Contributors @@ -51,6 +51,6 @@ Listed in alphabetical order. The following haven't provided code directly, but have provided guidance and advice. -- Jannis Leidel -- Nate Aune -- Barry Morrison +- Jannis Leidel +- Nate Aune +- Barry Morrison diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md index e984493d8..0e5ec12c4 100644 --- a/.github/ISSUE_TEMPLATE/bug.md +++ b/.github/ISSUE_TEMPLATE/bug.md @@ -12,41 +12,47 @@ labels: bug -* Host system configuration: - * Version of cookiecutter CLI (get it with `cookiecutter --version`): - * OS name and version: +- Host system configuration: - On Linux, run - ```bash - lsb_release -a 2> /dev/null || cat /etc/redhat-release 2> /dev/null || cat /etc/*-release 2> /dev/null || cat /etc/issue 2> /dev/null - ``` + - Version of cookiecutter CLI (get it with `cookiecutter --version`): + - OS name and version: - On MacOs, run - ```bash - sw_vers - ``` + On Linux, run - On Windows, via CMD, run - ``` - systeminfo | findstr /B /C:"OS Name" /C:"OS Version" - ``` - - - ```bash - # Insert here the OS name and version - - ``` - - * Python version, run `python3 -V`: - * Docker version (if using Docker), run `docker --version`: - * docker-compose version (if using Docker), run `docker-compose --version`: - * ... -* Options selected and/or [replay file](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html): - On Linux and MacOS: `cat ${HOME}/.cookiecutter_replay/cookiecutter-django.json` - (Please, take care to remove sensitive information) - ```json - # Insert here the replay file content + ```bash + lsb_release -a 2> /dev/null || cat /etc/redhat-release 2> /dev/null || cat /etc/*-release 2> /dev/null || cat /etc/issue 2> /dev/null ``` + + On MacOs, run + + ```bash + sw_vers + ``` + + On Windows, via CMD, run + + ``` + systeminfo | findstr /B /C:"OS Name" /C:"OS Version" + ``` + + ```bash + # Insert here the OS name and version + + ``` + + - Python version, run `python3 -V`: + - Docker version (if using Docker), run `docker --version`: + - docker-compose version (if using Docker), run `docker-compose --version`: + - ... + +- Options selected and/or [replay file](https://cookiecutter.readthedocs.io/en/latest/advanced/replay.html): + On Linux and macOS: `cat ${HOME}/.cookiecutter_replay/cookiecutter-django.json` + (Please, take care to remove sensitive information) + +```json + +``` + Logs:
diff --git a/.github/ISSUE_TEMPLATE/paid-support.md b/.github/ISSUE_TEMPLATE/paid-support.md index 9f997a8c8..f4e7578a8 100644 --- a/.github/ISSUE_TEMPLATE/paid-support.md +++ b/.github/ISSUE_TEMPLATE/paid-support.md @@ -5,8 +5,8 @@ about: Ask Core Team members to help you out Provided your question goes beyond [regular support](https://github.com/cookiecutter/cookiecutter-django/issues/new?template=question.md), and/or the task at hand is of timely/high priority nature use the below information to reach out for contributors directly. -* Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB. +- Bruno Alla, Core Developer ([GitHub](https://github.com/sponsors/browniebroke)). -* Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience. +- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB. -* Bruno Alla, Core Developer ([GitHub](https://github.com/sponsors/browniebroke)). +- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 10b66e266..2b197873f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,5 @@ - ## Description diff --git a/.github/changelog-template.md b/.github/changelog-template.md index 50aab38e1..64bb71790 100644 --- a/.github/changelog-template.md +++ b/.github/changelog-template.md @@ -1,8 +1,11 @@ {%- for change_type, pulls in grouped_pulls.items() %} {%- if pulls %} + ### {{ change_type }} + {%- for pull_request in pulls %} + - {{ pull_request.title }} ([#{{ pull_request.number }}]({{ pull_request.html_url }})) -{%- endfor -%} -{% endif -%} -{% endfor -%} + {%- endfor -%} + {% endif -%} + {% endfor -%} diff --git a/.github/contributors.json b/.github/contributors.json index 34c84979d..37c85e1bc 100644 --- a/.github/contributors.json +++ b/.github/contributors.json @@ -1347,5 +1347,50 @@ "name": "Robin", "github_login": "Kaffeetasse", "twitter_username": "" + }, + { + "name": "Patrick Tran", + "github_login": "theptrk", + "twitter_username": "" + }, + { + "name": "tildebox", + "github_login": "tildebox", + "twitter_username": "" + }, + { + "name": "duffn", + "github_login": "duffn", + "twitter_username": "" + }, + { + "name": "Delphine LEMIRE", + "github_login": "DelphineLemire", + "twitter_username": "" + }, + { + "name": "Hoai-Thu Vuong", + "github_login": "thuvh", + "twitter_username": "" + }, + { + "name": "Arkadiusz Michał Ryś", + "github_login": "arrys", + "twitter_username": "" + }, + { + "name": "mpsantos", + "github_login": "mpsantos", + "twitter_username": "" + }, + { + "name": "Morten Kaae", + "github_login": "MortenKaae", + "twitter_username": "" + }, + { + "name": "Birtibu", + "github_login": "Birtibu", + "twitter_username": "" } ] \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8922cd450..7642a3f2d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,3 +18,71 @@ updates: interval: "daily" labels: - "update" + + # Enable version updates for Docker + # We need to specify each Dockerfile in a separate entry because Dependabot doesn't + # support wildcards or recursively checking subdirectories. Check this issue for updates: + # https://github.com/dependabot/dependabot-core/issues/2178 + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/local/django/" + schedule: + interval: "daily" + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" + labels: + - "update" + + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/local/docs/" + schedule: + interval: "daily" + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" + labels: + - "update" + + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/local/node/" + schedule: + interval: "daily" + labels: + - "update" + + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/production/aws/" + schedule: + interval: "daily" + labels: + - "update" + + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/production/django/" + schedule: + interval: "daily" + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" + labels: + - "update" + + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/production/postgres/" + schedule: + interval: "daily" + labels: + - "update" + + - package-ecosystem: "docker" + directory: "{{cookiecutter.project_slug}}/compose/production/traefik/" + schedule: + interval: "daily" + labels: + - "update" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d466f4032..dbda77b5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,7 @@ name: CI on: push: + branches: ["master", "main"] pull_request: concurrency: @@ -9,17 +10,6 @@ concurrency: cancel-in-progress: true jobs: - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v4 - with: - python-version: "3.10" - cache: pip - - name: Run pre-commit - uses: pre-commit/action@v3.0.0 - tests: strategy: fail-fast: false @@ -29,18 +19,18 @@ jobs: - windows-latest - macOS-latest - name: "Run tests" + name: "pytest ${{ matrix.os }}" runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" cache: pip - name: Install dependencies run: pip install -r requirements.txt - name: Run tests - run: pytest tests + run: pytest -n auto tests docker: strategy: @@ -48,11 +38,15 @@ jobs: matrix: script: - name: Basic - args: "" - - name: Extended - args: "use_celery=y use_drf=y frontend_pipeline=Gulp" + args: "ci_tool=Gitlab" + - name: Celery & DRF + args: "use_celery=y use_drf=y" + - name: Gulp + args: "frontend_pipeline=Gulp" + - name: Webpack + args: "frontend_pipeline=Webpack" - name: "${{ matrix.script.name }} Docker" + name: "Docker ${{ matrix.script.name }}" runs-on: ubuntu-latest env: DOCKER_BUILDKIT: 1 @@ -62,7 +56,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" cache: pip - name: Install dependencies run: pip install -r requirements.txt @@ -74,12 +68,16 @@ jobs: fail-fast: false matrix: script: - - name: With Celery + - name: Celery args: "use_celery=y frontend_pipeline='Django Compressor'" - - name: With Gulp - args: "frontend_pipeline='Gulp'" + - name: Gulp + args: "frontend_pipeline=Gulp" + - name: Webpack + args: "frontend_pipeline=Webpack use_heroku=y" + - name: Email Username + args: "username_type=email ci_tool=Github" - name: "${{ matrix.script.name }} Bare metal" + name: "Bare metal ${{ matrix.script.name }}" runs-on: ubuntu-latest services: redis: @@ -102,7 +100,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" cache: pip cache-dependency-path: | requirements.txt @@ -112,6 +110,6 @@ jobs: run: pip install -r requirements.txt - uses: actions/setup-node@v3 with: - node-version: "16" + node-version: "18" - name: Bare Metal ${{ matrix.script.name }} run: sh tests/test_bare.sh ${{ matrix.script.args }} diff --git a/.github/workflows/django-issue-checker.yml b/.github/workflows/django-issue-checker.yml index fd250604f..cbfea922d 100644 --- a/.github/workflows/django-issue-checker.yml +++ b/.github/workflows/django-issue-checker.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/pre-commit-autoupdate.yml b/.github/workflows/pre-commit-autoupdate.yml index 1708e8b82..75bfe0a20 100644 --- a/.github/workflows/pre-commit-autoupdate.yml +++ b/.github/workflows/pre-commit-autoupdate.yml @@ -16,15 +16,15 @@ jobs: # Disables this workflow from running in a repository that is not part of the indicated organization/user if: github.repository_owner == 'cookiecutter' permissions: - contents: write # for peter-evans/create-pull-request to create branch - pull-requests: write # for peter-evans/create-pull-request to create a PR + contents: write # for peter-evans/create-pull-request to create branch + pull-requests: write # for peter-evans/create-pull-request to create a PR runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" - name: Install pre-commit run: pip install pre-commit @@ -37,7 +37,7 @@ jobs: run: pre-commit autoupdate - name: Create Pull Request - uses: peter-evans/create-pull-request@v4 + uses: peter-evans/create-pull-request@v5 with: token: ${{ secrets.GITHUB_TOKEN }} branch: update/pre-commit-autoupdate diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 27113a89f..f48f297aa 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.github/workflows/update-contributors.yml b/.github/workflows/update-contributors.yml index 83c651a46..78d72c241 100644 --- a/.github/workflows/update-contributors.yml +++ b/.github/workflows/update-contributors.yml @@ -13,7 +13,7 @@ jobs: # Disables this workflow from running in a repository that is not part of the indicated organization/user if: github.repository_owner == 'cookiecutter' permissions: - contents: write # for stefanzweifel/git-auto-commit-action to push code in repo + contents: write # for stefanzweifel/git-auto-commit-action to push code in repo runs-on: ubuntu-latest steps: @@ -22,7 +22,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ca86e7eb5..2c7876d3c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,4 +1,4 @@ -exclude: "{{cookiecutter.project_slug}}" +exclude: "{{cookiecutter.project_slug}}|.github/contributors.json|CHANGELOG.md|CONTRIBUTORS.md" default_stages: [commit] repos: @@ -6,22 +6,36 @@ repos: rev: v4.4.0 hooks: - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-json + - id: check-toml + - id: check-xml - id: check-yaml + - id: debug-statements + - id: check-builtin-literals + - id: check-case-conflict + - id: detect-private-key + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: "v3.0.0-alpha.9-for-vscode" + hooks: + - id: prettier + args: ["--tab-width", "2"] - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + rev: v3.4.0 hooks: - id: pyupgrade - args: [--py310-plus] + args: [--py311-plus] exclude: hooks/ - repo: https://github.com/psf/black - rev: 22.12.0 + rev: 23.3.0 hooks: - id: black - repo: https://github.com/PyCQA/isort - rev: 5.11.4 + rev: 5.12.0 hooks: - id: isort diff --git a/.readthedocs.yaml b/.readthedocs.yaml index beb30d845..4598ff77c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,12 +4,17 @@ # Required version: 2 +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # Build documentation in the docs/ directory with Sphinx sphinx: configuration: docs/conf.py -# Version of Python and requirements required to build the docs +# Declare the Python requirements required to build your docs python: - version: "3.8" install: - requirements: docs/requirements.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 00698a012..16b0786d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,477 @@ All enhancements and patches to Cookiecutter Django will be documented in this f +## 2023.05.15 + + +### Updated + +- Update django-cors-headers to 4.0.0 ([#4329](https://github.com/cookiecutter/cookiecutter-django/pull/4329)) + +- Update sentry-sdk to 1.23.0 ([#4337](https://github.com/cookiecutter/cookiecutter-django/pull/4337)) + +## 2023.05.09 + + +### Updated + +- Update werkzeug to 2.3.4 ([#4325](https://github.com/cookiecutter/cookiecutter-django/pull/4325)) + +## 2023.05.08 + + +### Updated + +- Auto-update pre-commit hooks ([#4320](https://github.com/cookiecutter/cookiecutter-django/pull/4320)) + +- Update sentry-sdk to 1.22.2 ([#4321](https://github.com/cookiecutter/cookiecutter-django/pull/4321)) + +## 2023.05.04 + + +### Changed + +- Remove pytz from dependencies ([#4309](https://github.com/cookiecutter/cookiecutter-django/pull/4309)) + +### Updated + +- Update django-anymail to 9.2 ([#4316](https://github.com/cookiecutter/cookiecutter-django/pull/4316)) + +- Update pre-commit to 3.3.1 ([#4315](https://github.com/cookiecutter/cookiecutter-django/pull/4315)) + +- Update coverage to 7.2.5 ([#4314](https://github.com/cookiecutter/cookiecutter-django/pull/4314)) + +- Update django to 4.1.9 ([#4313](https://github.com/cookiecutter/cookiecutter-django/pull/4313)) + +- Update sentry-sdk to 1.21.1 ([#4312](https://github.com/cookiecutter/cookiecutter-django/pull/4312)) + +- Update requests to 2.30.0 ([#4311](https://github.com/cookiecutter/cookiecutter-django/pull/4311)) + +## 2023.05.02 + + +### Updated + +- Upgrade traefik to 2.10.1 ([#4304](https://github.com/cookiecutter/cookiecutter-django/pull/4304)) + +- Update uvicorn to 0.22.0 ([#4305](https://github.com/cookiecutter/cookiecutter-django/pull/4305)) + +- Update werkzeug to 2.3.3 ([#4307](https://github.com/cookiecutter/cookiecutter-django/pull/4307)) + +## 2023.04.28 + + +### Changed + +- Add django-upgrade to pre-commit hooks ([#4298](https://github.com/cookiecutter/cookiecutter-django/pull/4298)) + +## 2023.04.27 + + +### Updated + +- Update djangorestframework-stubs to 3.14.0 ([#4303](https://github.com/cookiecutter/cookiecutter-django/pull/4303)) + +- Update werkzeug to 2.3.1 ([#4302](https://github.com/cookiecutter/cookiecutter-django/pull/4302)) + +- Update django-stubs to 4.2.0 ([#4301](https://github.com/cookiecutter/cookiecutter-django/pull/4301)) + +## 2023.04.26 + + +### Updated + +- Upgrade cssnano to v6.0.0 ([#4233](https://github.com/cookiecutter/cookiecutter-django/pull/4233)) + +- Upgrade concurrently to 8.0.1 ([#4237](https://github.com/cookiecutter/cookiecutter-django/pull/4237)) + +- Upgrade to node v18 ([#4294](https://github.com/cookiecutter/cookiecutter-django/pull/4294)) + +- Update coverage to 7.2.3 ([#4297](https://github.com/cookiecutter/cookiecutter-django/pull/4297)) + +- Update mypy to 1.2.0 ([#4295](https://github.com/cookiecutter/cookiecutter-django/pull/4295)) + +- Update werkzeug to 2.3.0 ([#4296](https://github.com/cookiecutter/cookiecutter-django/pull/4296)) + +## 2023.04.25 + + +### Updated + +- Update sentry-sdk to 1.21.0 ([#4293](https://github.com/cookiecutter/cookiecutter-django/pull/4293)) + +- Update sphinx to 6.2.1 ([#4292](https://github.com/cookiecutter/cookiecutter-django/pull/4292)) + +- Bump traefik from 2.9.10 to 2.10.0 ([#4290](https://github.com/cookiecutter/cookiecutter-django/pull/4290)) + +- Auto-update pre-commit hooks ([#4288](https://github.com/cookiecutter/cookiecutter-django/pull/4288)) + +## 2023.04.24 + + +### Updated + +- Auto-update pre-commit hooks ([#4286](https://github.com/cookiecutter/cookiecutter-django/pull/4286)) + +- Update sphinx to 6.2.0 ([#4285](https://github.com/cookiecutter/cookiecutter-django/pull/4285)) + +## 2023.04.19 + + +### Updated + +- Update sentry-sdk to 1.20.0 ([#4282](https://github.com/cookiecutter/cookiecutter-django/pull/4282)) + +## 2023.04.18 + + +### Documentation + +- Document how to add 3rd party packages with Docker ([#4279](https://github.com/cookiecutter/cookiecutter-django/pull/4279)) + +## 2023.04.15 + + +### Changed + +- Add username_type option ([#3958](https://github.com/cookiecutter/cookiecutter-django/pull/3958)) + +- Fix inconsistent line length and move configs to pyproject.toml ([#4276](https://github.com/cookiecutter/cookiecutter-django/pull/4276)) + +- Relax rules for linting of pull requests on this template ([#4273](https://github.com/cookiecutter/cookiecutter-django/pull/4273)) + +- Add more pre-commit hooks ([#4266](https://github.com/cookiecutter/cookiecutter-django/pull/4266)) + +- Upgrade Python to version 3.11 (Faster CPython) ([#4256](https://github.com/cookiecutter/cookiecutter-django/pull/4256)) + +### Updated + +- Update drf-spectacular to 0.26.2 ([#4277](https://github.com/cookiecutter/cookiecutter-django/pull/4277)) + +- Update pytest to 7.3.1 ([#4272](https://github.com/cookiecutter/cookiecutter-django/pull/4272)) + +## 2023.04.13 + +### Updated +- Update tox to 4.4.12 ([#4271](https://github.com/cookiecutter/cookiecutter-django/pull/4271)) + +## 2023.04.10 + +### Updated +- Update pytest-sugar to 0.9.7 ([#4269](https://github.com/cookiecutter/cookiecutter-django/pull/4269)) +- Update pytest to 7.3.0 ([#4268](https://github.com/cookiecutter/cookiecutter-django/pull/4268)) + +## 2023.04.07 + +### Updated +- Upgrade traefik to 2.9.10 ([#4267](https://github.com/cookiecutter/cookiecutter-django/pull/4267)) + +## 2023.04.05 + +### Changed +- Update indent for nginx config file ([#4260](https://github.com/cookiecutter/cookiecutter-django/pull/4260)) +### Updated +- Update tox to 4.4.11 ([#4262](https://github.com/cookiecutter/cookiecutter-django/pull/4262)) +- Update django to 4.1.8 ([#4258](https://github.com/cookiecutter/cookiecutter-django/pull/4258)) +- Update pre-commit to 3.2.2 ([#4259](https://github.com/cookiecutter/cookiecutter-django/pull/4259)) + +## 2023.04.04 + +### Changed +- Upgrade to Django 4.1 ([#4028](https://github.com/cookiecutter/cookiecutter-django/pull/4028)) +- Remove deprecated security setting ([#4247](https://github.com/cookiecutter/cookiecutter-django/pull/4247)) +### Fixed +- Replace `runserver_plus` with `runserver` ([#4255](https://github.com/cookiecutter/cookiecutter-django/pull/4255)) +- Fix traefik rule priority for media router ([#4244](https://github.com/cookiecutter/cookiecutter-django/pull/4244)) +### Updated +- Update sentry-sdk to 1.19.0 ([#4254](https://github.com/cookiecutter/cookiecutter-django/pull/4254)) +- Update django-debug-toolbar to 4.0.0 ([#4251](https://github.com/cookiecutter/cookiecutter-django/pull/4251)) + +## 2023.04.03 + +### Changed +- fix: Syntax for ignoring specific noqa errors ([#4250](https://github.com/cookiecutter/cookiecutter-django/pull/4250)) +### Updated +- Update psycopg2-binary to 2.9.6 ([#4249](https://github.com/cookiecutter/cookiecutter-django/pull/4249)) +- Update psycopg2 to 2.9.6 ([#4248](https://github.com/cookiecutter/cookiecutter-django/pull/4248)) + +## 2023.04.01 + +### Updated +- Update pytest-instafail to 0.5.0 ([#4240](https://github.com/cookiecutter/cookiecutter-django/pull/4240)) +- Update pillow to 9.5.0 ([#4242](https://github.com/cookiecutter/cookiecutter-django/pull/4242)) +- Update django-allauth to 0.54.0 ([#4241](https://github.com/cookiecutter/cookiecutter-django/pull/4241)) + +## 2023.03.29 + +### Updated +- Update redis to 4.5.4 ([#4239](https://github.com/cookiecutter/cookiecutter-django/pull/4239)) +- Update pytz to 2023.3 ([#4238](https://github.com/cookiecutter/cookiecutter-django/pull/4238)) +- Update black to 23.3.0 ([#4236](https://github.com/cookiecutter/cookiecutter-django/pull/4236)) + +## 2023.03.27 + +### Updated +- Update watchfiles to 0.19.0 ([#4232](https://github.com/cookiecutter/cookiecutter-django/pull/4232)) + +## 2023.03.26 + +### Updated +- Update pre-commit to 3.2.1 ([#4229](https://github.com/cookiecutter/cookiecutter-django/pull/4229)) + +## 2023.03.25 + +### Updated +- Update pytz to 2023.2 ([#4228](https://github.com/cookiecutter/cookiecutter-django/pull/4228)) + +## 2023.03.23 + +### Updated +- Bump traefik from 2.9.8 to 2.9.9 ([#4225](https://github.com/cookiecutter/cookiecutter-django/pull/4225)) + +## 2023.03.22 + +### Updated +- Update redis to 4.5.3 ([#4227](https://github.com/cookiecutter/cookiecutter-django/pull/4227)) + +## 2023.03.20 + +### Updated +- Update django-allauth to 0.53.1 ([#4223](https://github.com/cookiecutter/cookiecutter-django/pull/4223)) +- Update redis to 4.5.2 ([#4222](https://github.com/cookiecutter/cookiecutter-django/pull/4222)) + +## 2023.03.18 + +### Updated +- Update drf-spectacular to 0.26.1 ([#4221](https://github.com/cookiecutter/cookiecutter-django/pull/4221)) +- Update pygithub to 1.58.1 ([#4220](https://github.com/cookiecutter/cookiecutter-django/pull/4220)) +- Update pre-commit to 3.2.0 ([#4219](https://github.com/cookiecutter/cookiecutter-django/pull/4219)) + +## 2023.03.16 + +### Changed +- Pin base Python Docker images to bugfix ([#4194](https://github.com/cookiecutter/cookiecutter-django/pull/4194)) +### Fixed +- Trim leading and trailing space in `domain_name` and `email` ([#4163](https://github.com/cookiecutter/cookiecutter-django/pull/4163)) +### Updated +- Update djangorestframework-stubs to 1.10.0 ([#4217](https://github.com/cookiecutter/cookiecutter-django/pull/4217)) +- Update django-stubs to 1.16.0 ([#4216](https://github.com/cookiecutter/cookiecutter-django/pull/4216)) +- Update coverage to 7.2.2 ([#4218](https://github.com/cookiecutter/cookiecutter-django/pull/4218)) +- Update sentry-sdk to 1.17.0 ([#4215](https://github.com/cookiecutter/cookiecutter-django/pull/4215)) +- Bump Docker python image from 3.10.9 to 3.10.10 on production Django ([#4214](https://github.com/cookiecutter/cookiecutter-django/pull/4214)) +- Bump Docker python image from 3.10.9-slim-bullseye to 3.10.10-slim-bullseye for docs ([#4213](https://github.com/cookiecutter/cookiecutter-django/pull/4213)) +- Bump Docker python image from 3.10.9-slim-bullseye to 3.10.10-slim-bullseye for local Django service ([#4212](https://github.com/cookiecutter/cookiecutter-django/pull/4212)) +- Update uvicorn to 0.21.1 ([#4211](https://github.com/cookiecutter/cookiecutter-django/pull/4211)) +- Update django-allauth to 0.53.0 ([#4210](https://github.com/cookiecutter/cookiecutter-django/pull/4210)) + +## 2023.03.14 + +### Updated +- Update django-celery-beat to 2.5.0 ([#4208](https://github.com/cookiecutter/cookiecutter-django/pull/4208)) + +## 2023.03.13 + +### Updated +- Update uvicorn to 0.21.0 ([#4203](https://github.com/cookiecutter/cookiecutter-django/pull/4203)) +- Update django-anymail to 9.1 ([#4206](https://github.com/cookiecutter/cookiecutter-django/pull/4206)) +- Update tox to 4.4.7 ([#4207](https://github.com/cookiecutter/cookiecutter-django/pull/4207)) + +## 2023.03.09 + +### Fixed +- Fix the omit configuration for coverage ([#4201](https://github.com/cookiecutter/cookiecutter-django/pull/4201)) +### Updated +- Update ipdb to 0.13.13 ([#4202](https://github.com/cookiecutter/cookiecutter-django/pull/4202)) + +## 2023.03.07 + +### Updated +- Update mypy to 1.1.1 ([#4196](https://github.com/cookiecutter/cookiecutter-django/pull/4196)) +- Update django-environ to 0.10.0 ([#4195](https://github.com/cookiecutter/cookiecutter-django/pull/4195)) + +## 2023.03.04 + +### Changed +- Add option to serve media files locally using nginx ([#2457](https://github.com/cookiecutter/cookiecutter-django/pull/2457)) +### Documentation +- Include contributing page to the docs ([#4144](https://github.com/cookiecutter/cookiecutter-django/pull/4144)) +### Updated +- Update myst-parser to 0.19.1 ([#4193](https://github.com/cookiecutter/cookiecutter-django/pull/4193)) +- Update pytest to 7.2.2 ([#4191](https://github.com/cookiecutter/cookiecutter-django/pull/4191)) +- Update drf-spectacular to 0.26.0 ([#4192](https://github.com/cookiecutter/cookiecutter-django/pull/4192)) + +## 2023.02.28 + +### Updated +- Update pre-commit to 3.1.1 ([#4188](https://github.com/cookiecutter/cookiecutter-django/pull/4188)) + +## 2023.02.27 + +### Updated +- Update sentry-sdk to 1.16.0 ([#4187](https://github.com/cookiecutter/cookiecutter-django/pull/4187)) + +## 2023.02.26 + +### Changed +- Fix readthedocs config file for generated project ([#4172](https://github.com/cookiecutter/cookiecutter-django/pull/4172)) +### Updated +- Bump traefik from v2.2.11 to 2.9.8 ([#4164](https://github.com/cookiecutter/cookiecutter-django/pull/4164)) +- Update coverage to 7.2.1 ([#4186](https://github.com/cookiecutter/cookiecutter-django/pull/4186)) + +## 2023.02.25 + +### Changed +- Run linting with pre-commit on GitLab ([#4150](https://github.com/cookiecutter/cookiecutter-django/pull/4150)) +### Fixed +- Disable caching for linter job on GitHub actions ([#4166](https://github.com/cookiecutter/cookiecutter-django/pull/4166)) +### Documentation +- Add instuction to run celery beat ([#4162](https://github.com/cookiecutter/cookiecutter-django/pull/4162)) +### Updated +- Bump garland/aws-cli-docker from 1.15.47 to 1.16.140 ([#4136](https://github.com/cookiecutter/cookiecutter-django/pull/4136)) +- Update djangorestframework-stubs to 1.9.1 ([#4184](https://github.com/cookiecutter/cookiecutter-django/pull/4184)) +- Update whitenoise to 6.4.0 ([#4180](https://github.com/cookiecutter/cookiecutter-django/pull/4180)) +- Update django-stubs to 1.15.0 ([#4183](https://github.com/cookiecutter/cookiecutter-django/pull/4183)) +- Update django-crispy-forms to 2.0 ([#4158](https://github.com/cookiecutter/cookiecutter-django/pull/4158)) +- Update django-cors-headers to 3.14.0 ([#4181](https://github.com/cookiecutter/cookiecutter-django/pull/4181)) +- Update python-slugify to 8.0.1 ([#4178](https://github.com/cookiecutter/cookiecutter-django/pull/4178)) +- Update pre-commit to 3.1.0 ([#4176](https://github.com/cookiecutter/cookiecutter-django/pull/4176)) +- Update mypy to 1.0.1 ([#4168](https://github.com/cookiecutter/cookiecutter-django/pull/4168)) +- Update werkzeug to 2.2.3 ([#4160](https://github.com/cookiecutter/cookiecutter-django/pull/4160)) +- Update coverage to 7.2.0 ([#4177](https://github.com/cookiecutter/cookiecutter-django/pull/4177)) +- Update django to 4.0.10 ([#4159](https://github.com/cookiecutter/cookiecutter-django/pull/4159)) +- Update hiredis to 2.2.2 ([#4156](https://github.com/cookiecutter/cookiecutter-django/pull/4156)) + +## 2023.02.17 + +### Changed +- Update version of github actions on the template project ([#4167](https://github.com/cookiecutter/cookiecutter-django/pull/4167)) + +## 2023.02.09 + +### Changed +- Remove unused pip cache paths in GHA & add a note for pre-commit.ci ([#4151](https://github.com/cookiecutter/cookiecutter-django/pull/4151)) +### Updated +- Update mypy to 0.991 ([#4106](https://github.com/cookiecutter/cookiecutter-django/pull/4106)) + +## 2023.02.08 + +### Updated +- Update sphinx to 6.1.3 ([#4148](https://github.com/cookiecutter/cookiecutter-django/pull/4148)) +- Update redis to 4.5.1 ([#4147](https://github.com/cookiecutter/cookiecutter-django/pull/4147)) + +## 2023.02.07 + +### Updated +- Bump postcss-preset-env from 7.8.3 to 8.0.1 ([#4115](https://github.com/cookiecutter/cookiecutter-django/pull/4115)) +- Bump sass-loader from 12.6.0 to 13.2.0 ([#4116](https://github.com/cookiecutter/cookiecutter-django/pull/4116)) +- Bump babel-loader from 8.3.0 to 9.1.2 ([#4117](https://github.com/cookiecutter/cookiecutter-django/pull/4117)) +- Bump postcss-loader from 6.2.1 to 7.0.2 ([#4114](https://github.com/cookiecutter/cookiecutter-django/pull/4114)) +- Bump webpack-cli from 4.10.0 to 5.0.1 ([#4118](https://github.com/cookiecutter/cookiecutter-django/pull/4118)) +- Update redis to 4.5.0 ([#4142](https://github.com/cookiecutter/cookiecutter-django/pull/4142)) +- Update sentry-sdk to 1.15.0 ([#4141](https://github.com/cookiecutter/cookiecutter-django/pull/4141)) + +## 2023.02.06 + +### Changed +- Change `RequestFactory` to `APIRequestFactory` in tests for API views ([#4110](https://github.com/cookiecutter/cookiecutter-django/pull/4110)) +### Fixed +- Fix django-webpack-loader setup when running tests ([#4128](https://github.com/cookiecutter/cookiecutter-django/pull/4128)) +### Documentation +- Added AWS ECS Full Deployment Article to README ([#2630](https://github.com/cookiecutter/cookiecutter-django/pull/2630)) +### Updated +- Update hiredis to 2.2.1 ([#4123](https://github.com/cookiecutter/cookiecutter-django/pull/4123)) +- Update tox to 4.4.4 ([#4133](https://github.com/cookiecutter/cookiecutter-django/pull/4133)) +- Update django to 4.0.9 ([#4134](https://github.com/cookiecutter/cookiecutter-django/pull/4134)) +- Update django-webpack-loader to 1.8.1 ([#4132](https://github.com/cookiecutter/cookiecutter-django/pull/4132)) + +## 2023.02.05 + +### Documentation +- Add note about which service to request when running locally with Docker & Webpack or Gulp ([#4130](https://github.com/cookiecutter/cookiecutter-django/pull/4130)) + +## 2023.02.03 + +### Updated +- Update pre-commit to 3.0.4 ([#4127](https://github.com/cookiecutter/cookiecutter-django/pull/4127)) + +## 2023.02.02 + +### Updated +- Update python-slugify to 8.0.0 ([#4111](https://github.com/cookiecutter/cookiecutter-django/pull/4111)) +- Update pre-commit to 3.0.3 ([#4121](https://github.com/cookiecutter/cookiecutter-django/pull/4121)) +- Update black to 23.1.0 ([#4120](https://github.com/cookiecutter/cookiecutter-django/pull/4120)) +- Update black pre-commit hook ([#4122](https://github.com/cookiecutter/cookiecutter-django/pull/4122)) + +## 2023.01.29 + +### Changed +- Add Webpack support ([#3623](https://github.com/cookiecutter/cookiecutter-django/pull/3623)) +- Remove `BrokenLinkEmailsMiddleware` ([#4112](https://github.com/cookiecutter/cookiecutter-django/pull/4112)) + +## 2023.01.28 + +### Changed +- Refactor `merge_production_dotenvs_in_dotenv.py` ([#4105](https://github.com/cookiecutter/cookiecutter-django/pull/4105)) +### Updated +- Update isort to 5.12.0 ([#4109](https://github.com/cookiecutter/cookiecutter-django/pull/4109)) +- Auto-update pre-commit hooks ([#4108](https://github.com/cookiecutter/cookiecutter-django/pull/4108)) + +## 2023.01.27 + +### Updated +- Update django-stubs to 1.14.0 ([#4103](https://github.com/cookiecutter/cookiecutter-django/pull/4103)) + +## 2023.01.26 + +### Changed +- Rename BASE_DIR_PATH to BASE_DIR ([#4102](https://github.com/cookiecutter/cookiecutter-django/pull/4102)) +### Updated +- Update pre-commit to 3.0.1 ([#4104](https://github.com/cookiecutter/cookiecutter-django/pull/4104)) +- Update tox to 4.4.2 ([#4101](https://github.com/cookiecutter/cookiecutter-django/pull/4101)) + +## 2023.01.25 + +### Changed +- Rename ROOT_DIR to BASE_DIR ([#4086](https://github.com/cookiecutter/cookiecutter-django/pull/4086)) +- Update postgres and redis to point to mini tiers ([#4099](https://github.com/cookiecutter/cookiecutter-django/pull/4099)) +### Updated +- Update coverage to 7.1.0 ([#4100](https://github.com/cookiecutter/cookiecutter-django/pull/4100)) + +## 2023.01.24 + +### Updated +- Update pre-commit to 3.0.0 ([#4098](https://github.com/cookiecutter/cookiecutter-django/pull/4098)) + +## 2023.01.23 + +### Updated +- Update sentry-sdk to 1.14.0 ([#4096](https://github.com/cookiecutter/cookiecutter-django/pull/4096)) + +## 2023.01.22 + +### Updated +- Update django-compressor to 4.3.1 ([#4094](https://github.com/cookiecutter/cookiecutter-django/pull/4094)) + +## 2023.01.21 + +### Updated +- Update django-stubs to 1.13.2 ([#4093](https://github.com/cookiecutter/cookiecutter-django/pull/4093)) + +## 2023.01.19 + +### Fixed +- Add sourcemaps support to Gulp ([#4089](https://github.com/cookiecutter/cookiecutter-django/pull/4089)) +### Updated +- Update coverage to 7.0.5 ([#4092](https://github.com/cookiecutter/cookiecutter-django/pull/4092)) +- Update redis to 4.4.2 ([#4091](https://github.com/cookiecutter/cookiecutter-django/pull/4091)) +- Update requests to 2.28.2 ([#4090](https://github.com/cookiecutter/cookiecutter-django/pull/4090)) +- Update tox to 4.3.5 ([#4087](https://github.com/cookiecutter/cookiecutter-django/pull/4087)) + +## 2023.01.17 + +### Updated +- Update tox to 4.3.3 ([#4081](https://github.com/cookiecutter/cookiecutter-django/pull/4081)) + ## 2023.01.15 ### Updated diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 8a5fc4158..a7b21223b 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,3 +1,3 @@ ## Code of Conduct -Everyone who interacts in the Cookiecutter project's codebase, issue trackers, chat rooms, and mailing lists is expected to follow the [PyPA Code of Conduct](https://www.pypa.io/en/latest/code-of-conduct/). +Everyone who interacts in the Cookiecutter project's codebase, issue trackers, chat rooms, and mailing lists is expected to follow the [PSF Code of Conduct](https://www.python.org/psf/conduct/) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 69bce6f2e..94ecbdd7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,41 +2,81 @@ Always happy to get issues identified and pull requests! -## Getting your pull request merged in +## General considerations -1. Keep it small. The smaller the pull request, the more likely we are to accept. -2. Pull requests that fix a current issue get priority for review. +1. Keep it small. The smaller the change, the more likely we are to accept. +2. Changes that fix a current issue get priority for review. +3. Check out [GitHub guide][submit-a-pr] if you've never created a pull request before. + +## Getting started + +1. Fork the repo +2. Clone your fork +3. Create a branch for your changes + +This last step is very important, don't start developing from master, it'll cause pain if you need to send another change later. ## Testing +You'll need to run the tests using Python 3.11. We recommend using [tox](https://tox.readthedocs.io/en/latest/) to run the tests. It will automatically create a fresh virtual environment and install our test dependencies, such as [pytest-cookies](https://pypi.python.org/pypi/pytest-cookies/) and [flake8](https://pypi.python.org/pypi/flake8/). + +We'll also run the tests on GitHub actions when you send your pull request, but it's a good idea to run them locally before you send it. + ### Installation -Please install [tox](https://tox.readthedocs.io/en/latest/), which is a generic virtualenv management and test command line tool. +First, make sure that your version of Python is 3.11: -[tox](https://tox.readthedocs.io/en/latest/) is available for download from [PyPI](https://pypi.python.org/pypi) via [pip](https://pypi.python.org/pypi/pip/): +```bash +$ python --version +Python 3.11.3 +``` - $ pip install tox +Any version that starts with 3.11 will do. If you need to install it, you can get it from [python.org](https://www.python.org/downloads/). -It will automatically create a fresh virtual environment and install our test dependencies, -such as [pytest-cookies](https://pypi.python.org/pypi/pytest-cookies/) and [flake8](https://pypi.python.org/pypi/flake8/). +Then install `tox`, if not already installed: -### Run the Tests +```bash +$ python -m pip install tox +``` -Tox uses pytest under the hood, hence it supports the same syntax for selecting tests. +### Run the template's test suite -For further information please consult the [pytest usage docs](https://pytest.org/latest/usage.html#specifying-tests-selecting-tests). +To run the tests of the template using the current Python version: -To run all tests using various versions of python in virtualenvs defined in tox.ini, just run tox.: +```bash +$ tox -e py +``` - $ tox +This uses `pytest `under the hood, and you can pass options to it after a `--`. So to run a particular test: -It is possible to test with a specific version of python. To do this, the command -is: +```bash +$ tox -e py -- -k test_default_configuration +``` - $ tox -e py310 +For further information, please consult the [pytest usage docs](https://pytest.org/en/latest/how-to/usage.html#specifying-which-tests-to-run). -This will run pytest with the python3.10 interpreter, for example. +### Run the generated project tests -To run a particular test with tox for against your current Python version: +The template tests are checking that the generated project is fully rendered and that it passes `flake8`. We also have some test scripts which generate a specific project combination, install the dependencies, run the tests of the generated project, install FE dependencies and generate the docs. They will install the template dependencies, so make sure you create and activate a virtual environment first. - $ tox -e py -- -k test_default_configuration +```bash +$ python -m venv venv +$ source venv/bin/activate +``` + +These tests are slower and can be run with or without Docker: + +- Without Docker: `scripts/test_bare.sh` (for bare metal) +- With Docker: `scripts/test_docker.sh` + +All arguments to these scripts will be passed to the `cookiecutter` CLI, letting you set options, for example: + +```bash +$ scripts/test_bare.sh use_celery=y +``` + +## Submitting a pull request + +Once you're happy with your changes and they look ok locally, push and send send [a pull request][submit-a-pr] to the main repo, which will trigger the tests on GitHub actions. If they fail, try to fix them. A maintainer should take a look at your change and give you feedback or merge it. + +[submit-a-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 718d58c57..340588a9a 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -76,8 +76,8 @@ accept and merge pull requests. -*Audrey is also the creator of Cookiecutter. Audrey and Daniel are on -the Cookiecutter core team.* +_Audrey is also the creator of Cookiecutter. Audrey and Daniel are on +the Cookiecutter core team._ ## Other Contributors @@ -292,6 +292,13 @@ Listed in alphabetical order. + + Arkadiusz Michał Ryś + + arrys + + + Arnav Choudhury @@ -362,6 +369,13 @@ Listed in alphabetical order. + + Birtibu + + Birtibu + + + Bo Lopker @@ -642,6 +656,13 @@ Listed in alphabetical order. jangeador + + Delphine LEMIRE + + DelphineLemire + + + Demetris Stavrou @@ -705,6 +726,13 @@ Listed in alphabetical order. dudanogueira + + duffn + + duffn + + + Dónal Adams @@ -901,6 +929,13 @@ Listed in alphabetical order. + + Hoai-Thu Vuong + + thuvh + + + Howie Zhao @@ -1398,6 +1433,13 @@ Listed in alphabetical order. + + Morten Kaae + + MortenKaae + + + mozillazg @@ -1412,6 +1454,13 @@ Listed in alphabetical order. + + mpsantos + + mpsantos + + + Naveen @@ -1475,6 +1524,13 @@ Listed in alphabetical order. + + Patrick Tran + + theptrk + + + Pawan Chaurasia @@ -1734,6 +1790,13 @@ Listed in alphabetical order. + + tildebox + + tildebox + + + Tim Claessens @@ -1909,6 +1972,6 @@ Listed in alphabetical order. The following haven't provided code directly, but have provided guidance and advice. -- Jannis Leidel -- Nate Aune -- Barry Morrison \ No newline at end of file +- Jannis Leidel +- Nate Aune +- Barry Morrison \ No newline at end of file diff --git a/README.md b/README.md index d8fc58ec4..161b5ed0a 100644 --- a/README.md +++ b/README.md @@ -2,66 +2,69 @@ [![Build Status](https://img.shields.io/github/actions/workflow/status/cookiecutter/cookiecutter-django/ci.yml?branch=master)](https://github.com/cookiecutter/cookiecutter-django/actions/workflows/ci.yml?query=branch%3Amaster) [![Documentation Status](https://readthedocs.org/projects/cookiecutter-django/badge/?version=latest)](https://cookiecutter-django.readthedocs.io/en/latest/?badge=latest) +[![pre-commit.ci status](https://results.pre-commit.ci/badge/github/cookiecutter/cookiecutter-django/master.svg)](https://results.pre-commit.ci/latest/github/cookiecutter/cookiecutter-django/master) +[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) + [![Updates](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/shield.svg)](https://pyup.io/repos/github/cookiecutter/cookiecutter-django/) [![Join our Discord](https://img.shields.io/badge/Discord-cookiecutter-5865F2?style=flat&logo=discord&logoColor=white)](https://discord.gg/uFXweDQc5a) [![Code Helpers Badge](https://www.codetriage.com/cookiecutter/cookiecutter-django/badges/users.svg)](https://www.codetriage.com/cookiecutter/cookiecutter-django) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/ambv/black) Powered by [Cookiecutter](https://github.com/cookiecutter/cookiecutter), Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. -- Documentation: -- See [Troubleshooting](https://cookiecutter-django.readthedocs.io/en/latest/troubleshooting.html) for common errors and obstacles -- If you have problems with Cookiecutter Django, please open [issues](https://github.com/cookiecutter/cookiecutter-django/issues/new) don't send - emails to the maintainers. +- Documentation: +- See [Troubleshooting](https://cookiecutter-django.readthedocs.io/en/latest/troubleshooting.html) for common errors and obstacles +- If you have problems with Cookiecutter Django, please open [issues](https://github.com/cookiecutter/cookiecutter-django/issues/new) don't send + emails to the maintainers. ## Features -- For Django 4.0 -- Works with Python 3.10 -- Renders Django projects with 100% starting test coverage -- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5 -- [12-Factor](http://12factor.net/) based settings via [django-environ](https://github.com/joke2k/django-environ) -- Secure by default. We believe in SSL. -- Optimized development and production settings -- Registration via [django-allauth](https://github.com/pennersr/django-allauth) -- Comes with custom user model ready to go -- Optional basic ASGI setup for Websockets -- Optional custom static build using Gulp and livereload -- Send emails via [Anymail](https://github.com/anymail/django-anymail) (using [Mailgun](http://www.mailgun.com/) by default or Amazon SES if AWS is selected cloud provider, but switchable) -- Media storage using Amazon S3, Google Cloud Storage or Azure Storage -- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Traefik](https://traefik.io/) with [LetsEncrypt](https://letsencrypt.org/) support) -- [Procfile](https://devcenter.heroku.com/articles/procfile) for deploying to Heroku -- Instructions for deploying to [PythonAnywhere](https://www.pythonanywhere.com/) -- Run tests with unittest or pytest -- Customizable PostgreSQL version -- Default integration with [pre-commit](https://github.com/pre-commit/pre-commit) for identifying simple issues before submission to code review +- For Django 4.1 +- Works with Python 3.11 +- Renders Django projects with 100% starting test coverage +- Twitter [Bootstrap](https://github.com/twbs/bootstrap) v5 +- [12-Factor](http://12factor.net/) based settings via [django-environ](https://github.com/joke2k/django-environ) +- Secure by default. We believe in SSL. +- Optimized development and production settings +- Registration via [django-allauth](https://github.com/pennersr/django-allauth) +- Comes with custom user model ready to go +- Optional basic ASGI setup for Websockets +- Optional custom static build using Gulp or Webpack +- Send emails via [Anymail](https://github.com/anymail/django-anymail) (using [Mailgun](http://www.mailgun.com/) by default or Amazon SES if AWS is selected cloud provider, but switchable) +- Media storage using Amazon S3, Google Cloud Storage, Azure Storage or nginx +- Docker support using [docker-compose](https://github.com/docker/compose) for development and production (using [Traefik](https://traefik.io/) with [LetsEncrypt](https://letsencrypt.org/) support) +- [Procfile](https://devcenter.heroku.com/articles/procfile) for deploying to Heroku +- Instructions for deploying to [PythonAnywhere](https://www.pythonanywhere.com/) +- Run tests with unittest or pytest +- Customizable PostgreSQL version +- Default integration with [pre-commit](https://github.com/pre-commit/pre-commit) for identifying simple issues before submission to code review ## Optional Integrations -*These features can be enabled during initial project setup.* +_These features can be enabled during initial project setup._ -- Serve static files from Amazon S3, Google Cloud Storage, Azure Storage or [Whitenoise](https://whitenoise.readthedocs.io/) -- Configuration for [Celery](https://docs.celeryq.dev) and [Flower](https://github.com/mher/flower) (the latter in Docker setup only) -- Integration with [MailHog](https://github.com/mailhog/MailHog) for local email testing -- Integration with [Sentry](https://sentry.io/welcome/) for error logging +- Serve static files from Amazon S3, Google Cloud Storage, Azure Storage or [Whitenoise](https://whitenoise.readthedocs.io/) +- Configuration for [Celery](https://docs.celeryq.dev) and [Flower](https://github.com/mher/flower) (the latter in Docker setup only) +- Integration with [MailHog](https://github.com/mailhog/MailHog) for local email testing +- Integration with [Sentry](https://sentry.io/welcome/) for error logging ## Constraints -- Only maintained 3rd party libraries are used. -- Uses PostgreSQL everywhere: 10.19 - 14.1 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available). -- Environment variables for configuration (This won't work with Apache/mod_wsgi). +- Only maintained 3rd party libraries are used. +- Uses PostgreSQL everywhere: 10.19 - 14.1 ([MySQL fork](https://github.com/mabdullahadeel/cookiecutter-django-mysql) also available). +- Environment variables for configuration (This won't work with Apache/mod_wsgi). ## Support this Project! This project is run by volunteers. Please support them in their efforts to maintain and improve Cookiecutter Django: -- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB. -- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience. +- Daniel Roy Greenfeld, Project Lead ([GitHub](https://github.com/pydanny), [Patreon](https://www.patreon.com/danielroygreenfeld)): expertise in Django and AWS ELB. +- Fabio C. Barrionuevo, Core Developer ([GitHub](https://github.com/luzfcb)): expertise in Python/Django, hands-on DevOps and frontend experience. +- Nikita Shupeyko, Core Developer ([GitHub](https://github.com/webyneter)): expertise in Python/Django, hands-on DevOps and frontend experience. Projects that provide financial support to the maintainers: ------------------------------------------------------------------------- +---

@@ -116,6 +119,10 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re 4 - Apache Software License 2.0 5 - Not open source Choose from 1, 2, 3, 4, 5 [1]: 1 + Select username_type: # NOT USED FOR THIS TEMPLATE + 1 - username + 2 - email + Choose from 1, 2 [1]: 1 timezone [UTC]: America/Los_Angeles windows [n]: n use_pycharm [n]: y @@ -149,6 +156,7 @@ Answer the prompts with your own desired [options](http://cookiecutter-django.re 1 - None 2 - Django Compressor 3 - Gulp + 4 - Webpack Choose from 1, 2, 3, 4 [1]: 1 use_celery [n]: y use_mailhog [n]: n @@ -181,14 +189,14 @@ Now take a look at your repo. Don't forget to carefully look at the generated RE For local development, see the following: -- [Developing locally](http://cookiecutter-django.readthedocs.io/en/latest/developing-locally.html) -- [Developing locally using docker](http://cookiecutter-django.readthedocs.io/en/latest/developing-locally-docker.html) +- [Developing locally](http://cookiecutter-django.readthedocs.io/en/latest/developing-locally.html) +- [Developing locally using docker](http://cookiecutter-django.readthedocs.io/en/latest/developing-locally-docker.html) ## Community -- Have questions? **Before you ask questions anywhere else**, please post your question on [Stack Overflow](http://stackoverflow.com/questions/tagged/cookiecutter-django) under the *cookiecutter-django* tag. We check there periodically for questions. -- If you think you found a bug or want to request a feature, please open an [issue](https://github.com/cookiecutter/cookiecutter-django/issues). -- For anything else, you can chat with us on [Discord](https://discord.gg/uFXweDQc5a). +- Have questions? **Before you ask questions anywhere else**, please post your question on [Stack Overflow](http://stackoverflow.com/questions/tagged/cookiecutter-django) under the _cookiecutter-django_ tag. We check there periodically for questions. +- If you think you found a bug or want to request a feature, please open an [issue](https://github.com/cookiecutter/cookiecutter-django/issues). +- For anything else, you can chat with us on [Discord](https://discord.gg/uFXweDQc5a). ## For Readers of Two Scoops of Django @@ -196,13 +204,14 @@ You may notice that some elements of this project do not exactly match what we d ## For PyUp Users -If you are using [PyUp](https://pyup.io) to keep your dependencies updated and secure, use the code *cookiecutter* during checkout to get 15% off every month. +If you are using [PyUp](https://pyup.io) to keep your dependencies updated and secure, use the code _cookiecutter_ during checkout to get 15% off every month. ## "Your Stuff" Scattered throughout the Python and HTML of this project are places marked with "your stuff". This is where third-party libraries are to be integrated with your project. ## For MySQL users + To get full MySQL support in addition to the default Postgresql, you can use this fork of the cookiecutter-django: https://github.com/mabdullahadeel/cookiecutter-django-mysql @@ -212,18 +221,18 @@ Need a stable release? You can find them at ``, that would only add the package to the container. The container is ephemeral, so that new library won't be persisted if you run another container. Instead, you should modify the Docker image: +You have to modify the relevant requirement file: base, local or production by adding: :: + + == + +To get this change picked up, you'll need to rebuild the image(s) and restart the running container: :: + + docker-compose -f local.yml build + docker-compose -f local.yml up + Debugging ~~~~~~~~~ @@ -213,6 +226,11 @@ By default, it's enabled both in local and production environments (``local.yml` .. _`Flower`: https://github.com/mher/flower +Using Webpack or Gulp +~~~~~~~~~~~~~~~~~~~~~ + +When using Webpack or Gulp as the ``frontend_pipeline`` option, you should access your application at the address of the ``node`` service in order to see your correct styles. This is http://localhost:3000 by default. When using any of the other ``frontend_pipeline`` options, you should use the address of the ``django`` service, http://localhost:8000. + Developing locally with HTTPS ----------------------------- diff --git a/docs/developing-locally.rst b/docs/developing-locally.rst index 2b9438059..b79033aaa 100644 --- a/docs/developing-locally.rst +++ b/docs/developing-locally.rst @@ -9,7 +9,7 @@ Setting Up Development Environment Make sure to have the following on your host: -* Python 3.10 +* Python 3.11 * PostgreSQL_. * Redis_, if using Celery * Cookiecutter_ @@ -18,7 +18,7 @@ First things first. #. Create a virtualenv: :: - $ python3.10 -m venv + $ python3.11 -m venv #. Activate the virtualenv you have just created: :: @@ -172,9 +172,9 @@ You can also use Django admin to queue up tasks, thanks to the `django-celerybea Sass Compilation & Live Reloading --------------------------------- -If you've opted for Gulp as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change you Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page. +If you've opted for Gulp or Webpack as front-end pipeline, the project comes configured with `Sass`_ compilation and `live reloading`_. As you change you Sass/JS source files, the task runner will automatically rebuild the corresponding CSS and JS assets and reload them in your browser without refreshing the page. -#. Make sure that `Node.js`_ v16 is installed on your machine. +#. Make sure that `Node.js`_ v18 is installed on your machine. #. In the project root, install the JS dependencies with:: $ npm install diff --git a/docs/generate-project-block.rst b/docs/generate-project-block.rst index 2842b551d..fca3fe1a8 100644 --- a/docs/generate-project-block.rst +++ b/docs/generate-project-block.rst @@ -4,4 +4,3 @@ Generate a new cookiecutter-django project: :: For more information refer to :ref:`Project Generation Options `. - diff --git a/docs/index.rst b/docs/index.rst index dae641d10..da5186487 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -27,6 +27,7 @@ Contents websocket faq troubleshooting + contributing Indices and tables ------------------ diff --git a/docs/project-generation-options.rst b/docs/project-generation-options.rst index 0560badd3..a1d788173 100644 --- a/docs/project-generation-options.rst +++ b/docs/project-generation-options.rst @@ -24,6 +24,13 @@ author_name: email: The email address you want to identify yourself in the project. +username_type: + The type of username you want to use in the project. This can be either + ``username`` or ``email``. If you choose ``username``, the ``email`` field + will be included. If you choose ``email``, the ``username`` field will be + excluded. It is best practice to always include an email field, so there is + no option for having just the ``username`` field. + domain_name: The domain name you plan to use for your project once it goes live. Note that it can be safely changed later on whenever you need to. @@ -69,7 +76,7 @@ cloud_provider: 3. Azure_ 4. None - Note that if you choose no cloud provider, media files won't work. + If you choose no cloud provider and docker, the production stack will serve the media files via an nginx Docker service. Without Docker, the media files won't work. mail_service: Select an email service that Django-Anymail provides @@ -95,7 +102,10 @@ frontend_pipeline: 1. None 2. `Django Compressor`_ - 3. `Gulp`_: support Bootstrap recompilation with real-time variables alteration. + 3. `Gulp`_ + 4. `Webpack`_ + +Both Gulp and Webpack support Bootstrap recompilation with real-time variables alteration. use_celery: Indicates whether the project should be configured to use Celery_. @@ -145,6 +155,7 @@ debug: .. _PostgreSQL: https://www.postgresql.org/docs/ .. _Gulp: https://github.com/gulpjs/gulp +.. _Webpack: https://webpack.js.org .. _AWS: https://aws.amazon.com/s3/ .. _GCP: https://cloud.google.com/storage/ diff --git a/docs/requirements.txt b/docs/requirements.txt index 2cc8302a2..d3dd61dc6 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,3 @@ -sphinx==5.3.0 -sphinx-rtd-theme==1.1.1 +sphinx==6.2.1 +sphinx-rtd-theme==1.2.0 +myst-parser==1.0.0 diff --git a/docs/settings.rst b/docs/settings.rst index 4691adbbd..6dacb7404 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -22,7 +22,6 @@ DATABASE_URL DATABASES auto w/ Dock DJANGO_ADMIN_URL n/a 'admin/' raises error DJANGO_DEBUG DEBUG True False DJANGO_SECRET_KEY SECRET_KEY auto-generated raises error -DJANGO_SECURE_BROWSER_XSS_FILTER SECURE_BROWSER_XSS_FILTER n/a True DJANGO_SECURE_SSL_REDIRECT SECURE_SSL_REDIRECT n/a True DJANGO_SECURE_CONTENT_TYPE_NOSNIFF SECURE_CONTENT_TYPE_NOSNIFF n/a True DJANGO_SECURE_FRAME_DENY SECURE_FRAME_DENY n/a True diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst index ba8ab53e6..293e9b652 100644 --- a/docs/troubleshooting.rst +++ b/docs/troubleshooting.rst @@ -1,5 +1,5 @@ Troubleshooting -===================================== +=============== This page contains some advice about errors and problems commonly encountered during the development of Cookiecutter Django applications. @@ -38,6 +38,16 @@ To fix this, you can either: .. _rm: https://docs.docker.com/engine/reference/commandline/volume_rm/ .. _prune: https://docs.docker.com/v17.09/engine/reference/commandline/system_prune/ +Variable is not set. Defaulting to a blank string +------------------------------------------------- + +Example:: + + WARN[0000] The "DJANGO_AWS_STORAGE_BUCKET_NAME" variable is not set. Defaulting to a blank string. + WARN[0000] The "DJANGO_AWS_S3_CUSTOM_DOMAIN" variable is not set. Defaulting to a blank string. + +You have probably opted for Docker + Webpack without Whitenoise. This is a know limitation of the combination, which needs a little bit of manual intervention. See the :ref:`dedicated section about it `. + Others ------ diff --git a/hooks/post_gen_project.py b/hooks/post_gen_project.py index 9c3d946c1..39af59d33 100644 --- a/hooks/post_gen_project.py +++ b/hooks/post_gen_project.py @@ -10,6 +10,7 @@ TODO: restrict Cookiecutter Django project initialization to """ from __future__ import print_function +import json import os import random import shutil @@ -44,6 +45,24 @@ def remove_gplv3_files(): os.remove(file_name) +def remove_custom_user_manager_files(): + os.remove( + os.path.join( + "{{cookiecutter.project_slug}}", + "users", + "managers.py", + ) + ) + os.remove( + os.path.join( + "{{cookiecutter.project_slug}}", + "users", + "tests", + "test_managers.py", + ) + ) + + def remove_pycharm_files(): idea_dir_path = ".idea" if os.path.exists(idea_dir_path): @@ -73,10 +92,7 @@ def remove_utility_files(): def remove_heroku_files(): file_names = ["Procfile", "runtime.txt", "requirements.txt"] for file_name in file_names: - if ( - file_name == "requirements.txt" - and "{{ cookiecutter.ci_tool }}".lower() == "travis" - ): + if file_name == "requirements.txt" and "{{ cookiecutter.ci_tool }}".lower() == "travis": # don't remove the file if we are using travisci but not using heroku continue os.remove(file_name) @@ -87,15 +103,30 @@ def remove_heroku_build_hooks(): shutil.rmtree("bin") +def remove_sass_files(): + shutil.rmtree(os.path.join("{{cookiecutter.project_slug}}", "static", "sass")) + + def remove_gulp_files(): file_names = ["gulpfile.js"] for file_name in file_names: os.remove(file_name) - remove_sass_files() -def remove_sass_files(): - shutil.rmtree(os.path.join("{{cookiecutter.project_slug}}", "static", "sass")) +def remove_webpack_files(): + shutil.rmtree("webpack") + remove_vendors_js() + + +def remove_vendors_js(): + vendors_js_path = os.path.join( + "{{ cookiecutter.project_slug }}", + "static", + "js", + "vendors.js", + ) + if os.path.exists(vendors_js_path): + os.remove(vendors_js_path) def remove_packagejson_file(): @@ -104,13 +135,84 @@ def remove_packagejson_file(): os.remove(file_name) +def update_package_json(remove_dev_deps=None, remove_keys=None, scripts=None): + remove_dev_deps = remove_dev_deps or [] + remove_keys = remove_keys or [] + scripts = scripts or {} + with open("package.json", mode="r") as fd: + content = json.load(fd) + for package_name in remove_dev_deps: + content["devDependencies"].pop(package_name) + for key in remove_keys: + content.pop(key) + content["scripts"].update(scripts) + with open("package.json", mode="w") as fd: + json.dump(content, fd, ensure_ascii=False, indent=2) + fd.write("\n") + + +def handle_js_runner(choice, use_docker, use_async): + if choice == "Gulp": + update_package_json( + remove_dev_deps=[ + "@babel/core", + "@babel/preset-env", + "babel-loader", + "concurrently", + "css-loader", + "mini-css-extract-plugin", + "postcss-loader", + "postcss-preset-env", + "sass-loader", + "webpack", + "webpack-bundle-tracker", + "webpack-cli", + "webpack-dev-server", + "webpack-merge", + ], + remove_keys=["babel"], + scripts={ + "dev": "gulp", + "build": "gulp generate-assets", + }, + ) + remove_webpack_files() + elif choice == "Webpack": + scripts = { + "dev": "webpack serve --config webpack/dev.config.js", + "build": "webpack --config webpack/prod.config.js", + } + remove_dev_deps = [ + "browser-sync", + "cssnano", + "gulp", + "gulp-imagemin", + "gulp-plumber", + "gulp-postcss", + "gulp-rename", + "gulp-sass", + "gulp-uglify-es", + ] + if not use_docker: + dev_django_cmd = "uvicorn config.asgi:application --reload" if use_async else "python manage.py runserver" + scripts.update( + { + "dev": "concurrently npm:dev:*", + "dev:webpack": "webpack serve --config webpack/dev.config.js", + "dev:django": dev_django_cmd, + } + ) + else: + remove_dev_deps.append("concurrently") + update_package_json(remove_dev_deps=remove_dev_deps, scripts=scripts) + remove_gulp_files() + + def remove_celery_files(): file_names = [ os.path.join("config", "celery_app.py"), os.path.join("{{ cookiecutter.project_slug }}", "users", "tasks.py"), - os.path.join( - "{{ cookiecutter.project_slug }}", "users", "tests", "test_tasks.py" - ), + os.path.join("{{ cookiecutter.project_slug }}", "users", "tests", "test_tasks.py"), ] for file_name in file_names: os.remove(file_name) @@ -137,9 +239,7 @@ def remove_dotgithub_folder(): shutil.rmtree(".github") -def generate_random_string( - length, using_digits=False, using_ascii_letters=False, using_punctuation=False -): +def generate_random_string(length, using_digits=False, using_ascii_letters=False, using_punctuation=False): """ Example: opting out for 50 symbol-long, [a-z][A-Z][0-9] string @@ -233,9 +333,7 @@ def set_postgres_password(file_path, value=None): def set_celery_flower_user(file_path, value): - celery_flower_user = set_flag( - file_path, "!!!SET CELERY_FLOWER_USER!!!", value=value - ) + celery_flower_user = set_flag(file_path, "!!!SET CELERY_FLOWER_USER!!!", value=value) return celery_flower_user @@ -267,22 +365,14 @@ def set_flags_in_envs(postgres_user, celery_flower_user, debug=False): set_django_admin_url(production_django_envs_path) set_postgres_user(local_postgres_envs_path, value=postgres_user) - set_postgres_password( - local_postgres_envs_path, value=DEBUG_VALUE if debug else None - ) + set_postgres_password(local_postgres_envs_path, value=DEBUG_VALUE if debug else None) set_postgres_user(production_postgres_envs_path, value=postgres_user) - set_postgres_password( - production_postgres_envs_path, value=DEBUG_VALUE if debug else None - ) + set_postgres_password(production_postgres_envs_path, value=DEBUG_VALUE if debug else None) set_celery_flower_user(local_django_envs_path, value=celery_flower_user) - set_celery_flower_password( - local_django_envs_path, value=DEBUG_VALUE if debug else None - ) + set_celery_flower_password(local_django_envs_path, value=DEBUG_VALUE if debug else None) set_celery_flower_user(production_django_envs_path, value=celery_flower_user) - set_celery_flower_password( - production_django_envs_path, value=DEBUG_VALUE if debug else None - ) + set_celery_flower_password(production_django_envs_path, value=DEBUG_VALUE if debug else None) def set_flags_in_settings_files(): @@ -293,6 +383,7 @@ def set_flags_in_settings_files(): def remove_envs_and_associated_files(): shutil.rmtree(".envs") os.remove("merge_production_dotenvs_in_dotenv.py") + shutil.rmtree("tests") def remove_celery_compose_dirs(): @@ -311,21 +402,9 @@ def remove_aws_dockerfile(): def remove_drf_starter_files(): os.remove(os.path.join("config", "api_router.py")) shutil.rmtree(os.path.join("{{cookiecutter.project_slug}}", "users", "api")) - os.remove( - os.path.join( - "{{cookiecutter.project_slug}}", "users", "tests", "test_drf_urls.py" - ) - ) - os.remove( - os.path.join( - "{{cookiecutter.project_slug}}", "users", "tests", "test_drf_views.py" - ) - ) - os.remove( - os.path.join( - "{{cookiecutter.project_slug}}", "users", "tests", "test_swagger.py" - ) - ) + os.remove(os.path.join("{{cookiecutter.project_slug}}", "users", "tests", "test_drf_urls.py")) + os.remove(os.path.join("{{cookiecutter.project_slug}}", "users", "tests", "test_drf_views.py")) + os.remove(os.path.join("{{cookiecutter.project_slug}}", "users", "tests", "test_swagger.py")) def remove_storages_module(): @@ -347,6 +426,9 @@ def main(): if "{{ cookiecutter.open_source_license}}" != "GPLv3": remove_gplv3_files() + # if "{{ cookiecutter.username_type }}" == "username": + # remove_custom_user_manager_files() + if "{{ cookiecutter.use_pycharm }}".lower() == "n": remove_pycharm_files() @@ -355,10 +437,7 @@ def main(): else: remove_docker_files() - if ( - "{{ cookiecutter.use_docker }}".lower() == "y" - and "{{ cookiecutter.cloud_provider}}" != "AWS" - ): + if "{{ cookiecutter.use_docker }}".lower() == "y" and "{{ cookiecutter.cloud_provider}}" != "AWS": remove_aws_dockerfile() if "{{ cookiecutter.use_heroku }}".lower() == "n": @@ -366,10 +445,7 @@ def main(): elif "{{ cookiecutter.frontend_pipeline }}" != "Django Compressor": remove_heroku_build_hooks() - if ( - "{{ cookiecutter.use_docker }}".lower() == "n" - and "{{ cookiecutter.use_heroku }}".lower() == "n" - ): + if "{{ cookiecutter.use_docker }}".lower() == "n" and "{{ cookiecutter.use_heroku }}".lower() == "n": if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y": print( INFO + ".env(s) are only utilized when Docker Compose and/or " @@ -383,15 +459,23 @@ def main(): if "{{ cookiecutter.keep_local_envs_in_vcs }}".lower() == "y": append_to_gitignore_file("!.envs/.local/") - if "{{ cookiecutter.frontend_pipeline }}" != "Gulp": + if "{{ cookiecutter.frontend_pipeline }}" in ["None", "Django Compressor"]: remove_gulp_files() + remove_webpack_files() + remove_sass_files() remove_packagejson_file() if "{{ cookiecutter.use_docker }}".lower() == "y": remove_node_dockerfile() + else: + handle_js_runner( + "{{ cookiecutter.frontend_pipeline }}", + use_docker=("{{ cookiecutter.use_docker }}".lower() == "y"), + use_async=("{{ cookiecutter.use_async }}".lower() == "y"), + ) - if "{{ cookiecutter.cloud_provider}}" == "None": + if "{{ cookiecutter.cloud_provider }}" == "None" and "{{ cookiecutter.use_docker }}".lower() == "n": print( - WARNING + "You chose not to use a cloud provider, " + WARNING + "You chose to not use any cloud providers nor Docker, " "media files won't be served in production." + TERMINATOR ) remove_storages_module() diff --git a/hooks/pre_gen_project.py b/hooks/pre_gen_project.py index c3eef1e43..33dc2e834 100644 --- a/hooks/pre_gen_project.py +++ b/hooks/pre_gen_project.py @@ -17,26 +17,28 @@ INFO = "\x1b[1;33m [INFO]: " HINT = "\x1b[3;33m" SUCCESS = "\x1b[1;32m [SUCCESS]: " +# The content of this string is evaluated by Jinja, and plays an important role. +# It updates the cookiecutter context to trim leading and trailing spaces +# from domain/email values +""" +{{ cookiecutter.update({ "domain_name": cookiecutter.domain_name | trim }) }} +{{ cookiecutter.update({ "email": cookiecutter.email | trim }) }} +""" + project_slug = "{{ cookiecutter.project_slug }}" if hasattr(project_slug, "isidentifier"): - assert ( - project_slug.isidentifier() - ), "'{}' project slug is not a valid Python identifier.".format(project_slug) + assert project_slug.isidentifier(), "'{}' project slug is not a valid Python identifier.".format(project_slug) -assert ( - project_slug == project_slug.lower() -), "'{}' project slug should be all lowercase".format(project_slug) +assert project_slug == project_slug.lower(), "'{}' project slug should be all lowercase".format(project_slug) -assert ( - "\\" not in "{{ cookiecutter.author_name }}" -), "Don't include backslashes in author name." +assert "\\" not in "{{ cookiecutter.author_name }}", "Don't include backslashes in author name." if "{{ cookiecutter.use_docker }}".lower() == "n": python_major_version = sys.version_info[0] if python_major_version == 2: print( WARNING + "You're running cookiecutter under Python 2, but the generated " - "project requires Python 3.10+. Do you want to proceed (y/n)? " + TERMINATOR + "project requires Python 3.11+. Do you want to proceed (y/n)? " + TERMINATOR ) yes_options, no_options = frozenset(["y"]), frozenset(["n"]) while True: @@ -51,32 +53,16 @@ if "{{ cookiecutter.use_docker }}".lower() == "n": print( HINT + "Please respond with {} or {}: ".format( - ", ".join( - ["'{}'".format(o) for o in yes_options if not o == ""] - ), - ", ".join( - ["'{}'".format(o) for o in no_options if not o == ""] - ), + ", ".join(["'{}'".format(o) for o in yes_options if not o == ""]), + ", ".join(["'{}'".format(o) for o in no_options if not o == ""]), ) + TERMINATOR ) -if ( - "{{ cookiecutter.use_whitenoise }}".lower() == "n" - and "{{ cookiecutter.cloud_provider }}" == "None" -): - print( - "You should either use Whitenoise or select a " - "Cloud Provider to serve static files" - ) +if "{{ cookiecutter.use_whitenoise }}".lower() == "n" and "{{ cookiecutter.cloud_provider }}" == "None": + print("You should either use Whitenoise or select a " "Cloud Provider to serve static files") sys.exit(1) -if ( - "{{ cookiecutter.mail_service }}" == "Amazon SES" - and "{{ cookiecutter.cloud_provider }}" != "AWS" -): - print( - "You should either use AWS or select a different " - "Mail Service for sending emails." - ) +if "{{ cookiecutter.mail_service }}" == "Amazon SES" and "{{ cookiecutter.cloud_provider }}" != "AWS": + print("You should either use AWS or select a different " "Mail Service for sending emails.") sys.exit(1) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..2b4b98783 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,29 @@ +# ==== pytest ==== +[tool.pytest.ini_options] +addopts = "-v --tb=short" +norecursedirs = [ + ".tox", + ".git", + "*/migrations/*", + "*/static/*", + "docs", + "venv", + "*/{{cookiecutter.project_slug}}/*", +] + + +# ==== black ==== +[tool.black] +line-length = 119 +target-version = ['py311'] + + +# ==== isort ==== +[tool.isort] +profile = "black" +line_length = 119 +known_first_party = [ + "tests", + "scripts", + "hooks", +] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 52506f47d..000000000 --- a/pytest.ini +++ /dev/null @@ -1,3 +0,0 @@ -[pytest] -addopts = -v --tb=short -norecursedirs = .tox .git */migrations/* */static/* docs venv */{{cookiecutter.project_slug}}/* diff --git a/requirements.txt b/requirements.txt index 627cfebe5..f308aef60 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,26 +1,27 @@ cookiecutter==2.1.1 -sh==1.14.3; sys_platform != "win32" +sh==2.0.4; sys_platform != "win32" binaryornot==0.4.4 # Code quality # ------------------------------------------------------------------------------ -black==22.12.0 -isort==5.11.4 +black==23.3.0 +isort==5.12.0 flake8==6.0.0 -flake8-isort==6.0.0 -pre-commit==2.21.0 +django-upgrade==1.13.0 +pre-commit==3.3.1 # Testing # ------------------------------------------------------------------------------ -tox==4.2.7 -pytest==7.2.1 -pytest-cookies==0.6.1 -pytest-instafail==0.4.2 +tox==4.5.1 +pytest==7.3.1 +pytest-xdist==3.3.0 +pytest-cookies==0.7.0 +pytest-instafail==0.5.0 pyyaml==6.0 # Scripting # ------------------------------------------------------------------------------ -PyGithub==1.57 -gitpython==3.1.30 +PyGithub==1.58.2 +gitpython==3.1.31 jinja2==3.1.2 -requests==2.28.1 +requests==2.30.0 diff --git a/scripts/create_django_issue.py b/scripts/create_django_issue.py index 5809f393d..d3b3c3792 100644 --- a/scripts/create_django_issue.py +++ b/scripts/create_django_issue.py @@ -141,9 +141,7 @@ class GitHubManager: self.requirements_files = ["base", "local", "production"] # Format: # requirement file name: {package name: (master_version, package_info)} - self.requirements: dict[str, dict[str, tuple[str, dict]]] = { - x: {} for x in self.requirements_files - } + self.requirements: dict[str, dict[str, tuple[str, dict]]] = {x: {} for x in self.requirements_files} def setup(self) -> None: self.load_requirements() @@ -177,11 +175,7 @@ class GitHubManager: "is": "issue", "in": "title", } - issues = list( - self.github.search_issues( - "[Django Update]", "created", "desc", **qualifiers - ) - ) + issues = list(self.github.search_issues("[Django Update]", "created", "desc", **qualifiers)) print(f"Found {len(issues)} issues matching search") for issue in issues: matches = re.match(r"\[Update Django] Django (\d+.\d+)$", issue.title) @@ -194,9 +188,7 @@ class GitHubManager: else: self.existing_issues[issue_version] = issue - def get_compatibility( - self, package_name: str, package_info: dict, needed_dj_version: DjVersion - ): + def get_compatibility(self, package_name: str, package_info: dict, needed_dj_version: DjVersion): """ Verify compatibility via setup.py classifiers. If Django is not in the classifiers, then default compatibility is n/a and OK is ✅. @@ -209,9 +201,7 @@ class GitHubManager: # updated packages, or known releases that will happen but haven't yet if issue := self.existing_issues.get(needed_dj_version): if index := issue.body.find(package_name): - name, _current, prev_compat, ok = ( - s.strip() for s in issue.body[index:].split("|", 4)[:4] - ) + name, _current, prev_compat, ok = (s.strip() for s in issue.body[index:].split("|", 4)[:4]) if ok in ("✅", "❓", "🕒"): return prev_compat, ok @@ -248,9 +238,7 @@ class GitHubManager: ] def _get_md_home_page_url(self, package_info: dict): - urls = [ - package_info["info"].get(url_key) for url_key in self.HOME_PAGE_URL_KEYS - ] + urls = [package_info["info"].get(url_key) for url_key in self.HOME_PAGE_URL_KEYS] try: return f"[{{}}]({next(item for item in urls if item)})" except StopIteration: @@ -259,13 +247,9 @@ class GitHubManager: def generate_markdown(self, needed_dj_version: DjVersion): requirements = f"{needed_dj_version} requirements tables\n\n" for _file in self.requirements_files: - requirements += _TABLE_HEADER.format_map( - {"file": _file, "dj_version": needed_dj_version} - ) + requirements += _TABLE_HEADER.format_map({"file": _file, "dj_version": needed_dj_version}) for package_name, (version, info) in self.requirements[_file].items(): - compat_version, icon = self.get_compatibility( - package_name, info, needed_dj_version - ) + compat_version, icon = self.get_compatibility(package_name, info, needed_dj_version) requirements += ( f"| {self._get_md_home_page_url(info).format(package_name)} " f"| {version.strip()} " @@ -282,9 +266,7 @@ class GitHubManager: issue.edit(body=description) else: print(f"Creating new issue for Django {needed_dj_version}") - issue = self.repo.create_issue( - f"[Update Django] Django {needed_dj_version}", description - ) + issue = self.repo.create_issue(f"[Update Django] Django {needed_dj_version}", description) issue.add_to_labels(f"django{needed_dj_version}") def generate(self): @@ -297,9 +279,7 @@ class GitHubManager: def main(django_max_version=None) -> None: # Check if there are any djs - current_dj, latest_djs = get_all_latest_django_versions( - django_max_version=django_max_version - ) + current_dj, latest_djs = get_all_latest_django_versions(django_max_version=django_max_version) if not latest_djs: sys.exit(0) manager = GitHubManager(current_dj, latest_djs) @@ -309,9 +289,7 @@ def main(django_max_version=None) -> None: if __name__ == "__main__": if GITHUB_REPO is None: - raise RuntimeError( - "No github repo, please set the environment variable GITHUB_REPOSITORY" - ) + raise RuntimeError("No github repo, please set the environment variable GITHUB_REPOSITORY") max_version = None last_arg = sys.argv[-1] if CURRENT_FILE.name not in last_arg: diff --git a/scripts/update_changelog.py b/scripts/update_changelog.py index b50d25066..7d43a0b57 100644 --- a/scripts/update_changelog.py +++ b/scripts/update_changelog.py @@ -82,14 +82,20 @@ def group_pulls_by_change_type( grouped_pulls = { "Changed": [], "Fixed": [], + "Documentation": [], "Updated": [], } for pull in pull_requests_list: label_names = {label.name for label in pull.labels} + if "project infrastructure" in label_names: + # Don't mention it in the changelog + continue if "update" in label_names: group_name = "Updated" elif "bug" in label_names: group_name = "Fixed" + elif "docs" in label_names: + group_name = "Documentation" else: group_name = "Changed" grouped_pulls[group_name].append(pull) @@ -148,11 +154,7 @@ def update_git_repo(paths: list[Path], release: str) -> None: if __name__ == "__main__": if GITHUB_REPO is None: - raise RuntimeError( - "No github repo, please set the environment variable GITHUB_REPOSITORY" - ) + raise RuntimeError("No github repo, please set the environment variable GITHUB_REPOSITORY") if GIT_BRANCH is None: - raise RuntimeError( - "No git branch set, please set the GITHUB_REF_NAME environment variable" - ) + raise RuntimeError("No git branch set, please set the GITHUB_REF_NAME environment variable") main() diff --git a/scripts/update_contributors.py b/scripts/update_contributors.py index 76ccf60ad..09a7082c0 100644 --- a/scripts/update_contributors.py +++ b/scripts/update_contributors.py @@ -44,15 +44,9 @@ def iter_recent_authors(): git CLI to work with Github usernames. """ repo = Github(login_or_token=GITHUB_TOKEN, per_page=5).get_repo(GITHUB_REPO) - recent_pulls = repo.get_pulls( - state="closed", sort="updated", direction="desc" - ).get_page(0) + recent_pulls = repo.get_pulls(state="closed", sort="updated", direction="desc").get_page(0) for pull in recent_pulls: - if ( - pull.merged - and pull.user.type == "User" - and pull.user.login not in BOT_LOGINS - ): + if pull.merged and pull.user.type == "User" and pull.user.login not in BOT_LOGINS: yield pull.user @@ -96,9 +90,7 @@ def write_md_file(contributors): core_contributors = [c for c in contributors if c.get("is_core", False)] other_contributors = (c for c in contributors if not c.get("is_core", False)) other_contributors = sorted(other_contributors, key=lambda c: c["name"].lower()) - content = template.render( - core_contributors=core_contributors, other_contributors=other_contributors - ) + content = template.render(core_contributors=core_contributors, other_contributors=other_contributors) file_path = ROOT / "CONTRIBUTORS.md" file_path.write_text(content) @@ -106,7 +98,5 @@ def write_md_file(contributors): if __name__ == "__main__": if GITHUB_REPO is None: - raise RuntimeError( - "No github repo, please set the environment variable GITHUB_REPOSITORY" - ) + raise RuntimeError("No github repo, please set the environment variable GITHUB_REPOSITORY") main() diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index dd8f1ef3c..000000000 --- a/setup.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[flake8] -exclude = docs -max-line-length = 88 - -[isort] -profile = black -known_first_party = tests,scripts,hooks diff --git a/setup.py b/setup.py index cdbbc6929..f1933ad27 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ except ImportError: from distutils.core import setup # We use calendar versioning -version = "2023.01.15" +version = "2023.05.15" with open("README.rst") as readme_file: long_description = readme_file.read() @@ -13,10 +13,7 @@ with open("README.rst") as readme_file: setup( name="cookiecutter-django", version=version, - description=( - "A Cookiecutter template for creating production-ready " - "Django projects quickly." - ), + description=("A Cookiecutter template for creating production-ready " "Django projects quickly."), long_description=long_description, author="Daniel Roy Greenfeld", author_email="pydanny@gmail.com", @@ -27,13 +24,13 @@ setup( classifiers=[ "Development Status :: 4 - Beta", "Environment :: Console", - "Framework :: Django :: 4.0", + "Framework :: Django :: 4.1", "Intended Audience :: Developers", "Natural Language :: English", "License :: OSI Approved :: BSD License", "Programming Language :: Python", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development", ], diff --git a/tests/test_bare.sh b/tests/test_bare.sh index 05da9328b..5dc175ebd 100755 --- a/tests/test_bare.sh +++ b/tests/test_bare.sh @@ -20,25 +20,17 @@ sudo utility/install_os_dependencies.sh install # Install Python deps pip install -r requirements/local.txt -# Lint by running pre-commit on all files -# Needs a git repo to find the project root -git init -git add . -pre-commit run --show-diff-on-failure -a - # run the project's tests pytest # Make sure the check doesn't raise any warnings python manage.py check --fail-level WARNING +# Run npm build script if package.json is present if [ -f "package.json" ] then npm install - if [ -f "gulpfile.js" ] - then - npm run build - fi + npm run build fi # Generate the HTML for the documentation diff --git a/tests/test_cookiecutter_generation.py b/tests/test_cookiecutter_generation.py index 6219f75ef..778e3411f 100755 --- a/tests/test_cookiecutter_generation.py +++ b/tests/test_cookiecutter_generation.py @@ -1,3 +1,4 @@ +import glob import os import re import sys @@ -20,6 +21,12 @@ if sys.platform.startswith("win"): elif sys.platform.startswith("darwin") and os.getenv("CI"): pytest.skip("skipping slow macOS tests on CI", allow_module_level=True) +# Run auto-fixable styles checks - skipped on CI by default. These can be fixed +# automatically by running pre-commit after generation however they are tedious +# to fix in the template, so we don't insist too much in fixing them. +AUTOFIXABLE_STYLES = os.getenv("AUTOFIXABLE_STYLES") == "1" +auto_fixable = pytest.mark.skipif(not AUTOFIXABLE_STYLES, reason="auto-fixable") + @pytest.fixture def context(): @@ -36,6 +43,8 @@ def context(): SUPPORTED_COMBINATIONS = [ + {"username_type": "username"}, + {"username_type": "email"}, {"open_source_license": "MIT"}, {"open_source_license": "BSD"}, {"open_source_license": "GPLv3"}, @@ -101,6 +110,7 @@ SUPPORTED_COMBINATIONS = [ {"frontend_pipeline": "None"}, {"frontend_pipeline": "Django Compressor"}, {"frontend_pipeline": "Gulp"}, + {"frontend_pipeline": "Webpack"}, {"use_celery": "y"}, {"use_celery": "n"}, {"use_mailhog": "y"}, @@ -134,13 +144,9 @@ def _fixture_id(ctx): return "-".join(f"{key}:{value}" for key, value in ctx.items()) -def build_files_list(root_dir): +def build_files_list(base_dir): """Build a list containing absolute paths to the generated files.""" - return [ - os.path.join(dirpath, file_path) - for dirpath, subdirs, files in os.walk(root_dir) - for file_path in files - ] + return [os.path.join(dirpath, file_path) for dirpath, subdirs, files in os.walk(base_dir) for file_path in files] def check_paths(paths): @@ -181,9 +187,10 @@ def test_flake8_passes(cookies, context_override): pytest.fail(e.stdout.decode()) +@auto_fixable @pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id) def test_black_passes(cookies, context_override): - """Generated project should pass black.""" + """Check whether generated project passes black style.""" result = cookies.bake(extra_context=context_override) try: @@ -199,6 +206,39 @@ def test_black_passes(cookies, context_override): pytest.fail(e.stdout.decode()) +@auto_fixable +@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id) +def test_isort_passes(cookies, context_override): + """Check whether generated project passes isort style.""" + result = cookies.bake(extra_context=context_override) + + try: + sh.isort(_cwd=str(result.project_path)) + except sh.ErrorReturnCode as e: + pytest.fail(e.stdout.decode()) + + +@auto_fixable +@pytest.mark.parametrize("context_override", SUPPORTED_COMBINATIONS, ids=_fixture_id) +def test_django_upgrade_passes(cookies, context_override): + """Check whether generated project passes django-upgrade.""" + result = cookies.bake(extra_context=context_override) + + python_files = [ + file_path.removeprefix(f"{result.project_path}/") + for file_path in glob.glob(str(result.project_path / "**" / "*.py"), recursive=True) + ] + try: + sh.django_upgrade( + "--target-version", + "4.1", + *python_files, + _cwd=str(result.project_path), + ) + except sh.ErrorReturnCode as e: + pytest.fail(e.stdout.decode()) + + @pytest.mark.parametrize( ["use_docker", "expected_test_script"], [ @@ -231,9 +271,7 @@ def test_travis_invokes_pytest(cookies, context, use_docker, expected_test_scrip ("y", "docker-compose -f local.yml run django pytest"), ], ) -def test_gitlab_invokes_flake8_and_pytest( - cookies, context, use_docker, expected_test_script -): +def test_gitlab_invokes_precommit_and_pytest(cookies, context, use_docker, expected_test_script): context.update({"ci_tool": "Gitlab", "use_docker": use_docker}) result = cookies.bake(extra_context=context) @@ -245,7 +283,9 @@ def test_gitlab_invokes_flake8_and_pytest( with open(f"{result.project_path}/.gitlab-ci.yml") as gitlab_yml: try: gitlab_config = yaml.safe_load(gitlab_yml) - assert gitlab_config["flake8"]["script"] == ["flake8"] + assert gitlab_config["precommit"]["script"] == [ + "pre-commit run --show-diff-on-failure --color=always --all-files" + ] assert gitlab_config["pytest"]["script"] == [expected_test_script] except yaml.YAMLError as e: pytest.fail(e) @@ -258,9 +298,7 @@ def test_gitlab_invokes_flake8_and_pytest( ("y", "docker-compose -f local.yml run django pytest"), ], ) -def test_github_invokes_linter_and_pytest( - cookies, context, use_docker, expected_test_script -): +def test_github_invokes_linter_and_pytest(cookies, context, use_docker, expected_test_script): context.update({"ci_tool": "Github", "use_docker": use_docker}) result = cookies.bake(extra_context=context) @@ -316,10 +354,29 @@ def test_error_if_incompatible(cookies, context, invalid_context): ], ) def test_pycharm_docs_removed(cookies, context, use_pycharm, pycharm_docs_exist): - """.""" context.update({"use_pycharm": use_pycharm}) result = cookies.bake(extra_context=context) with open(f"{result.project_path}/docs/index.rst") as f: has_pycharm_docs = "pycharm/configuration" in f.read() assert has_pycharm_docs is pycharm_docs_exist + + +def test_trim_domain_email(cookies, context): + """Check that leading and trailing spaces are trimmed in domain and email.""" + context.update( + { + "use_docker": "y", + "domain_name": " example.com ", + "email": " me@example.com ", + } + ) + result = cookies.bake(extra_context=context) + + assert result.exit_code == 0 + + prod_django_env = result.project_path / ".envs" / ".production" / ".django" + assert "DJANGO_ALLOWED_HOSTS=.example.com" in prod_django_env.read_text() + + base_settings = result.project_path / "config" / "settings" / "base.py" + assert '"me@example.com"' in base_settings.read_text() diff --git a/tests/test_docker.sh b/tests/test_docker.sh index b3663bd2c..5c60d20d3 100755 --- a/tests/test_docker.sh +++ b/tests/test_docker.sh @@ -14,13 +14,6 @@ cd .cache/docker cookiecutter ../../ --no-input --overwrite-if-exists use_docker=y "$@" cd my_awesome_project -# Lint by running pre-commit on all files -# Needs a git repo to find the project root -# We don't have git inside Docker, so run it outside -git init -git add . -pre-commit run --show-diff-on-failure -a - # make sure all images build docker-compose -f local.yml build @@ -41,3 +34,9 @@ docker-compose -f local.yml run django python manage.py check --fail-level WARNI # Generate the HTML for the documentation docker-compose -f local.yml run docs make html + +# Run npm build script if package.json is present +if [ -f "package.json" ] +then + docker-compose -f local.yml run node npm run build +fi diff --git a/tests/test_hooks.py b/tests/test_hooks.py index 7ca752722..6afdc400b 100644 --- a/tests/test_hooks.py +++ b/tests/test_hooks.py @@ -22,7 +22,5 @@ def test_append_to_gitignore_file(working_directory): gitignore_file.write_text("node_modules/\n") append_to_gitignore_file(".envs/*") linesep = os.linesep.encode() - assert ( - gitignore_file.read_bytes() == b"node_modules/" + linesep + b".envs/*" + linesep - ) + assert gitignore_file.read_bytes() == b"node_modules/" + linesep + b".envs/*" + linesep assert gitignore_file.read_text() == "node_modules/\n.envs/*\n" diff --git a/tox.ini b/tox.ini index 0400e4f91..903d5a53b 100644 --- a/tox.ini +++ b/tox.ini @@ -1,10 +1,11 @@ [tox] skipsdist = true -envlist = py310,black-template +envlist = py311,black-template [testenv] deps = -rrequirements.txt -commands = pytest {posargs:./tests} +passenv = AUTOFIXABLE_STYLES +commands = pytest -n auto {posargs:./tests} [testenv:black-template] deps = black diff --git a/{{cookiecutter.project_slug}}/.editorconfig b/{{cookiecutter.project_slug}}/.editorconfig index 6a9a5c45d..c0ce34260 100644 --- a/{{cookiecutter.project_slug}}/.editorconfig +++ b/{{cookiecutter.project_slug}}/.editorconfig @@ -22,6 +22,6 @@ trim_trailing_whitespace = false [Makefile] indent_style = tab -[nginx.conf] +[default.conf] indent_style = space indent_size = 2 diff --git a/{{cookiecutter.project_slug}}/.github/dependabot.yml b/{{cookiecutter.project_slug}}/.github/dependabot.yml index 420a63cdc..be52c68d5 100644 --- a/{{cookiecutter.project_slug}}/.github/dependabot.yml +++ b/{{cookiecutter.project_slug}}/.github/dependabot.yml @@ -4,11 +4,11 @@ version: 2 updates: # Update GitHub actions in workflows - - package-ecosystem: "github-actions" - directory: "/" - # Check for updates to GitHub Actions every weekday + - package-ecosystem: 'github-actions' + directory: '/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' {%- if cookiecutter.use_docker == 'y' %} @@ -16,80 +16,92 @@ updates: # We need to specify each Dockerfile in a separate entry because Dependabot doesn't # support wildcards or recursively checking subdirectories. Check this issue for updates: # https://github.com/dependabot/dependabot-core/issues/2178 - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/local/django` directory - directory: "compose/local/django/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/local/django/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' + # Ignore minor version updates (3.10 -> 3.11) but update patch versions + ignore: + - dependency-name: '*' + update-types: + - 'version-update:semver-major' + - 'version-update:semver-minor' - # Enable version updates for Docker - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/local/docs` directory - directory: "compose/local/docs/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/local/docs/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' + # Ignore minor version updates (3.10 -> 3.11) but update patch versions + ignore: + - dependency-name: '*' + update-types: + - 'version-update:semver-major' + - 'version-update:semver-minor' - # Enable version updates for Docker - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/local/node` directory - directory: "compose/local/node/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/local/node/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' - # Enable version updates for Docker - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/production/aws` directory - directory: "compose/production/aws/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/production/aws/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' - # Enable version updates for Docker - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/production/django` directory - directory: "compose/production/django/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/production/django/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' + # Ignore minor version updates (3.10 -> 3.11) but update patch versions + ignore: + - dependency-name: '*' + update-types: + - 'version-update:semver-major' + - 'version-update:semver-minor' - # Enable version updates for Docker - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/production/postgres` directory - directory: "compose/production/postgres/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/production/postgres/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' - # Enable version updates for Docker - - package-ecosystem: "docker" + - package-ecosystem: 'docker' # Look for a `Dockerfile` in the `compose/production/traefik` directory - directory: "compose/production/traefik/" - # Check for updates to GitHub Actions every weekday + directory: 'compose/production/traefik/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' {%- endif %} # Enable version updates for Python/Pip - Production - - package-ecosystem: "pip" + - package-ecosystem: 'pip' # Look for a `requirements.txt` in the `root` directory # also 'setup.cfg', 'runtime.txt' and 'requirements/*.txt' - directory: "/" - # Check for updates to GitHub Actions every weekday + directory: '/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' {%- if cookiecutter.frontend_pipeline == 'Gulp' %} # Enable version updates for javascript/npm - - package-ecosystem: "npm" - # Look for a `packages.json' in the `root` directory - directory: "/" - # Check for updates to GitHub Actions every weekday + - package-ecosystem: 'npm' + # Look for a `packages.json` in the `root` directory + directory: '/' + # Every weekday schedule: - interval: "daily" + interval: 'daily' {%- endif %} diff --git a/{{cookiecutter.project_slug}}/.github/workflows/ci.yml b/{{cookiecutter.project_slug}}/.github/workflows/ci.yml index 0790187bd..ac231ee72 100644 --- a/{{cookiecutter.project_slug}}/.github/workflows/ci.yml +++ b/{{cookiecutter.project_slug}}/.github/workflows/ci.yml @@ -7,12 +7,12 @@ env: on: pull_request: - branches: [ "master", "main" ] - paths-ignore: [ "docs/**" ] + branches: ['master', 'main'] + paths-ignore: ['docs/**'] push: - branches: [ "master", "main" ] - paths-ignore: [ "docs/**" ] + branches: ['master', 'main'] + paths-ignore: ['docs/**'] concurrency: group: {% raw %}${{ github.head_ref || github.run_id }}{% endraw %} @@ -22,21 +22,19 @@ jobs: linter: runs-on: ubuntu-latest steps: - - name: Checkout Code Repository uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: - python-version: "3.10" - cache: pip - cache-dependency-path: | - requirements/base.txt - requirements/local.txt + python-version: '3.11' + {%- if cookiecutter.open_source_license != 'Not open source' %} + # Consider using pre-commit.ci for open source project + {%- endif %} - name: Run pre-commit - uses: pre-commit/action@v2.0.3 + uses: pre-commit/action@v3.0.0 # With no caching at all the entire ci process takes 4m 30s to complete! pytest: @@ -59,35 +57,34 @@ jobs: env: {%- if cookiecutter.use_celery == 'y' %} - CELERY_BROKER_URL: "redis://localhost:6379/0" + CELERY_BROKER_URL: 'redis://localhost:6379/0' {%- endif %} # postgres://user:password@host:port/database - DATABASE_URL: "postgres://postgres:postgres@localhost:5432/postgres" + DATABASE_URL: 'postgres://postgres:postgres@localhost:5432/postgres' {%- endif %} steps: - - name: Checkout Code Repository uses: actions/checkout@v3 {%- if cookiecutter.use_docker == 'y' %} - name: Build the Stack - run: docker-compose -f local.yml build + run: docker-compose -f local.yml build - name: Run DB Migrations - run: docker-compose -f local.yml run --rm django python manage.py migrate + run: docker-compose -f local.yml run --rm django python manage.py migrate - name: Run Django Tests - run: docker-compose -f local.yml run django pytest + run: docker-compose -f local.yml run django pytest - name: Tear down the Stack - run: docker-compose -f local.yml down + run: docker-compose -f local.yml down {%- else %} - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: - python-version: "3.10" + python-version: '3.11' cache: pip cache-dependency-path: | requirements/base.txt @@ -99,5 +96,5 @@ jobs: pip install -r requirements/local.txt - name: Test with pytest - run: pytest + run: pytest {%- endif %} diff --git a/{{cookiecutter.project_slug}}/.gitignore b/{{cookiecutter.project_slug}}/.gitignore index acc484307..19bb2bc07 100644 --- a/{{cookiecutter.project_slug}}/.gitignore +++ b/{{cookiecutter.project_slug}}/.gitignore @@ -346,4 +346,9 @@ project.css project.min.css vendors.js *.min.js +*.min.js.map +{%- endif %} +{%- if cookiecutter.frontend_pipeline == 'Webpack' %} +{{ cookiecutter.project_slug }}/static/webpack_bundles/ +webpack-stats.json {%- endif %} diff --git a/{{cookiecutter.project_slug}}/.gitlab-ci.yml b/{{cookiecutter.project_slug}}/.gitlab-ci.yml index dbb65fb73..a312a41ae 100644 --- a/{{cookiecutter.project_slug}}/.gitlab-ci.yml +++ b/{{cookiecutter.project_slug}}/.gitlab-ci.yml @@ -7,21 +7,26 @@ variables: POSTGRES_PASSWORD: '' POSTGRES_DB: 'test_{{ cookiecutter.project_slug }}' POSTGRES_HOST_AUTH_METHOD: trust - {% if cookiecutter.use_celery == 'y' -%} + {%- if cookiecutter.use_celery == 'y' %} CELERY_BROKER_URL: 'redis://redis:6379/0' {%- endif %} -flake8: +precommit: stage: lint - image: python:3.10-alpine + image: python:3.11 + variables: + PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit + cache: + paths: + - ${PRE_COMMIT_HOME} before_script: - - pip install -q flake8 + - pip install -q pre-commit script: - - flake8 + - pre-commit run --show-diff-on-failure --color=always --all-files pytest: stage: test - {% if cookiecutter.use_docker == 'y' -%} + {%- if cookiecutter.use_docker == 'y' %} image: docker/compose:1.29.2 tags: - docker @@ -34,19 +39,16 @@ pytest: - docker-compose -f local.yml up -d script: - docker-compose -f local.yml run django pytest - {%- else -%} - image: python:3.10 + {%- else %} + image: python:3.11 tags: - python services: - postgres:{{ cookiecutter.postgresql_version }} variables: DATABASE_URL: pgsql://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres/$POSTGRES_DB - before_script: - pip install -r requirements/local.txt - script: - pytest {%- endif %} - diff --git a/{{cookiecutter.project_slug}}/.idea/runConfigurations/docker_compose_up_django.xml b/{{cookiecutter.project_slug}}/.idea/runConfigurations/docker_compose_up_django.xml index ad3b6a35a..e84c5ffdd 100644 --- a/{{cookiecutter.project_slug}}/.idea/runConfigurations/docker_compose_up_django.xml +++ b/{{cookiecutter.project_slug}}/.idea/runConfigurations/docker_compose_up_django.xml @@ -10,7 +10,7 @@