Skip to content

Commit 24bf881

Browse files
authored
Add Docker and GitHub Actions (#3)
1 parent c6b8d6a commit 24bf881

File tree

12 files changed

+145
-23
lines changed

12 files changed

+145
-23
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Best practices [cookiecutter](https://github.com/audreyr/cookiecutter) template
99
- Static typing with [mypy](http://mypy-lang.org/)
1010
- Linting with [flake8](http://flake8.pycqa.org/en/latest/)
1111
- Git hooks that run all the above with [pre-commit](https://pre-commit.com/)
12+
- Deployment ready with [Docker](https://docker.com/)
13+
- Continuous Integration with [GitHub Actions](https://github.com/features/actions)
1214

1315
## Quickstart
1416
```sh

cookiecutter.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
22
"project_name": "Best Practices",
3-
"repo_name": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}"
3+
"repo_name": "{{ cookiecutter.project_name.lower().replace(' ', '_').replace('-', '_') }}",
4+
"docker": "y"
45
}

hooks/post_gen_project.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,41 @@
1+
import os
12
import sys
23

3-
python_version = str(sys.version_info.major) + '.' + str(sys.version_info.minor)
44

5+
def set_python_version():
6+
python_version = str(sys.version_info.major) + "." + str(sys.version_info.minor)
57

6-
with open('Pipfile') as f:
7-
pipfile = f.read()
8-
pipfile = pipfile.replace(r'{python_version}', python_version)
8+
file_names = ["Dockerfile", "Pipfile", ".github/workflows/test.yml"]
9+
for file_name in file_names:
10+
with open(file_name) as f:
11+
contents = f.read()
12+
contents = contents.replace(r"{python_version}", python_version)
13+
with open(file_name, "w") as f:
14+
f.write(contents)
915

1016

11-
with open('Pipfile', 'w') as f:
12-
f.write(pipfile)
17+
def remove_docker():
18+
file_names = ["Dockerfile", ".dockerignore"]
19+
for file_name in file_names:
20+
if os.path.exists(file_name):
21+
os.remove(file_name)
22+
23+
24+
SUCCESS = "\x1b[1;32m"
25+
INFO = "\x1b[1;33m"
26+
TERMINATOR = "\x1b[0m"
27+
28+
29+
def main():
30+
set_python_version()
31+
32+
docker = "{{ cookiecutter.docker }}".lower() == "y"
33+
34+
if not docker:
35+
remove_docker()
36+
37+
print(SUCCESS + "Project successfully initialized" + TERMINATOR)
38+
39+
40+
if __name__ == "__main__":
41+
main()

hooks/pre_gen_project.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import re
22
import sys
33

4-
MODULE_REGEX = r'^[a-zA-Z][_a-zA-Z0-9]+$'
5-
module_name = '{{ cookiecutter.repo_name }}'
4+
MODULE_REGEX = r"^[a-zA-Z][_a-zA-Z0-9]+$"
5+
module_name = "{{ cookiecutter.repo_name }}"
66

77
if not re.match(MODULE_REGEX, module_name):
8-
print('ERROR: %s is not a valid Python module name!' % module_name)
8+
print("ERROR: %s is not a valid Python module name!" % module_name)
99
sys.exit(1)

{{cookiecutter.repo_name}}/.coveragerc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[run]
22
source = {{cookiecutter.repo_name}}
3+
omit = {{cookiecutter.repo_name}}/__main__.py
34

45
[report]
56
exclude_lines =
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Ignore everything
2+
**
3+
4+
# ... except for dependencies and source
5+
!Pipfile
6+
!Pipfile.lock
7+
!{{cookiecutter.repo_name}}

{{cookiecutter.repo_name}}/.editorconfig

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@ insert_final_newline = true
1010
trim_trailing_whitespace = true
1111

1212
[*.md]
13-
indent_size = 4
14-
15-
[*.md]
16-
indent_size = 4
1713
trim_trailing_whitespace = false
1814

1915
[Makefile]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Test
2+
3+
on:
4+
pull_request: {}
5+
push:
6+
branches: master
7+
tags: "*"
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
15+
- name: Setup Python
16+
uses: actions/setup-python@v1
17+
with:
18+
python-version: {python_version}
19+
20+
- name: Install dependencies with pipenv
21+
run: |
22+
pip install pipenv
23+
pipenv install --deploy --dev
24+
25+
- run: pipenv run isort --recursive --diff
26+
- run: pipenv run black --check .
27+
- run: pipenv run flake8
28+
- run: pipenv run mypy
29+
- run: pipenv run pytest --cov --cov-fail-under=100
30+
31+
docker-image:
32+
runs-on: ubuntu-latest
33+
steps:
34+
- uses: actions/checkout@v2
35+
36+
- name: Build docker image
37+
run: docker build . -t {{cookiecutter.repo_name}}:test
38+
39+
- name: Smoke test docker image
40+
run: |
41+
docker run --rm {{cookiecutter.repo_name}}:test 10

{{cookiecutter.repo_name}}/.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ repos:
3030
language: system
3131
entry: pipenv run mypy
3232
types: [python]
33-
pass_filenames: false
33+
require_serial: true
3434

3535
- id: pytest
3636
name: pytest

{{cookiecutter.repo_name}}/Dockerfile

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
FROM python:{python_version}-slim AS base
2+
3+
# Setup env
4+
ENV LANG C.UTF-8
5+
ENV LC_ALL C.UTF-8
6+
ENV PYTHONDONTWRITEBYTECODE 1
7+
ENV PYTHONFAULTHANDLER 1
8+
9+
10+
FROM base AS python-deps
11+
12+
# Install pipenv and compilation dependencies
13+
RUN pip install pipenv
14+
RUN apt-get update && apt-get install -y --no-install-recommends gcc
15+
16+
# Install python dependencies in /.venv
17+
COPY Pipfile .
18+
COPY Pipfile.lock .
19+
RUN PIPENV_VENV_IN_PROJECT=1 pipenv install --deploy
20+
21+
22+
FROM base AS runtime
23+
24+
# Copy virtual env from python-deps stage
25+
COPY --from=python-deps /.venv /.venv
26+
ENV PATH="/.venv/bin:$PATH"
27+
28+
# Create and switch to a new user
29+
RUN useradd --create-home appuser
30+
WORKDIR /home/appuser
31+
USER appuser
32+
33+
# Install application into container
34+
COPY . .
35+
36+
# Run the executable
37+
ENTRYPOINT ["python", "-m", "{{cookiecutter.repo_name}}"]
38+
CMD ["10"]

0 commit comments

Comments
 (0)