Files
BrowserOS/packages/browseros/build/common/notify.py
Nikhil 24e9cfd8f2 chromium 142 upgrade, new cli (#214)
* refactor 1: new typer based cli and browseros cli module

* refactor 2: fixes to context.py

* refactor 3: common/ and notify

* new sign and package module

* update .gitignore

* refactor 5: dev.py and modules for each

* refactor 6: clean-up old files

* refactor 7: organise modules fruther

* refactor 8: renaming nxtscape to browseros

* refactor 9: dev.py remove cli load

* fix: pyproject.toml

* fix: typer pretty exception disable

* refactor 10: cli/build.py set to primary

* refactor 10: cli/build.py set to primary, move OS detection

* refactor: context split, env and module dataclass

* reactor: clean and git moved ot new module type

* refactor: compile and configure

* reactor: sign and package module update

* refactor: new build.py cli

* 'refactor: remove reducant OS checks

* refactor: rename BuildContext to Context

* refactor: rename BuildModule to CommandModule

* refactor: dev.py to use the new modules

* build.py: improve help output

* remove old patching way

* clean-up: remove old build.py stuff

* refactor: move to proper yaml parsing

* clean-up: remove legacy args gating

* fix: patches issues

* fix: clean-up build.py and ars resolver

* minor: gitignore

* fix: patches.py issue

* support universal build

* fix: ENV variable and YAMLs

* fix: move compile to folder to avoid compflics

* fixes: more env fixes

* fix: build_type override in CLI fix

* fix: universal clean all archs before starting

* fix: universal build type constants

* fix: linter, extract options

* fix: linter

* fix: remove chromium_src as a not a conflicting flag

* fix: support chromium_src from cli in config mode

* fix: notify with better messages

* feat: new apply patch with --reset-to feature

* feat: refactor apply and extract into separate sub modules

* 142 patches working (#211)

* updates to build.py apply/patch

* removed all old patches

* 142 build update

* fix: get updated patches from main to 142

* fix: correct patches dir

* fix: import path

* add pyright

* fix: setup pyright

* fix: new updated patches from 137 rebased on 142

* feat: new extract_patch command

* fix: add mising side_panel build patch

* fix: extension uninstall for browseros

* fix: prefs fix

* fix: ota extension updater patch fix

* fix: llm hub and chat

* feat: unvisersal module also package individual archs

* fix: add browseros-server binaries

* fix: attach color for notify

* fix: attachment for slack

* fix: update chromium version to 142.0.7444.175

* feat: add new icons needed

* fix: disable settings in menu

* fix: uv add build-backend

* minor: chromium version bump

* clean-up: removed old files of extnesion and sidepanel

* fix: product logo generate and assets.car and appicon.icns

* feat: few chromium UI fixes

* fix: update features.yaml

* fix: features.yaml path in context

* refactor: rename to get_patches_dir()

* feat: show browserOS version in about page

* fix: copy browseros_version on the build time and rename other to offset

* bump offset

* fix: update features.yaml

* feat: load env from .env files too

* fix: enable split view

* clean-up: removed old prefs

* fix: minor import issue

* fix: linux flag update
2025-12-03 13:09:23 -08:00

165 lines
4.7 KiB
Python
Generated

#!/usr/bin/env python3
"""Notification system for BrowserOS build pipeline"""
import os
import threading
from typing import Optional, Dict, Any
# Slack attachment colors
COLOR_BLUE = "#2196F3"
COLOR_GREEN = "#4CAF50"
COLOR_RED = "#F44336"
# Build context (set once at pipeline start)
_build_context: Dict[str, str] = {}
def set_build_context(os_name: str, arch: str) -> None:
"""Set build context for all notifications"""
_build_context["os"] = os_name
_build_context["arch"] = arch
def _get_context_prefix() -> str:
"""Get [arch] prefix if context is set"""
if "arch" in _build_context:
return f"[{_build_context['arch']}] "
return ""
def _get_context_footer() -> str:
"""Get OS footer if context is set"""
if "os" in _build_context:
return f"BrowserOS Build System - {_build_context['os']}"
return "BrowserOS Build System"
class Notifier:
"""Fire-and-forget notification system"""
def __init__(self):
self.slack_webhook_url = os.environ.get("SLACK_WEBHOOK_URL")
self.enabled = bool(self.slack_webhook_url)
def notify(self, event: str, message: str, details: Optional[Dict[str, Any]] = None, color: str = "#36a64f") -> None:
"""Send notification asynchronously (fire-and-forget)"""
if not self.enabled:
return
# Fire and forget - run in background thread
thread = threading.Thread(
target=self._send_notification,
args=(event, message, details, color),
daemon=True
)
thread.start()
def _send_notification(self, event: str, message: str, details: Optional[Dict[str, Any]], color: str) -> None:
"""Internal method to send notification (runs in background thread)"""
try:
import requests
# Build footer text
footer = f"🍎 {_get_context_footer()}" if _build_context.get("os") == "macOS" \
else f"🪟 {_get_context_footer()}" if _build_context.get("os") == "Windows" \
else f"🐧 {_get_context_footer()}" if _build_context.get("os") == "Linux" \
else _get_context_footer()
# Use legacy attachment format for colored sidebar
attachment = {
"color": color,
"mrkdwn_in": ["text", "fields"],
"text": f"*{event}*\n{message}",
"footer": footer
}
if details:
attachment["fields"] = [
{"title": key, "value": str(value), "short": True}
for key, value in details.items()
]
payload = {"attachments": [attachment]}
requests.post(
self.slack_webhook_url,
json=payload,
timeout=5 # Quick timeout for fire-and-forget
)
except ImportError:
pass
except Exception:
pass
# Global notifier instance
_notifier = None
def get_notifier() -> Notifier:
"""Get global notifier instance"""
global _notifier
if _notifier is None:
_notifier = Notifier()
return _notifier
def notify_pipeline_start(pipeline_name: str, modules: list) -> None:
"""Notify that pipeline has started"""
notifier = get_notifier()
notifier.notify(
"🚀 Pipeline Started",
"Build pipeline started",
{"Modules": ", ".join(modules)},
color=COLOR_BLUE
)
def notify_pipeline_end(pipeline_name: str, duration: float) -> None:
"""Notify that pipeline completed successfully"""
notifier = get_notifier()
mins = int(duration / 60)
secs = int(duration % 60)
notifier.notify(
"🏁 Pipeline Completed",
"Build pipeline completed successfully",
{"Duration": f"{mins}m {secs}s"},
color=COLOR_GREEN
)
def notify_pipeline_error(pipeline_name: str, error: str) -> None:
"""Notify that pipeline failed with error"""
notifier = get_notifier()
notifier.notify(
"❌ Pipeline Failed",
"Build pipeline failed",
{"Error": error},
color=COLOR_RED
)
def notify_module_start(module_name: str) -> None:
"""Notify that a module started executing"""
notifier = get_notifier()
prefix = _get_context_prefix()
notifier.notify(
"▶️ Module Started",
f"{prefix}Module '{module_name}' started",
None,
color=COLOR_BLUE
)
def notify_module_completion(module_name: str, duration: float) -> None:
"""Notify that a module completed successfully"""
notifier = get_notifier()
prefix = _get_context_prefix()
notifier.notify(
"✅ Module Completed",
f"{prefix}Module '{module_name}' completed",
{"Duration": f"{duration:.1f}s"},
color=COLOR_GREEN
)