snapshot: preserve release checklist documentation

This commit is contained in:
Md Bayazid Bostame
2026-03-24 14:05:47 +01:00
parent f728f7134f
commit 8e2104c306
7 changed files with 355 additions and 12 deletions

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: tubco-portal\n" "Project-Id-Version: tubco-portal\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-24 12:58+0000\n" "POT-Creation-Date: 2026-03-24 13:05+0000\n"
"PO-Revision-Date: 2026-03-24 00:00+0000\n" "PO-Revision-Date: 2026-03-24 00:00+0000\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@@ -262,6 +262,43 @@ msgstr "deployment, security, and maintenance notes"
msgid "Open Developer Handbook" msgid "Open Developer Handbook"
msgstr "Open Developer Handbook" msgstr "Open Developer Handbook"
#: workflows/templates/workflows/handbook.html:67
#: workflows/templates/workflows/release_checklist.html:36
msgid "Release"
msgstr ""
#: workflows/templates/workflows/handbook.html:68
#: workflows/templates/workflows/release_checklist.html:7
#: workflows/templates/workflows/release_checklist.html:38
msgid "Release Checklist"
msgstr ""
#: workflows/templates/workflows/handbook.html:69
msgid ""
"Step-by-step release runbook for rebuilds, migrations, translations, static "
"assets, smoke checks, and rollout verification."
msgstr ""
#: workflows/templates/workflows/handbook.html:71
msgid "pre-release validation commands"
msgstr ""
#: workflows/templates/workflows/handbook.html:72
msgid "translation, static, and migration steps"
msgstr ""
#: workflows/templates/workflows/handbook.html:73
msgid "post-release smoke checks"
msgstr ""
#: workflows/templates/workflows/handbook.html:74
msgid "rollback and evidence checklist"
msgstr ""
#: workflows/templates/workflows/handbook.html:77
msgid "Open Release Checklist"
msgstr ""
#: workflows/templates/workflows/home.html:8 #: workflows/templates/workflows/home.html:8
#: workflows/templates/workflows/home.html:469 #: workflows/templates/workflows/home.html:469
#: workflows/templates/workflows/requests_dashboard.html:1118 #: workflows/templates/workflows/requests_dashboard.html:1118
@@ -915,6 +952,167 @@ msgstr "Generate live protocol"
msgid "Live-Protokoll öffnen" msgid "Live-Protokoll öffnen"
msgstr "Open live protocol" msgstr "Open live protocol"
#: workflows/templates/workflows/release_checklist.html:39
#, fuzzy
#| msgid "Back to Home"
msgid "Back to Handbook"
msgstr "Back to home"
#: workflows/templates/workflows/release_checklist.html:41
msgid ""
"Single runbook for preparing, validating, and evidencing a safe application "
"release. Use it for both local production-like rollouts and future CI/CD "
"handoffs."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:46
msgid "1. Pre-release checks"
msgstr ""
#: workflows/templates/workflows/release_checklist.html:48
msgid "Confirm git working tree is clean or intentionally scoped."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:49
msgid ""
"Read the latest Project Wiki and Developer Handbook updates for architecture "
"changes."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:50
msgid ""
"Check environment changes in .env.example and deployment secrets if "
"integrations changed."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:51
msgid ""
"If dependencies changed, rebuild web and worker images before validation."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:58
msgid "2. Validation commands"
msgstr ""
#: workflows/templates/workflows/release_checklist.html:60
msgid "Run Django system checks."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:61
msgid "Run tests or a targeted verification command for the changed area."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:62
msgid "Compile translations after UI/content changes."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:63
msgid "If dependencies changed, verify imports do not emit warnings."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:72
msgid "3. Data and asset steps"
msgstr ""
#: workflows/templates/workflows/release_checklist.html:74
msgid "Create and apply migrations if models changed."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:75
msgid "Run collectstatic if UI assets changed."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:76
msgid "Generate fresh PDFs if PDF templates or document logic changed."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:77
msgid "Confirm file outputs appear under backend/media/pdfs/."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:85
#, fuzzy
#| msgid "Integrationen"
msgid "4. Integration checks"
msgstr "Integrations"
#: workflows/templates/workflows/release_checklist.html:87
msgid "Verify the health endpoint returns status ok."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:88
msgid "Verify MailHog in test mode or SMTP in production mode."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:89
msgid "Verify Nextcloud upload if synchronization behavior changed."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:90
msgid ""
"Verify welcome-email scheduling or notification rules if email routing "
"changed."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:97
msgid "5. Release evidence"
msgstr ""
#: workflows/templates/workflows/release_checklist.html:99
msgid "Record which checks were run and their result."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:100
msgid "Take a snapshot commit before moving to the next change phase."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:101
msgid ""
"If a release introduces new operations or engineering behavior, update both "
"handbooks."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:102
msgid ""
"Keep at least one successful onboarding and one offboarding smoke example "
"during major workflow changes."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:107
msgid "6. Rollback basics"
msgstr ""
#: workflows/templates/workflows/release_checklist.html:109
msgid ""
"If rollout fails after code-only changes, redeploy the previous snapshot "
"commit."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:110
msgid ""
"If rollout includes schema changes, verify backward compatibility before "
"rollback."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:111
msgid ""
"If integrations fail, switch email mode/test settings conservatively before "
"wider retry."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:112
msgid ""
"Use logs from web and worker containers to isolate whether the issue is "
"request, task, or integration related."
msgstr ""
#: workflows/templates/workflows/release_checklist.html:119
msgid ""
"Project rule: German remains the primary/fallback language. English is "
"secondary. If a release adds new dynamic text, add the German source first "
"and then the English value."
msgstr ""
#: workflows/templates/workflows/requests_dashboard.html:899 #: workflows/templates/workflows/requests_dashboard.html:899
msgid "" msgid ""
"Steuert Onboarding- und Offboarding-Prozesse an einem Ort. Die Oberfläche " "Steuert Onboarding- und Offboarding-Prozesse an einem Ort. Die Oberfläche "
@@ -1230,45 +1428,45 @@ msgstr "Finish"
msgid "Notizen und Freigabe" msgid "Notizen und Freigabe"
msgstr "Notes and approval" msgstr "Notes and approval"
#: workflows/views.py:239 #: workflows/views.py:245
msgid "Sie haben keine Berechtigung für diese Aktion." msgid "Sie haben keine Berechtigung für diese Aktion."
msgstr "You do not have permission for this action." msgstr "You do not have permission for this action."
#: workflows/views.py:248 #: workflows/views.py:254
msgid "Keine Einträge ausgewählt." msgid "Keine Einträge ausgewählt."
msgstr "No entries selected." msgstr "No entries selected."
#: workflows/views.py:277 #: workflows/views.py:283
#, python-format #, python-format
msgid "%(count)s Eintrag/Einträge gelöscht." msgid "%(count)s Eintrag/Einträge gelöscht."
msgstr "%(count)s entry/entries deleted." msgstr "%(count)s entry/entries deleted."
#: workflows/views.py:279 #: workflows/views.py:285
#, python-format #, python-format
msgid "%(count)s Auswahl(en) konnten nicht verarbeitet werden." msgid "%(count)s Auswahl(en) konnten nicht verarbeitet werden."
msgstr "%(count)s selection(s) could not be processed." msgstr "%(count)s selection(s) could not be processed."
#: workflows/views.py:281 #: workflows/views.py:287
msgid "Keine passenden Einträge gefunden." msgid "Keine passenden Einträge gefunden."
msgstr "No matching entries found." msgstr "No matching entries found."
#: workflows/views.py:440 #: workflows/views.py:446
msgid "Einweisungs- und Übergabeprotokoll wurde erzeugt." msgid "Einweisungs- und Übergabeprotokoll wurde erzeugt."
msgstr "Introduction and handover protocol was generated." msgstr "Introduction and handover protocol was generated."
#: workflows/views.py:457 #: workflows/views.py:463
msgid "Einweisungsprotokoll aus Live-Status wurde erzeugt." msgid "Einweisungsprotokoll aus Live-Status wurde erzeugt."
msgstr "Introduction protocol from live status was generated." msgstr "Introduction protocol from live status was generated."
#: workflows/views.py:486 #: workflows/views.py:492
msgid "Einweisung wurde zurückgesetzt." msgid "Einweisung wurde zurückgesetzt."
msgstr "Introduction was reset." msgstr "Introduction was reset."
#: workflows/views.py:492 #: workflows/views.py:498
msgid "Einweisung wurde als abgeschlossen gespeichert." msgid "Einweisung wurde als abgeschlossen gespeichert."
msgstr "Introduction was saved as completed." msgstr "Introduction was saved as completed."
#: workflows/views.py:497 #: workflows/views.py:503
msgid "Einweisung wurde als Entwurf gespeichert." msgid "Einweisung wurde als Entwurf gespeichert."
msgstr "Introduction was saved as draft." msgstr "Introduction was saved as draft."

View File

@@ -194,6 +194,7 @@ docker compose exec -T web python manage.py run_staging_e2e_check</code></pre>
<li>Use <code>check</code> after model/view/template changes.</li> <li>Use <code>check</code> after model/view/template changes.</li>
<li>Use targeted shell checks for render validation when changing templates or routes.</li> <li>Use targeted shell checks for render validation when changing templates or routes.</li>
<li>Use real PDF generation tests when changing PDF templates or intro/offboarding document logic.</li> <li>Use real PDF generation tests when changing PDF templates or intro/offboarding document logic.</li>
<li>Use the dedicated Release Checklist page as the final go/no-go runbook before shipping changes.</li>
</ul> </ul>
<h2 id="deploy">12) Deployment and Release Checklist</h2> <h2 id="deploy">12) Deployment and Release Checklist</h2>

View File

@@ -13,7 +13,7 @@
.top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; } .top { display: flex; justify-content: space-between; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
h1 { margin: 0; color: #000078; font-size: 30px; } h1 { margin: 0; color: #000078; font-size: 30px; }
.sub { margin: 8px 0 18px; color: #5f6f85; max-width: 760px; } .sub { margin: 8px 0 18px; color: #5f6f85; max-width: 760px; }
.grid { display: grid; grid-template-columns: repeat(2, minmax(280px, 1fr)); gap: 14px; } .grid { display: grid; grid-template-columns: repeat(3, minmax(260px, 1fr)); gap: 14px; }
.card { border: 1px solid #d7e0ea; border-radius: 14px; background: #fcfdff; padding: 16px; } .card { border: 1px solid #d7e0ea; border-radius: 14px; background: #fcfdff; padding: 16px; }
.eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; } .eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; }
h2 { margin: 0 0 8px; color: #113a74; } h2 { margin: 0 0 8px; color: #113a74; }
@@ -62,6 +62,20 @@
<div class="actions"> <div class="actions">
<a class="btn btn-secondary" href="/admin-tools/developer-handbook/">{% trans "Open Developer Handbook" %}</a> <a class="btn btn-secondary" href="/admin-tools/developer-handbook/">{% trans "Open Developer Handbook" %}</a>
</div> </div>
<section class="card">
<div class="eyebrow">{% trans "Release" %}</div>
<h2>{% trans "Release Checklist" %}</h2>
<p>{% trans "Step-by-step release runbook for rebuilds, migrations, translations, static assets, smoke checks, and rollout verification." %}</p>
<ul>
<li>{% trans "pre-release validation commands" %}</li>
<li>{% trans "translation, static, and migration steps" %}</li>
<li>{% trans "post-release smoke checks" %}</li>
<li>{% trans "rollback and evidence checklist" %}</li>
</ul>
<div class="actions">
<a class="btn btn-secondary" href="/admin-tools/release-checklist/">{% trans "Open Release Checklist" %}</a>
</div>
</section> </section>
</div> </div>
</div> </div>

View File

@@ -196,6 +196,7 @@
<li><strong>Einweisungs- und Übergabeprotokoll:</strong> staff-only <code>PDF erzeugen</code>, <code>Neu erzeugen</code>, and <code>PDF öffnen</code> actions directly on onboarding rows in the Requests Dashboard.</li> <li><strong>Einweisungs- und Übergabeprotokoll:</strong> staff-only <code>PDF erzeugen</code>, <code>Neu erzeugen</code>, and <code>PDF öffnen</code> actions directly on onboarding rows in the Requests Dashboard.</li>
<li><strong>Einweisung durchführen:</strong> staff-only live checklist page opened from onboarding rows, with draft/completed status, notes, progress tracking, and a separate live-status PDF export.</li> <li><strong>Einweisung durchführen:</strong> staff-only live checklist page opened from onboarding rows, with draft/completed status, notes, progress tracking, and a separate live-status PDF export.</li>
<li><strong>Project Wiki:</strong> this documentation page.</li> <li><strong>Project Wiki:</strong> this documentation page.</li>
<li><strong>Release Checklist:</strong> dedicated staff-only release runbook for validation, rollout evidence, and rollback basics.</li>
</ul> </ul>
<h2 id="operations">10) Operations Runbook</h2> <h2 id="operations">10) Operations Runbook</h2>

View File

@@ -0,0 +1,122 @@
{% load static i18n %}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{% trans "Release Checklist" %}</title>
<link rel="stylesheet" href="{% static 'workflows/css/buttons.css' %}" />
<style>
body { margin: 0; font-family: Arial, sans-serif; background: #f4f8ff; color: #1b2b43; padding: 20px; }
.shell { max-width: 1120px; margin: 0 auto; }
.brand-logo { width: 190px; max-width: 100%; height: auto; margin: 0 0 10px; display: block; }
.hero, .panel { background: #fff; border: 1px solid #d7e0ea; border-radius: 16px; box-shadow: 0 20px 40px rgba(17, 58, 116, 0.08); }
.hero { padding: 20px; margin-bottom: 18px; }
.top { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
.eyebrow { display: inline-block; padding: 5px 10px; border-radius: 999px; background: #eef4ff; color: #244a8f; border: 1px solid #d5e2f9; font-size: 12px; font-weight: 700; margin-bottom: 10px; }
h1 { margin: 0; color: #000078; font-size: 30px; }
.sub { margin: 8px 0 0; color: #5f6f85; max-width: 820px; }
.grid { display: grid; grid-template-columns: repeat(2, minmax(320px, 1fr)); gap: 16px; }
.panel { padding: 18px; }
h2 { margin: 0 0 12px; color: #113a74; font-size: 20px; }
ol, ul { margin: 0; padding-left: 20px; }
li { margin: 8px 0; color: #334155; }
.checklist li { list-style: none; position: relative; padding-left: 28px; }
.checklist li::before { content: '\25A1'; position: absolute; left: 0; top: 0; color: #66758c; font-size: 16px; }
pre { margin: 12px 0 0; padding: 14px; border-radius: 12px; background: #f7faff; border: 1px solid #dfe8f4; overflow-x: auto; color: #16345f; }
code { font-family: Menlo, Monaco, Consolas, monospace; font-size: 13px; }
.note { margin-top: 16px; padding: 14px 16px; border-radius: 12px; background: #f7faff; border: 1px solid #dfe8f4; color: #355175; }
@media (max-width: 820px) { .grid { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<div class="shell">
<img class="brand-logo" src="{% static 'workflows/img/tubco-logo.svg' %}" alt="TUB/CO Logo" />
<section class="hero">
<div class="eyebrow">{% trans "Release" %}</div>
<div class="top">
<h1>{% trans "Release Checklist" %}</h1>
<a class="btn btn-secondary" href="/admin-tools/handbook/">{% trans "Back to Handbook" %}</a>
</div>
<p class="sub">{% trans "Single runbook for preparing, validating, and evidencing a safe application release. Use it for both local production-like rollouts and future CI/CD handoffs." %}</p>
</section>
<div class="grid">
<section class="panel">
<h2>{% trans "1. Pre-release checks" %}</h2>
<ul class="checklist">
<li>{% trans "Confirm git working tree is clean or intentionally scoped." %}</li>
<li>{% trans "Read the latest Project Wiki and Developer Handbook updates for architecture changes." %}</li>
<li>{% trans "Check environment changes in .env.example and deployment secrets if integrations changed." %}</li>
<li>{% trans "If dependencies changed, rebuild web and worker images before validation." %}</li>
</ul>
<pre><code>git status --short
docker compose up -d --build web worker</code></pre>
</section>
<section class="panel">
<h2>{% trans "2. Validation commands" %}</h2>
<ul class="checklist">
<li>{% trans "Run Django system checks." %}</li>
<li>{% trans "Run tests or a targeted verification command for the changed area." %}</li>
<li>{% trans "Compile translations after UI/content changes." %}</li>
<li>{% trans "If dependencies changed, verify imports do not emit warnings." %}</li>
</ul>
<pre><code>docker compose exec -T web python manage.py check
docker compose exec -T web python manage.py test
make i18n-compile
docker compose exec -T web python -c "import requests"</code></pre>
</section>
<section class="panel">
<h2>{% trans "3. Data and asset steps" %}</h2>
<ul class="checklist">
<li>{% trans "Create and apply migrations if models changed." %}</li>
<li>{% trans "Run collectstatic if UI assets changed." %}</li>
<li>{% trans "Generate fresh PDFs if PDF templates or document logic changed." %}</li>
<li>{% trans "Confirm file outputs appear under backend/media/pdfs/." %}</li>
</ul>
<pre><code>docker compose exec -T web python manage.py makemigrations
docker compose exec -T web python manage.py migrate
docker compose exec -T web python manage.py collectstatic --noinput</code></pre>
</section>
<section class="panel">
<h2>{% trans "4. Integration checks" %}</h2>
<ul class="checklist">
<li>{% trans "Verify the health endpoint returns status ok." %}</li>
<li>{% trans "Verify MailHog in test mode or SMTP in production mode." %}</li>
<li>{% trans "Verify Nextcloud upload if synchronization behavior changed." %}</li>
<li>{% trans "Verify welcome-email scheduling or notification rules if email routing changed." %}</li>
</ul>
<pre><code>curl --max-time 8 http://127.0.0.1:8088/healthz/
docker compose exec -T web python manage.py run_staging_e2e_check</code></pre>
</section>
<section class="panel">
<h2>{% trans "5. Release evidence" %}</h2>
<ul class="checklist">
<li>{% trans "Record which checks were run and their result." %}</li>
<li>{% trans "Take a snapshot commit before moving to the next change phase." %}</li>
<li>{% trans "If a release introduces new operations or engineering behavior, update both handbooks." %}</li>
<li>{% trans "Keep at least one successful onboarding and one offboarding smoke example during major workflow changes." %}</li>
</ul>
</section>
<section class="panel">
<h2>{% trans "6. Rollback basics" %}</h2>
<ul class="checklist">
<li>{% trans "If rollout fails after code-only changes, redeploy the previous snapshot commit." %}</li>
<li>{% trans "If rollout includes schema changes, verify backward compatibility before rollback." %}</li>
<li>{% trans "If integrations fail, switch email mode/test settings conservatively before wider retry." %}</li>
<li>{% trans "Use logs from web and worker containers to isolate whether the issue is request, task, or integration related." %}</li>
</ul>
<pre><code>docker compose logs --no-color --tail=200 web
docker compose logs --no-color --tail=200 worker</code></pre>
</section>
</div>
<div class="note">{% trans "Project rule: German remains the primary/fallback language. English is secondary. If a release adds new dynamic text, add the German source first and then the English value." %}</div>
</div>
</body>
</html>

View File

@@ -30,6 +30,7 @@ urlpatterns = [
path('admin-tools/handbook/', views.handbook_page, name='handbook_page'), path('admin-tools/handbook/', views.handbook_page, name='handbook_page'),
path('admin-tools/wiki/', views.project_wiki_page, name='project_wiki_page'), path('admin-tools/wiki/', views.project_wiki_page, name='project_wiki_page'),
path('admin-tools/developer-handbook/', views.developer_handbook_page, name='developer_handbook_page'), path('admin-tools/developer-handbook/', views.developer_handbook_page, name='developer_handbook_page'),
path('admin-tools/release-checklist/', views.release_checklist_page, name='release_checklist_page'),
path('admin-tools/form-builder/', views.form_builder_page, name='form_builder_page'), path('admin-tools/form-builder/', views.form_builder_page, name='form_builder_page'),
path('admin-tools/form-builder/save-order/', views.form_builder_save_order, name='form_builder_save_order'), path('admin-tools/form-builder/save-order/', views.form_builder_save_order, name='form_builder_save_order'),
path('admin-tools/intro-builder/', views.intro_builder_page, name='intro_builder_page'), path('admin-tools/intro-builder/', views.intro_builder_page, name='intro_builder_page'),

View File

@@ -232,6 +232,12 @@ def developer_handbook_page(request):
return render(request, 'workflows/developer_handbook.html') return render(request, 'workflows/developer_handbook.html')
@login_required
@user_passes_test(_is_staff)
def release_checklist_page(request):
return render(request, 'workflows/release_checklist.html')
@login_required @login_required
def requests_dashboard(request): def requests_dashboard(request):
if request.method == 'POST': if request.method == 'POST':