Compare commits

...

13 Commits

@ -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

@ -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/

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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>

@ -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 %}

@ -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"),
]

@ -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)

@ -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

@ -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,

@ -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 %}

@ -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(

Loading…
Cancel
Save