Compare commits
	
		
			12 Commits
		
	
	
		
			0.1.1
			...
			8e1c670ffd
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8e1c670ffd | |||
| e5a9b9aa50 | |||
| c9b2d5bd8d | |||
| 0d20b543b0 | |||
| f7b69f7704 | |||
| 1ccfdc321a | |||
| 25a58c2732 | |||
| 270d9f7296 | |||
| 2939b4a515 | |||
| d029fda896 | |||
| 9dead362c1 | |||
| d81dba727b | 
							
								
								
									
										1
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.dockerignore
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| src/web/static/* | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -5,3 +5,4 @@ __pycache__ | ||||
| node_modules | ||||
| package-lock.json | ||||
| db.sqlite3 | ||||
| src/web/static | ||||
							
								
								
									
										12
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								CHANGELOG.md
									
									
									
									
									
								
							| @ -1,3 +1,15 @@ | ||||
| ## 0.1.4 / 2023-01-08 15:45+01:00 | ||||
|  | ||||
| * Fix collectstaticfiles causing error when restarting container (https://git.kucharczyk.xyz/lukas/timetracker/issues/23) | ||||
|  | ||||
| ## 0.1.3 / 2023-01-08 15:23+01:00 | ||||
|  | ||||
| * Fix CSRF error (https://git.kucharczyk.xyz/lukas/timetracker/pulls/22) | ||||
|  | ||||
| ## 0.1.2 / 2023-01-07 22:05+01:00 | ||||
|  | ||||
| * Switch to Uvicorn/Gunicorn + Caddy (https://git.kucharczyk.xyz/lukas/timetracker/pulls/4) | ||||
|  | ||||
| ## 0.1.1 / 2023-01-05 23:26+01:00 | ||||
| * Order by timestamp_start by default | ||||
| * Add pre-commit hook to update version | ||||
|  | ||||
							
								
								
									
										14
									
								
								Caddyfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Caddyfile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| { | ||||
|     auto_https off | ||||
|     admin off | ||||
| } | ||||
|  | ||||
| :8000 { | ||||
|     handle_path /static/* { | ||||
|         root * src/web/static/ | ||||
|         file_server | ||||
|     } | ||||
|     handle { | ||||
|         reverse_proxy :8001 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -4,12 +4,17 @@ COPY . /app | ||||
| RUN npm install && \ | ||||
|     npx tailwindcss -i ./src/input.css -o ./src/web/tracker/static/base.css --minify | ||||
|  | ||||
| FROM python:3.10-slim-bullseye | ||||
| FROM python:3.10.9-alpine | ||||
|  | ||||
| ENV VERSION_NUMBER 0.1.0-48-gdb5de81 | ||||
| ENV VERSION_NUMBER 0.1.4 | ||||
| ENV PROD 1 | ||||
|  | ||||
| RUN useradd --create-home --uid 1000 timetracker | ||||
| RUN apk add \ | ||||
|     bash \ | ||||
|     vim \ | ||||
|     curl \ | ||||
|     caddy | ||||
| RUN adduser -D -u 1000 timetracker | ||||
| WORKDIR /home/timetracker/app | ||||
| COPY . /home/timetracker/app/ | ||||
| RUN chown -R timetracker:timetracker /home/timetracker/app | ||||
|  | ||||
							
								
								
									
										18
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Makefile
									
									
									
									
									
								
							| @ -1,5 +1,3 @@ | ||||
| .PHONY: createsuperuser shell | ||||
|  | ||||
| all: css migrate | ||||
|  | ||||
| initialize: npm css migrate sethookdir loadplatforms | ||||
| @ -24,6 +22,12 @@ migrate: makemigrations | ||||
| dev: migrate sethookdir | ||||
| 	poetry run python src/web/manage.py runserver_plus | ||||
|  | ||||
| caddy: | ||||
| 	caddy run --watch | ||||
|  | ||||
| dev-prod: migrate collectstatic sethookdir | ||||
| 	cd src/web/; PROD=1 poetry run python -m gunicorn --bind 0.0.0.0:8001 web.asgi:application -k uvicorn.workers.UvicornWorker | ||||
|  | ||||
| dumptracker: | ||||
| 	poetry run python src/web/manage.py dumpdata --format yaml tracker --output tracker_fixture.yaml | ||||
|  | ||||
| @ -39,6 +43,9 @@ createsuperuser: | ||||
| shell: | ||||
| 	poetry run python src/web/manage.py shell | ||||
|  | ||||
| collectstatic: | ||||
| 	poetry run python src/web/manage.py collectstatic --clear --no-input | ||||
|  | ||||
| poetry.lock: pyproject.toml | ||||
| 	poetry install | ||||
|  | ||||
| @ -48,5 +55,10 @@ test: poetry.lock | ||||
| sethookdir: | ||||
| 	git config core.hooksPath .githooks | ||||
|  | ||||
| make date: | ||||
| date: | ||||
| 	python3 -c 'import datetime; from zoneinfo import ZoneInfo; print(datetime.datetime.isoformat(datetime.datetime.now(ZoneInfo("Europe/Prague")), timespec="minutes", sep=" "))' | ||||
|  | ||||
| cleanstatic: | ||||
| 	rm -r src/web/static/* | ||||
|  | ||||
| clean: cleanstatic | ||||
|  | ||||
							
								
								
									
										17
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								docker-compose.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | ||||
| --- | ||||
| services: | ||||
|   timetracker: | ||||
|     image: registry.kucharczyk.xyz/timetracker | ||||
|     build: | ||||
|       context: . | ||||
|       dockerfile: Dockerfile | ||||
|     container_name: timetracker | ||||
|     environment: | ||||
|       - TZ=Europe/Prague | ||||
|       - CSRF_TRUSTED_ORIGINS="https://tracker.kucharczyk.xyz" | ||||
|     user: "1000" | ||||
|     # volumes: | ||||
|     #   - "db:/home/timetracker/app/src/web/db.sqlite3" | ||||
|     ports: | ||||
|       - "8000:8000" | ||||
|     restart: unless-stopped | ||||
| @ -1,8 +1,13 @@ | ||||
| #!/bin/bash | ||||
| # Apply database migrations | ||||
| set -euo pipefail | ||||
| echo "Apply database migrations" | ||||
| poetry run python src/web/manage.py migrate | ||||
|  | ||||
| # Start server | ||||
| echo "Collect static files" | ||||
| poetry run python src/web/manage.py collectstatic --clear --no-input | ||||
|  | ||||
| echo "Starting server" | ||||
| poetry run python src/web/manage.py runserver 0.0.0.0:8000 | ||||
| caddy start | ||||
| cd src/web || exit | ||||
| poetry run python -m gunicorn --bind 0.0.0.0:8001 web.asgi:application -k uvicorn.workers.UvicornWorker | ||||
|  | ||||
							
								
								
									
										75
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										75
									
								
								poetry.lock
									
									
									
										generated
									
									
									
								
							| @ -73,7 +73,7 @@ uvloop = ["uvloop (>=0.15.2)"] | ||||
| name = "click" | ||||
| version = "8.1.3" | ||||
| description = "Composable command line interface toolkit" | ||||
| category = "dev" | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
| @ -88,7 +88,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} | ||||
| name = "colorama" | ||||
| version = "0.4.6" | ||||
| description = "Cross-platform colored terminal text." | ||||
| category = "dev" | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" | ||||
| files = [ | ||||
| @ -215,6 +215,39 @@ files = [ | ||||
| [package.extras] | ||||
| test = ["pytest (>=6)"] | ||||
|  | ||||
| [[package]] | ||||
| name = "gunicorn" | ||||
| version = "20.1.0" | ||||
| description = "WSGI HTTP Server for UNIX" | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = ">=3.5" | ||||
| files = [ | ||||
|     {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, | ||||
|     {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, | ||||
| ] | ||||
|  | ||||
| [package.dependencies] | ||||
| setuptools = ">=3.0" | ||||
|  | ||||
| [package.extras] | ||||
| eventlet = ["eventlet (>=0.24.1)"] | ||||
| gevent = ["gevent (>=1.4.0)"] | ||||
| setproctitle = ["setproctitle"] | ||||
| tornado = ["tornado (>=0.2)"] | ||||
|  | ||||
| [[package]] | ||||
| name = "h11" | ||||
| version = "0.14.0" | ||||
| description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, | ||||
|     {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "html-tag-names" | ||||
| version = "0.1.2" | ||||
| @ -627,6 +660,23 @@ files = [ | ||||
|     {file = "regex-2022.10.31.tar.gz", hash = "sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83"}, | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "setuptools" | ||||
| version = "65.6.3" | ||||
| description = "Easily download, build, install, upgrade, and uninstall Python packages" | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "setuptools-65.6.3-py3-none-any.whl", hash = "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54"}, | ||||
|     {file = "setuptools-65.6.3.tar.gz", hash = "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75"}, | ||||
| ] | ||||
|  | ||||
| [package.extras] | ||||
| docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"] | ||||
| testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8 (<5)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pip-run (>=8.8)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] | ||||
| testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] | ||||
|  | ||||
| [[package]] | ||||
| name = "six" | ||||
| version = "1.16.0" | ||||
| @ -708,6 +758,25 @@ files = [ | ||||
|     {file = "tzdata-2022.7.tar.gz", hash = "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa"}, | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "uvicorn" | ||||
| version = "0.20.0" | ||||
| description = "The lightning-fast ASGI server." | ||||
| category = "main" | ||||
| optional = false | ||||
| python-versions = ">=3.7" | ||||
| files = [ | ||||
|     {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"}, | ||||
|     {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"}, | ||||
| ] | ||||
|  | ||||
| [package.dependencies] | ||||
| click = ">=7.0" | ||||
| h11 = ">=0.8" | ||||
|  | ||||
| [package.extras] | ||||
| standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] | ||||
|  | ||||
| [[package]] | ||||
| name = "werkzeug" | ||||
| version = "2.2.2" | ||||
| @ -745,4 +814,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" | ||||
| [metadata] | ||||
| lock-version = "2.0" | ||||
| python-versions = "^3.10" | ||||
| content-hash = "4e2d507e5549e97f894ebcaf0781c1fa54acf3444583510c36d3807e6c4761d9" | ||||
| content-hash = "fd85e51c8fb99824a433b451c9712b7418c13688b9eb0e8ca6c51768f544e48f" | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| [tool.poetry] | ||||
| name = "timetracker" | ||||
| version = "0.1.0" | ||||
| version = "0.1.4" | ||||
| description = "A simple time tracker." | ||||
| authors = ["Lukáš Kucharczyk <lukas@kucharczyk.xyz>"] | ||||
| license = "GPL" | ||||
| @ -9,6 +9,8 @@ readme = "README.md" | ||||
| [tool.poetry.dependencies] | ||||
| python = "^3.10" | ||||
| django = "^4.1.4" | ||||
| gunicorn = "^20.1.0" | ||||
| uvicorn = "^0.20.0" | ||||
|  | ||||
| [tool.poetry.group.dev.dependencies] | ||||
| black = "^22.12.0" | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| from django import template | ||||
| from django.conf import settings | ||||
| import time | ||||
| import os | ||||
|  | ||||
| @ -9,7 +10,11 @@ register = template.Library() | ||||
| def version_date(): | ||||
|     return time.strftime( | ||||
|         "%d-%b-%Y %H:%m", | ||||
|         time.gmtime(os.path.getmtime(os.path.abspath(os.path.join(".git")))), | ||||
|         time.gmtime( | ||||
|             os.path.getmtime( | ||||
|                 os.path.abspath(os.path.join(settings.BASE_DIR, "..", "..", ".git")) | ||||
|             ) | ||||
|         ), | ||||
|     ) | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -34,7 +34,6 @@ ALLOWED_HOSTS = ["*"] | ||||
|  | ||||
| INSTALLED_APPS = [ | ||||
|     "tracker.apps.TrackerConfig", | ||||
|     "django.contrib.admin", | ||||
|     "django.contrib.auth", | ||||
|     "django.contrib.contenttypes", | ||||
|     "django.contrib.sessions", | ||||
| @ -44,6 +43,7 @@ INSTALLED_APPS = [ | ||||
|  | ||||
| if DEBUG: | ||||
|     INSTALLED_APPS.append("django_extensions") | ||||
|     INSTALLED_APPS.append("django.contrib.admin") | ||||
|  | ||||
| MIDDLEWARE = [ | ||||
|     "django.middleware.security.SecurityMiddleware", | ||||
| @ -123,6 +123,7 @@ USE_TZ = True | ||||
| # https://docs.djangoproject.com/en/4.1/howto/static-files/ | ||||
|  | ||||
| STATIC_URL = "static/" | ||||
| STATIC_ROOT = BASE_DIR / "static" | ||||
|  | ||||
| # Default primary key field type | ||||
| # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field | ||||
| @ -144,7 +145,8 @@ LOGGING = { | ||||
|     }, | ||||
| } | ||||
|  | ||||
| _csrf_trusted_origins = os.environ.get("CSRF_TRUSTED_ORIGINS") | ||||
| if _csrf_trusted_origins: | ||||
|     CSRF_TRUSTED_ORIGINS = _csrf_trusted_origins.split(",") | ||||
| else: | ||||
|     CSRF_TRUSTED_ORIGINS = [] | ||||
|  | ||||
| if os.environ.get("PROD"): | ||||
|     CSRF_TRUSTED_ORIGINS.append(os.environ.get("CSRF_TRUSTED_ORIGINS")) | ||||
|  | ||||
| @ -16,10 +16,13 @@ Including another URLconf | ||||
| from django.contrib import admin | ||||
| from django.urls import include, path | ||||
| from django.views.generic import RedirectView | ||||
| from django.conf import settings | ||||
|  | ||||
|  | ||||
| urlpatterns = [ | ||||
|     path("admin/", admin.site.urls), | ||||
|     path("", RedirectView.as_view(url="/tracker/list-sessions")), | ||||
|     path("tracker/", include("tracker.urls")), | ||||
| ] | ||||
|  | ||||
| if settings.DEBUG: | ||||
|     urlpatterns.append(path("admin/", admin.site.urls)) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user