You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
5.3 KiB
157 lines
5.3 KiB
cd /home/def/otb_billing || exit 1 |
|
set -e |
|
|
|
STAMP="$(date +%Y%m%d-%H%M%S)" |
|
NEW_VERSION="v0.6.0" |
|
ZIP_NAME="otb_billing-${NEW_VERSION}.zip" |
|
|
|
echo "===== backups =====" |
|
cp VERSION "VERSION.bak.${STAMP}" |
|
cp README.md "README.md.bak.${STAMP}" |
|
cp PROJECT_STATE.md "PROJECT_STATE.md.bak.${STAMP}" |
|
|
|
echo "===== version bump =====" |
|
printf '%s\n' "${NEW_VERSION}" > VERSION |
|
|
|
echo "===== update README + PROJECT_STATE =====" |
|
python3 <<'PY' |
|
from pathlib import Path |
|
from datetime import datetime, timezone |
|
|
|
root = Path("/home/def/otb_billing") |
|
version = "v0.6.0" |
|
stamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
utc_stamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC") |
|
|
|
readme = root / "README.md" |
|
project_state = root / "PROJECT_STATE.md" |
|
|
|
readme_text = readme.read_text() if readme.exists() else "" |
|
project_text = project_state.read_text() if project_state.exists() else "" |
|
|
|
readme_entry = f"""## {version} - {stamp} |
|
|
|
### Highlights |
|
- Added authenticated `/portal/services` page as a new service hub inside the billing portal. |
|
- Added modular route file `backend/routes/portal_services.py` instead of expanding the main app with another large inline route block. |
|
- Added shared `templates/portal_base.html` layout using Jinja `{% extends %}` / block pattern. |
|
- Converted portal pages to the shared base-template structure for cleaner reuse and consistent branding. |
|
- Added branded service cards for: |
|
- Follow-me Tracker |
|
- Video Rendering / Streaming |
|
- Miner Rentals |
|
- Fixed portal services layout so it uses the same nav, footer, styling, and light/dark toggle behavior as the working portal/dashboard pages. |
|
- Corrected the Follow-me service link to use the real external service domain. |
|
- Updated service launch buttons so external services open in a new tab. |
|
- Improved portal services identity display to prepare for showing real logged-in client identity instead of a generic placeholder. |
|
|
|
### Notes |
|
- This is the first successful rollout of the reusable `portal_base.html` structure and it should be used for future portal pages and future project builds. |
|
- This release establishes the billing portal as the launch point for OTB services. |
|
|
|
""" |
|
|
|
project_entry = f"""# Project State Update - {version} |
|
Updated: {utc_stamp} |
|
|
|
## Current Version |
|
{version} |
|
|
|
## Current Status |
|
OTB Billing has been advanced from a billing-only portal toward a unified service-launch platform. |
|
|
|
## Completed This Session |
|
- Created `/portal/services` authenticated service hub. |
|
- Added modular route file: `backend/routes/portal_services.py` |
|
- Added shared Jinja portal base template: `templates/portal_base.html` |
|
- Converted: |
|
- `templates/portal_dashboard.html` |
|
- `templates/portal/services_here.html` |
|
to the new shared base-template architecture. |
|
- Restored consistent OTB branding, nav, footer, spacing, and dark/light toggle behavior on the services page. |
|
- Added service cards for: |
|
- Follow-me Tracker (active/beta) |
|
- Video Rendering / Streaming (coming soon) |
|
- Miner Rentals (coming soon) |
|
- Fixed service routing so Follow-me points to the real service domain. |
|
- Updated external service launch links to open in a new tab. |
|
- Confirmed the new shared template architecture is successful and should be reused in future pages/projects. |
|
|
|
## Architectural Direction |
|
The portal now has a proven reusable pattern: |
|
- `templates/portal_base.html` |
|
- child templates using `{{% extends "portal_base.html" %}}` |
|
- focused page content blocks instead of duplicating full HTML shell on each page |
|
|
|
This is now the preferred portal/page structure going forward. |
|
|
|
## Next Logical Steps |
|
- Unify logged-in client identity handling across portal routes. |
|
- Add real service-aware handoff / account linkage for Follow-me. |
|
- Add future service cards/pages without duplicating layout shell. |
|
- Move page-specific inline service-card CSS into shared stylesheet when ready. |
|
|
|
""" |
|
|
|
def prepend_once(existing: str, new_block: str, marker: str) -> str: |
|
if marker in existing: |
|
return existing |
|
if existing.startswith("# "): |
|
return existing.rstrip() + "\n\n" + new_block |
|
return new_block + existing |
|
|
|
readme.write_text(prepend_once(readme_text, readme_entry, f"## {version} - ")) |
|
project_state.write_text(prepend_once(project_text, project_entry, f"# Project State Update - {version}")) |
|
PY |
|
|
|
echo "===== build full zip snapshot =====" |
|
rm -f "releases/${ZIP_NAME}" |
|
mkdir -p releases |
|
|
|
python3 <<'PY' |
|
from pathlib import Path |
|
import zipfile |
|
|
|
root = Path("/home/def/otb_billing") |
|
zip_path = root / "releases" / "otb_billing-v0.6.0.zip" |
|
|
|
exclude_parts = { |
|
".git", |
|
"__pycache__", |
|
".pytest_cache", |
|
} |
|
|
|
exclude_suffixes = { |
|
".pyc", |
|
".pyo", |
|
} |
|
|
|
with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: |
|
for path in root.rglob("*"): |
|
rel = path.relative_to(root) |
|
if any(part in exclude_parts for part in rel.parts): |
|
continue |
|
if path.suffix in exclude_suffixes: |
|
continue |
|
if path == zip_path: |
|
continue |
|
zf.write(path, arcname=str(Path("otb_billing-v0.6.0") / rel)) |
|
print(zip_path) |
|
PY |
|
|
|
echo "===== quick verify =====" |
|
echo |
|
echo "--- VERSION ---" |
|
cat VERSION |
|
echo |
|
echo "--- README.md top 40 ---" |
|
sed -n '1,40p' README.md |
|
echo |
|
echo "--- PROJECT_STATE.md top 60 ---" |
|
sed -n '1,60p' PROJECT_STATE.md |
|
echo |
|
echo "--- ZIP snapshot ---" |
|
ls -lh "releases/${ZIP_NAME}" |
|
echo |
|
echo "===== optional git review =====" |
|
git status --short
|
|
|