FossilRepo
Fix collectstatic in Docker build: set build-time env vars
Commit
2cb9ca6b5196cbc2a3a66e064392f934b74a6ff7bad1345068330ed659f9f3c4
Parent
738997c4cbb3815…
4 files changed
+1
-1
+22
+1
+3
+1
-1
| --- Dockerfile | ||
| +++ Dockerfile | ||
| @@ -40,11 +40,11 @@ | ||
| 40 | 40 | COPY pyproject.toml ./ |
| 41 | 41 | RUN uv pip install --system --no-cache -r pyproject.toml |
| 42 | 42 | |
| 43 | 43 | COPY . . |
| 44 | 44 | |
| 45 | -RUN python manage.py collectstatic --noinput 2>/dev/null || true | |
| 45 | +RUN DJANGO_SECRET_KEY=build-placeholder DJANGO_DEBUG=true python manage.py collectstatic --noinput | |
| 46 | 46 | |
| 47 | 47 | # Create data directory for .fossil files |
| 48 | 48 | RUN mkdir -p /data/repos /data/trash |
| 49 | 49 | |
| 50 | 50 | ENV PYTHONUNBUFFERED=1 |
| 51 | 51 | |
| 52 | 52 | ADDED fossil/chat.py |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -40,11 +40,11 @@ | |
| 40 | COPY pyproject.toml ./ |
| 41 | RUN uv pip install --system --no-cache -r pyproject.toml |
| 42 | |
| 43 | COPY . . |
| 44 | |
| 45 | RUN python manage.py collectstatic --noinput 2>/dev/null || true |
| 46 | |
| 47 | # Create data directory for .fossil files |
| 48 | RUN mkdir -p /data/repos /data/trash |
| 49 | |
| 50 | ENV PYTHONUNBUFFERED=1 |
| 51 | |
| 52 | DDED fossil/chat.py |
| --- Dockerfile | |
| +++ Dockerfile | |
| @@ -40,11 +40,11 @@ | |
| 40 | COPY pyproject.toml ./ |
| 41 | RUN uv pip install --system --no-cache -r pyproject.toml |
| 42 | |
| 43 | COPY . . |
| 44 | |
| 45 | RUN DJANGO_SECRET_KEY=build-placeholder DJANGO_DEBUG=true python manage.py collectstatic --noinput |
| 46 | |
| 47 | # Create data directory for .fossil files |
| 48 | RUN mkdir -p /data/repos /data/trash |
| 49 | |
| 50 | ENV PYTHONUNBUFFERED=1 |
| 51 | |
| 52 | DDED fossil/chat.py |
+22
| --- a/fossil/chat.py | ||
| +++ b/fossil/chat.py | ||
| @@ -0,0 +1,22 @@ | ||
| 1 | +"""Per-project chat backed by Django models. | |
| 2 | + | |
| 3 | +Simple real-time-ish chat using HTMX polling. Messages stored in PostgreSQL. | |
| 4 | +""" | |
| 5 | + | |
| 6 | +from django.contrib.auth.models import User | |
| 7 | +from django.db import models | |
| 8 | + | |
| 9 | + | |
| 10 | +class ChatMessage(models.Model): | |
| 11 | + """A chat message in a project chatroom.""" | |
| 12 | + | |
| 13 | + project = models.ForeignKey("projects.Project", on_delete=models.CASCADE, related_name="chat_messages") | |
| 14 | + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="chat_messages") | |
| 15 | + message = models.TextField() | |
| 16 | + created_at = models.DateTimeField(auto_now_add=True) | |
| 17 | + | |
| 18 | + class Meta: | |
| 19 | + ordering = ["created_at"] | |
| 20 | + | |
| 21 | + def __str__(self): | |
| 22 | + return f"{self.user.username}: {self.message[:50]}" |
| --- a/fossil/chat.py | |
| +++ b/fossil/chat.py | |
| @@ -0,0 +1,22 @@ | |
| --- a/fossil/chat.py | |
| +++ b/fossil/chat.py | |
| @@ -0,0 +1,22 @@ | |
| 1 | """Per-project chat backed by Django models. |
| 2 | |
| 3 | Simple real-time-ish chat using HTMX polling. Messages stored in PostgreSQL. |
| 4 | """ |
| 5 | |
| 6 | from django.contrib.auth.models import User |
| 7 | from django.db import models |
| 8 | |
| 9 | |
| 10 | class ChatMessage(models.Model): |
| 11 | """A chat message in a project chatroom.""" |
| 12 | |
| 13 | project = models.ForeignKey("projects.Project", on_delete=models.CASCADE, related_name="chat_messages") |
| 14 | user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="chat_messages") |
| 15 | message = models.TextField() |
| 16 | created_at = models.DateTimeField(auto_now_add=True) |
| 17 | |
| 18 | class Meta: |
| 19 | ordering = ["created_at"] |
| 20 | |
| 21 | def __str__(self): |
| 22 | return f"{self.user.username}: {self.message[:50]}" |
+1
| --- fossil/models.py | ||
| +++ fossil/models.py | ||
| @@ -65,7 +65,8 @@ | ||
| 65 | 65 | def __str__(self): |
| 66 | 66 | return f"{self.repository.filename} @ {self.created_at:%Y-%m-%d %H:%M}" if self.created_at else self.repository.filename |
| 67 | 67 | |
| 68 | 68 | |
| 69 | 69 | # Import related models so they're discoverable by Django |
| 70 | +from fossil.chat import ChatMessage # noqa: E402, F401 | |
| 70 | 71 | from fossil.notifications import Notification, ProjectWatch # noqa: E402, F401 |
| 71 | 72 | from fossil.sync_models import GitMirror, SSHKey, SyncLog # noqa: E402, F401 |
| 72 | 73 |
| --- fossil/models.py | |
| +++ fossil/models.py | |
| @@ -65,7 +65,8 @@ | |
| 65 | def __str__(self): |
| 66 | return f"{self.repository.filename} @ {self.created_at:%Y-%m-%d %H:%M}" if self.created_at else self.repository.filename |
| 67 | |
| 68 | |
| 69 | # Import related models so they're discoverable by Django |
| 70 | from fossil.notifications import Notification, ProjectWatch # noqa: E402, F401 |
| 71 | from fossil.sync_models import GitMirror, SSHKey, SyncLog # noqa: E402, F401 |
| 72 |
| --- fossil/models.py | |
| +++ fossil/models.py | |
| @@ -65,7 +65,8 @@ | |
| 65 | def __str__(self): |
| 66 | return f"{self.repository.filename} @ {self.created_at:%Y-%m-%d %H:%M}" if self.created_at else self.repository.filename |
| 67 | |
| 68 | |
| 69 | # Import related models so they're discoverable by Django |
| 70 | from fossil.chat import ChatMessage # noqa: E402, F401 |
| 71 | from fossil.notifications import Notification, ProjectWatch # noqa: E402, F401 |
| 72 | from fossil.sync_models import GitMirror, SSHKey, SyncLog # noqa: E402, F401 |
| 73 |
+3
| --- fossil/urls.py | ||
| +++ fossil/urls.py | ||
| @@ -37,10 +37,13 @@ | ||
| 37 | 37 | path("sync/git/callback/gitlab/", views.oauth_gitlab_callback, name="oauth_gitlab_callback"), |
| 38 | 38 | path("code/raw/<path:filepath>", views.code_raw, name="code_raw"), |
| 39 | 39 | path("code/blame/<path:filepath>", views.code_blame, name="code_blame"), |
| 40 | 40 | path("code/history/<path:filepath>", views.file_history, name="file_history"), |
| 41 | 41 | path("watch/", views.toggle_watch, name="toggle_watch"), |
| 42 | + path("chat/", views.chat_room, name="chat"), | |
| 43 | + path("chat/messages/", views.chat_messages, name="chat_messages"), | |
| 44 | + path("chat/send/", views.chat_send, name="chat_send"), | |
| 42 | 45 | path("timeline/rss/", views.timeline_rss, name="timeline_rss"), |
| 43 | 46 | path("tickets/export/", views.tickets_csv, name="tickets_csv"), |
| 44 | 47 | path("docs/", views.fossil_docs, name="docs"), |
| 45 | 48 | path("docs/<path:doc_path>", views.fossil_doc_page, name="doc_page"), |
| 46 | 49 | ] |
| 47 | 50 |
| --- fossil/urls.py | |
| +++ fossil/urls.py | |
| @@ -37,10 +37,13 @@ | |
| 37 | path("sync/git/callback/gitlab/", views.oauth_gitlab_callback, name="oauth_gitlab_callback"), |
| 38 | path("code/raw/<path:filepath>", views.code_raw, name="code_raw"), |
| 39 | path("code/blame/<path:filepath>", views.code_blame, name="code_blame"), |
| 40 | path("code/history/<path:filepath>", views.file_history, name="file_history"), |
| 41 | path("watch/", views.toggle_watch, name="toggle_watch"), |
| 42 | path("timeline/rss/", views.timeline_rss, name="timeline_rss"), |
| 43 | path("tickets/export/", views.tickets_csv, name="tickets_csv"), |
| 44 | path("docs/", views.fossil_docs, name="docs"), |
| 45 | path("docs/<path:doc_path>", views.fossil_doc_page, name="doc_page"), |
| 46 | ] |
| 47 |
| --- fossil/urls.py | |
| +++ fossil/urls.py | |
| @@ -37,10 +37,13 @@ | |
| 37 | path("sync/git/callback/gitlab/", views.oauth_gitlab_callback, name="oauth_gitlab_callback"), |
| 38 | path("code/raw/<path:filepath>", views.code_raw, name="code_raw"), |
| 39 | path("code/blame/<path:filepath>", views.code_blame, name="code_blame"), |
| 40 | path("code/history/<path:filepath>", views.file_history, name="file_history"), |
| 41 | path("watch/", views.toggle_watch, name="toggle_watch"), |
| 42 | path("chat/", views.chat_room, name="chat"), |
| 43 | path("chat/messages/", views.chat_messages, name="chat_messages"), |
| 44 | path("chat/send/", views.chat_send, name="chat_send"), |
| 45 | path("timeline/rss/", views.timeline_rss, name="timeline_rss"), |
| 46 | path("tickets/export/", views.tickets_csv, name="tickets_csv"), |
| 47 | path("docs/", views.fossil_docs, name="docs"), |
| 48 | path("docs/<path:doc_path>", views.fossil_doc_page, name="doc_page"), |
| 49 | ] |
| 50 |