Compare commits

...

13 Commits

99 changed files with 12380 additions and 15487 deletions

View File

@ -11,6 +11,7 @@ permissions:
jobs:
tests:
name: Test
uses: ./.github/workflows/test.yaml
push_to_registry:
name: Push Docker image to Docker Hub
@ -50,4 +51,4 @@ jobs:
max_attempts: 5
retry_wait_seconds: 2
warning_on_retry: false
command: curl -sSL --fail -m 10 https://checkout.augendre.info | grep ${GITHUB_SHA::7} > /dev/null
command: curl -sSL --fail -m 10 https://checkout.augendre.info/ping/ | grep ${GITHUB_SHA::7} > /dev/null

View File

@ -23,6 +23,8 @@ jobs:
run: |
pip install pip-tools
pip-sync requirements.txt requirements-dev.txt
sudo apt-get update
sudo apt-get install -y --no-install-recommends gettext
- name: Setup pre-commit cache
uses: actions/cache@v3
with:
@ -31,5 +33,5 @@ jobs:
- name: Check pre-commit
run: pre-commit run --show-diff-on-failure --color=always --all-files
- name: Test
run: pytest --cov=. --cov-branch --cov-report term-missing:skip-covered
run: inv test-cov
working-directory: ./src/

View File

@ -28,7 +28,8 @@ RUN useradd -M -d /app -u 1000 -g 1000 -s /bin/bash django
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends \
libxml2 \
media-types
media-types \
gettext
# Fetch project requirements
##############################################
@ -52,6 +53,7 @@ ENV DB_BASE_DIR "/app/db"
RUN python -m pip install --no-cache-dir -r requirements.txt
WORKDIR /app/src
RUN python manage.py collectstatic --noinput --clear
RUN python manage.py compilemessages -l fr -l en
EXPOSE 8000

View File

@ -2,10 +2,16 @@
Simple interface to register baskets.
## Development
## Quick start
Clone, then
```shell
inv test-cov
inv beam
pip install -U pip pip-tools invoke
inv sync-dependencies
pre-commit install --install-hooks
inv test
./src/manage.py migrate
./src/manage.py generat_dummy_baskets
./src/manage.py createsuperuser
```
# Reuse

View File

@ -55,7 +55,6 @@ EMAIL_TIMEOUT = 30
ANYMAIL = {
"MAILGUN_API_KEY": env("MAILGUN_API_KEY"),
"MAILGUN_SENDER_DOMAIN": env("MAILGUN_SENDER_DOMAIN"),
"MAILGUN_API_URL": "https://api.eu.mailgun.net/v3",
}
EMAIL_BACKEND = "anymail.backends.mailgun.EmailBackend"
@ -129,6 +128,7 @@ TEMPLATES = [
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"common.context_processors.app",
],
},
},
@ -228,3 +228,26 @@ CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5"
MESSAGE_TAGS = {messages.ERROR: "danger"}
APP = {
"build": {
"date": "latest-date",
"commit": "latest-commit",
"describe": "latest-describe",
},
}
try:
with Path("/app/git/build-date").open() as f:
APP["build"]["date"] = f.read().strip()
except Exception: # noqa: S110
pass
try:
with Path("/app/git/git-commit").open() as f:
APP["build"]["commit"] = f.read().strip()
except Exception: # noqa: S110
pass
try:
with Path("/app/git/git-describe").open() as f:
APP["build"]["describe"] = f.read().strip()
except Exception: # noqa: S110
pass

View File

@ -0,0 +1,5 @@
from django.conf import settings
def app(_):
return settings.APP

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,8 @@
/*!
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Bootstrap Reboot v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors
* Copyright 2011-2022 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
@ -16,6 +15,7 @@
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
@ -48,7 +48,7 @@
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
@ -57,6 +57,20 @@
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-2xl: 2rem;
--bs-border-radius-pill: 50rem;
--bs-link-color: #0d6efd;
--bs-link-hover-color: #0a58ca;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
}
*,
@ -87,15 +101,11 @@ body {
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
border-top: 1px solid;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
@ -152,8 +162,7 @@ p {
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
@ -209,8 +218,8 @@ small {
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
@ -230,11 +239,11 @@ sup {
}
a {
color: #0d6efd;
color: var(--bs-link-color);
text-decoration: underline;
}
a:hover {
color: #0a58ca;
color: var(--bs-link-hover-color);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
@ -248,8 +257,6 @@ kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr /* rtl:ignore */;
unicode-bidi: bidi-override;
}
pre {
@ -267,7 +274,7 @@ pre code {
code {
font-size: 0.875em;
color: #d63384;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
@ -275,16 +282,15 @@ a > code {
}
kbd {
padding: 0.2rem 0.4rem;
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
@ -363,8 +369,8 @@ select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
@ -450,14 +456,11 @@ legend + * {
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,9 +1,8 @@
/*!
* Bootstrap Reboot v5.1.3 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Bootstrap Reboot v5.2.3 (https://getbootstrap.com/)
* Copyright 2011-2022 The Bootstrap Authors
* Copyright 2011-2022 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
:root {
--bs-blue: #0d6efd;
@ -16,6 +15,7 @@
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
@ -48,7 +48,7 @@
--bs-black-rgb: 0, 0, 0;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg-rgb: 255, 255, 255;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
@ -57,6 +57,20 @@
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-bg: #fff;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-2xl: 2rem;
--bs-border-radius-pill: 50rem;
--bs-link-color: #0d6efd;
--bs-link-hover-color: #0a58ca;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
}
*,
@ -87,15 +101,11 @@ body {
hr {
margin: 1rem 0;
color: inherit;
background-color: currentColor;
border: 0;
border-top: 1px solid;
opacity: 0.25;
}
hr:not([size]) {
height: 1px;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
@ -152,8 +162,7 @@ p {
margin-bottom: 1rem;
}
abbr[title],
abbr[data-bs-original-title] {
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
@ -209,8 +218,8 @@ small {
}
mark {
padding: 0.2em;
background-color: #fcf8e3;
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
@ -230,11 +239,11 @@ sup {
}
a {
color: #0d6efd;
color: var(--bs-link-color);
text-decoration: underline;
}
a:hover {
color: #0a58ca;
color: var(--bs-link-hover-color);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
@ -248,8 +257,6 @@ kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
direction: ltr ;
unicode-bidi: bidi-override;
}
pre {
@ -267,7 +274,7 @@ pre code {
code {
font-size: 0.875em;
color: #d63384;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
@ -275,16 +282,15 @@ a > code {
}
kbd {
padding: 0.2rem 0.4rem;
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: #fff;
background-color: #212529;
border-radius: 0.2rem;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
font-weight: 700;
}
figure {
@ -363,8 +369,8 @@ select:disabled {
opacity: 1;
}
[list]::-webkit-calendar-picker-indicator {
display: none;
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
@ -448,14 +454,11 @@ legend + * {
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Checkout</title>
<link href="{% static "vendor/bootstrap-5.1.3-dist/css/bootstrap.min.css" %}"
<link href="{% static "vendor/bootstrap-5.2.3-dist/css/bootstrap.min.css" %}"
rel="stylesheet">
<style>
body {
@ -13,9 +13,9 @@
touch-action: manipulation;
}
</style>
<script defer src="{% static "vendor/fontawesome-6.1.1-free/brands.min.js" %}"></script>
<script defer src="{% static "vendor/fontawesome-6.1.1-free/solid.min.js" %}"></script>
<script defer src="{% static "vendor/fontawesome-6.1.1-free/fontawesome.min.js" %}"></script>
<script defer src="{% static "vendor/fontawesome-6.3.0-free/brands.min.js" %}"></script>
<script defer src="{% static "vendor/fontawesome-6.3.0-free/solid.min.js" %}"></script>
<script defer src="{% static "vendor/fontawesome-6.3.0-free/fontawesome.min.js" %}"></script>
{% block extrahead %}
{% endblock %}
@ -27,7 +27,7 @@
{% block content %}
{% endblock %}
</div>
<script src="{% static "vendor/bootstrap-5.1.3-dist/js/bootstrap.bundle.min.js" %}"></script>
<script src="{% static "vendor/bootstrap-5.2.3-dist/js/bootstrap.bundle.min.js" %}"></script>
{% block extrascript %}
{% endblock %}
</body>

View File

@ -0,0 +1,10 @@
{% extends "common/base.html" %}
{% block content %}
<h1>Ping</h1>
<h2>Versions</h2>
<ul>
<li>Build date: {{ build.date }}</li>
<li>Commit: {{ build.commit }}</li>
<li>Version: {{ build.describe }}</li>
</ul>
{% endblock %}

View File

@ -1,8 +1,10 @@
from django.urls import path
from common.views import home
from common import views
app_name = "common"
urlpatterns = [
path("", home, name="home"),
path("error_check/", views.error_check, name="error_check"),
path("ping/", views.ping, name="ping"),
path("", views.home, name="home"),
]

View File

@ -1,5 +1,14 @@
from django.shortcuts import redirect
from django.shortcuts import redirect, render
def home(_request):
return redirect("purchase:new")
def ping(request):
return render(request, "common/ping.html", {})
def error_check(_request):
msg = "Error check"
raise ValueError(msg)

View File

@ -22,4 +22,5 @@ def firefox_options(firefox_options):
@pytest.fixture()
def selenium(selenium):
selenium.implicitly_wait(3)
selenium.set_window_size(3860, 2140)
return selenium

View File

@ -45,7 +45,8 @@ class Command(BaseCommand):
items_in_basket = len(products)
if items_in_basket < 1:
items_in_basket = 1
selected_products = np.random.Generator(
rng = np.random.default_rng()
selected_products = rng.choice(
products,
size=items_in_basket,
replace=False,

View File

@ -41,6 +41,6 @@
{% endblock %}
{% block extrascript %}
<script src="{% static 'vendor/htmx-1.8.0/htmx.min.js' %}" defer></script>
<script src="{% static 'vendor/htmx-1.8.6/htmx.min.js' %}" defer></script>
{% django_htmx_script %}
{% endblock %}

View File

@ -57,13 +57,13 @@ def compilemessages(ctx: Context) -> None:
ctx.run("./manage.py compilemessages -l en -l fr", pty=True, echo=True)
@task
@task(pre=[compilemessages])
def test(ctx: Context) -> None:
with ctx.cd(SRC_DIR):
ctx.run("pytest", pty=True, echo=True)
@task
@task(pre=[compilemessages])
def test_cov(ctx: Context) -> None:
with ctx.cd(SRC_DIR):
ctx.run(