1455 lines
37 KiB
Plaintext
1455 lines
37 KiB
Plaintext
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "80d363f7",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!pip install -r requirements.txt"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "750a3ea8",
|
||
"metadata": {},
|
||
"source": [
|
||
"### git hook"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "50691f34",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"cat > .git/hooks/pre-commit <<'EOF'\n",
|
||
"#!/usr/bin/env bash\n",
|
||
"set -euo pipefail\n",
|
||
"\n",
|
||
"FILES=$(git diff --cached --name-only -- '*.ipynb' || true)\n",
|
||
"if [ -z \"$FILES\" ]; then\n",
|
||
" exit 0\n",
|
||
"fi\n",
|
||
"\n",
|
||
"export FILES\n",
|
||
"python3 - <<'PY'\n",
|
||
"import json, subprocess, os\n",
|
||
"from pathlib import Path\n",
|
||
"\n",
|
||
"files = os.environ.get(\"FILES\",\"\").splitlines()\n",
|
||
"for f in files:\n",
|
||
" p = Path(f)\n",
|
||
" nb = json.loads(p.read_text(encoding=\"utf-8\"))\n",
|
||
" for cell in nb.get(\"cells\", []):\n",
|
||
" if cell.get(\"cell_type\") == \"code\":\n",
|
||
" cell[\"outputs\"] = []\n",
|
||
" cell[\"display_name\"] = \".venv\"\n",
|
||
" cell[\"execution_count\"] = None\n",
|
||
" p.write_text(json.dumps(nb, ensure_ascii=False, indent=1) + \"\\n\", encoding=\"utf-8\")\n",
|
||
"\n",
|
||
"subprocess.run([\"git\",\"add\"] + files, check=True)\n",
|
||
"PY\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"chmod +x .git/hooks/pre-commit\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "2657898e",
|
||
"metadata": {},
|
||
"source": [
|
||
"### env setup"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "d0c8af1f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# ignore\n",
|
||
"import os\n",
|
||
"\n",
|
||
"def load_env(file_path):\n",
|
||
" \"\"\"Загружает переменные окружения из файла .env с поддержкой булевых значений.\"\"\"\n",
|
||
" with open(file_path) as f:\n",
|
||
" for line in f:\n",
|
||
" line = line.strip()\n",
|
||
" if not line or line.startswith('#'):\n",
|
||
" continue\n",
|
||
" \n",
|
||
" try:\n",
|
||
" key, value = line.split('=', 1)\n",
|
||
" key = key.strip()\n",
|
||
" value = value.strip('\"\\' ')\n",
|
||
" # Преобразование строковых значений в булевые\n",
|
||
" if value.lower() in ['true', '1', 'yes']:\n",
|
||
" value = True\n",
|
||
" elif value.lower() in ['false', '0', 'no']:\n",
|
||
" value = False\n",
|
||
" \n",
|
||
" # Проверка, что ключ не пустой\n",
|
||
" if key:\n",
|
||
" os.environ[key] = str(value) # Храним как строку\n",
|
||
" except ValueError:\n",
|
||
" print(f\"Ошибка: неверный формат в строке '{line}'\")\n",
|
||
"\n",
|
||
"try:\n",
|
||
" load_env('env')\n",
|
||
"except:\n",
|
||
" load_env('env_example')"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "d0947a0b",
|
||
"metadata": {},
|
||
"source": [
|
||
"### setup"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "627c905d",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"htpasswd -nbB 'user' $REGISTRY_PASS > /tmp/registry.htpasswd\n",
|
||
"kubectl -n container-registry create secret generic registry-basic-auth \\\n",
|
||
" --from-file=auth=/tmp/registry.htpasswd \\\n",
|
||
" --dry-run=client -o yaml | kubectl apply -f -\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "c3339daa",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl create secret docker-registry regcred --docker-server=$REGISTRY_HOST --docker-username='user' --docker-password=$REGISTRY_PASS --docker-email=\"$(git config --global --get user.email)\""
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "63d3463e",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl create namespace kultmost\n",
|
||
"!kubectl create secret docker-registry regcred -n kultmost --docker-server=$REGISTRY_HOST --docker-username='user' --docker-password=$REGISTRY_PASS --docker-email=\"$(git config --global --get user.email)\""
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "ff732fa4",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker login $REGISTRY_HOST -u 'user' -p $REGISTRY_PASS"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "75172234",
|
||
"metadata": {},
|
||
"source": [
|
||
"### pre pull"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "ff55c6cf",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker pull $REGISTRY_HOST/python:3.13-alpine"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "34437078",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker pull $REGISTRY_HOST/python:3.13-slim"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "74d7ec58",
|
||
"metadata": {},
|
||
"source": [
|
||
"### build (ipynb -> py)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "2809c42c",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import json\n",
|
||
"import os\n",
|
||
"\n",
|
||
"IGNORE = ['build.ipynb', 'data.ipynb', 'migrate.ipynb']\n",
|
||
"def build():\n",
|
||
" for _filename in [i for i in os.listdir() if 'ipynb' in i and i not in IGNORE]:\n",
|
||
" filename_without_extension = os.path.splitext(os.path.basename(_filename))[0]\n",
|
||
"\n",
|
||
" with open(f'{filename_without_extension}.ipynb', 'r') as f:\n",
|
||
" data = f.read()\n",
|
||
" main = json.loads(data)\n",
|
||
" app = []\n",
|
||
" for cell in main['cells']:\n",
|
||
" if '## Run' in cell['source']:\n",
|
||
" break\n",
|
||
" if '# ignore\\n' in cell['source']:\n",
|
||
" continue\n",
|
||
" app.append(''.join(cell['source']))\n",
|
||
"\n",
|
||
" with open(f'{filename_without_extension}.py', 'w') as f:\n",
|
||
" f.write('\\n\\n'.join(app))\n",
|
||
"\n",
|
||
"build()"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "fef1918f",
|
||
"metadata": {},
|
||
"source": [
|
||
"### tg build"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "4489de4b",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker tag mongo:latest registry.spiritofweb.ru/mongo:latest"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "81571f0b",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker build -t $REGISTRY_HOST/api-tg:latest tg/."
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "3244466f",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker push $REGISTRY_HOST/api-tg:latest"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "37eabaef",
|
||
"metadata": {},
|
||
"source": [
|
||
"### quick"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "d62a9efa",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker build -t $REGISTRY_HOST/avtopost-api:latest ."
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "fa6370f6",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker image push $REGISTRY_HOST/avtopost-api:latest"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "0309c9b3",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl rollout restart deployments/kultmost-api -n kultmost"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "b1c2c66c",
|
||
"metadata": {},
|
||
"source": [
|
||
"### rollout restart celery"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "8c359276",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl rollout restart deployments/vk-celery -n kultmost"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "a75776f0",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl rollout restart deployments/email-celery -n kultmost"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "92189739",
|
||
"metadata": {},
|
||
"source": [
|
||
"### containers"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "f4b322e5",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"docker pull gitea/gitea:1.22\n",
|
||
"docker tag gitea/gitea:1.22 $REGISTRY_HOST/gitea/gitea:1.22\n",
|
||
"docker push $REGISTRY_HOST/gitea/gitea:1.22"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "b3da4168",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"docker pull busybox:1.36\n",
|
||
"docker pull rabbitmq:3.11-management\n",
|
||
"docker pull alpine:3.14\n",
|
||
"docker pull redis:latest\n",
|
||
"docker pull mongo:latest\n",
|
||
"docker tag redis:latest $REGISTRY_HOST/redis:latest\n",
|
||
"docker tag mongo:latest $REGISTRY_HOST/mongo:latest\n",
|
||
"docker tag busybox:1.36 $REGISTRY_HOST/busybox:1.36\n",
|
||
"docker tag rabbitmq:3.11-management $REGISTRY_HOST/rabbitmq:3.11-management\n",
|
||
"docker tag alpine:3.14 $REGISTRY_HOST/alpine:3.14"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "62728f9d",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"docker push $REGISTRY_HOST/redis:latest\n",
|
||
"docker push $REGISTRY_HOST/mongo:latest\n",
|
||
"docker push $REGISTRY_HOST/busybox:1.36\n",
|
||
"docker push $REGISTRY_HOST/rabbitmq:3.11-management\n",
|
||
"docker push $REGISTRY_HOST/alpine:3.14"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "6b8282c4",
|
||
"metadata": {},
|
||
"source": [
|
||
"### tunnel"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "496f4cc7",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker build -t $REGISTRY_HOST/ssh-tunnel:2 tunnel/"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "cf41b7b4",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!docker push $REGISTRY_HOST/ssh-tunnel:2"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "4419ce48",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl create secret generic ssh-id-rsa --from-file=id_rsa=/home/user/.ssh/id_rsa -n kultmost"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "aa7b001d",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl apply -n kultmost -f k8s/stunnel.yaml"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "97d2a6d6",
|
||
"metadata": {},
|
||
"source": [
|
||
"### k8s"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "c472ba3a",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!envsubst < k8s/prod.yaml | kubectl apply -n kultmost -f -"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "b8579fa2",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!envsubst < k8s/kultmost.yaml | kubectl apply -n kultmost -f -"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "01c430ae",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!envsubst < k8s/mq.yaml | kubectl apply -n kultmost -f -"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "598e0bc3",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!envsubst < k8s/gitea.yaml | kubectl apply -n gitea -f -"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "f047b0f2",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!kubectl get pod -n kultmost"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "35a1cf25",
|
||
"metadata": {},
|
||
"source": [
|
||
"### tg yaml"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "d4139bf6",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"echo \"$INIT_SSH'bash -s' <<'SCRIPT'\"\n",
|
||
"echo \"kubectl create secret docker-registry regcred --docker-server=$REGISTRY_HOST --docker-username='user' --docker-password=$REGISTRY_PASS --docker-email=\\\"$(git config --global --get user.email)\\\" && clear && history -c && history -w\"\n",
|
||
"echo \"SCRIPT\""
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "2a13a8af",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"echo \"$INIT_SSH'bash -s' <<'SCRIPT'\"\n",
|
||
"echo \"kubectl apply -f - <<'EOF'\"\n",
|
||
"envsubst < k8s/tg.yaml\n",
|
||
"echo\n",
|
||
"echo \"EOF\"\n",
|
||
"echo \"SCRIPT\"\n",
|
||
"echo \"clear\"\n",
|
||
"echo \"history -c\"\n",
|
||
"echo \"history -w\""
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "0a429fca",
|
||
"metadata": {},
|
||
"source": [
|
||
"### rsync"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "ff536fb8",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!rsync -avz -ogp --chown=www-data:www-data ./static/ kultmost:/var/www/static/"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "fc4aa1ca",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!echo $(git branch --show-current)"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "11c03751",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!rsync -avh --exclude-from=.rsyncignore --exclude=.venv/ . kultmost:/app/$(git branch --show-current)/"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "c49e0757",
|
||
"metadata": {},
|
||
"source": [
|
||
"### fastapi prod service"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "b0a663d0",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"ssh kultmost 'tee /etc/systemd/system/production.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=FastAPI prod service\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=/app/production\n",
|
||
"ExecStart=/app/production/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 30081 --workers 8\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=/app/production/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"ssh kultmost 'systemctl daemon-reload && systemctl enable --now production.service && systemctl status --no-pager -l production.service'\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "d4552baa",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"ssh kultmost 'tee /etc/systemd/system/fastapi.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=FastAPI prod service\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=/app/production\n",
|
||
"ExecStart=/app/production/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 30080 --workers 8\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=/app/production/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"ssh kultmost 'systemctl daemon-reload && systemctl enable --now fastapi.service && systemctl status --no-pager -l fastapi.service'\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "dfd8deed",
|
||
"metadata": {},
|
||
"source": [
|
||
"### fastapi stag service"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "3b4f2998",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"ssh kultmost 'tee /etc/systemd/system/staging.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=FastAPI stag service\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=/app/staging\n",
|
||
"ExecStart=/app/staging/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 30082 --reload\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=/app/staging/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"ssh kultmost 'systemctl daemon-reload && systemctl enable --now staging.service && systemctl status --no-pager -l staging.service'\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "4c434852",
|
||
"metadata": {},
|
||
"source": [
|
||
"### local service"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "45bddd01",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"'tee /etc/systemd/system/staging.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=FastAPI stag service\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=$pwd\n",
|
||
"ExecStart=$pwd/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 30082 --reload\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=$pwd/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "837698d9",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"ssh kultmost 'tee /etc/systemd/system/staging.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=FastAPI stag service\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=/app/staging\n",
|
||
"ExecStart=/app/staging/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 30082 --reload\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=/app/staging/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"ssh kultmost 'systemctl daemon-reload && systemctl enable --now staging.service && systemctl status --no-pager -l staging.service'\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "0474516d",
|
||
"metadata": {},
|
||
"source": [
|
||
"### restart fastapi"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "001d41fe",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl restart production.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "676e82ad",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl status production.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "6fdc2d37",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl restart fastapi.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "4633b242",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl status fastapi.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "004c5bea",
|
||
"metadata": {},
|
||
"source": [
|
||
"### restart celery"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "88961bb1",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"ssh kultmost 'tee /etc/systemd/system/vk-celery.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=Celery VK\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=/app/production\n",
|
||
"ExecStart=/app/production/.venv/bin/celery -A vk.celery_app_vk worker --loglevel=info\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=/app/production/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"ssh kultmost 'systemctl daemon-reload && systemctl enable --now vk-celery.service && systemctl status --no-pager -l vk-celery.service'\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "3cc3fd1c",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl restart vk-celery.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "3f77084c",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl status vk-celery.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "21036b74",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"%%bash\n",
|
||
"ssh kultmost 'tee /etc/systemd/system/email-celery.service >/dev/null' <<'EOF'\n",
|
||
"[Unit]\n",
|
||
"Description=Celery Emails\n",
|
||
"After=network.target\n",
|
||
"\n",
|
||
"[Service]\n",
|
||
"WorkingDirectory=/app/production\n",
|
||
"ExecStart=/app/production/.venv/bin/celery -A email_task.celery_app_email worker --loglevel=info\n",
|
||
"Restart=always\n",
|
||
"EnvironmentFile=/app/production/env\n",
|
||
"\n",
|
||
"[Install]\n",
|
||
"WantedBy=default.target\n",
|
||
"EOF\n",
|
||
"\n",
|
||
"ssh kultmost 'systemctl daemon-reload && systemctl enable --now email-celery.service && systemctl status --no-pager -l email-celery.service'\n"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "68340709",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl restart email-celery.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "d9285803",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'systemctl status email-celery.service'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "1a723121",
|
||
"metadata": {},
|
||
"source": [
|
||
"### nginx"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "003f0324",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"# !scp kultmost:/etc/nginx/sites-enabled/default nginx_conf "
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "dbfffccd",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!scp nginx_conf kultmost:/tmp/default\n",
|
||
"!ssh kultmost 'sudo mv /tmp/default /etc/nginx/sites-enabled/default'\n",
|
||
"!ssh kultmost 'nginx -t'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "f7d27751",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"!ssh kultmost 'nginx -s reload'"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "a26138d2",
|
||
"metadata": {},
|
||
"source": [
|
||
"### microk8s"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "e10becc3",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"sudo snap install microk8s --classic\n",
|
||
"sudo usermod -a -G microk8s $USER\n",
|
||
"newgrp microk8s\n",
|
||
"microk8s status"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "b0761e24",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "shellscript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"curl -LO https://cert-manager.io/public-keys/cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg\n",
|
||
"helm install cert-manager oci://quay.io/jetstack/charts/cert-manager --version v1.20.2 --namespace cert-manager --create-namespace --verify --keyring ./cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg --set crds.enabled=true\n",
|
||
"microk8s helm install cert-manager oci://quay.io/jetstack/charts/cert-manager --version v1.20.2 --namespace cert-manager --create-namespace --verify --keyring ./cert-manager-keyring-2021-09-20-1020CF3C033D4F35BAE1C19E1226061C665DF13E.gpg --set crds.enabled=true"
|
||
],
|
||
"display_name": ".venv"
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "622f00a3",
|
||
"metadata": {},
|
||
"source": [
|
||
"### Figma"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "8fe7cf08",
|
||
"metadata": {
|
||
"vscode": {
|
||
"languageId": "javascript"
|
||
}
|
||
},
|
||
"outputs": [],
|
||
"source": [
|
||
"m1 = figma.currentPage.children[0]\n",
|
||
"HTML_TAGS = new Set(['a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'title', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr']);\n",
|
||
"\n",
|
||
"function isHtmlTag(name) {\n",
|
||
" return typeof name === 'string' && HTML_TAGS.has(name.toLowerCase());\n",
|
||
"}\n",
|
||
"\n",
|
||
"function randomString5() { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let s = ''; for (let i = 0; i < 5; i++) s += chars.charAt(Math.floor(Math.random() * chars.length)); return s; }\n",
|
||
"\n",
|
||
"pc = m1.children[0]\n",
|
||
"tablet = m1.children[1]\n",
|
||
"mob = m1.children[2]\n",
|
||
"console.log(pc.name, tablet.name, mob.name)\n",
|
||
"// helpers (примерные реализации, если у вас другие — замените)\n",
|
||
"function randomString5() {\n",
|
||
" return Math.random().toString(36).slice(2, 7);\n",
|
||
"}\n",
|
||
"function isHtmlTag(name) {\n",
|
||
" return typeof name === 'string' && /^[a-zA-Z][\\w-]*$/.test(name);\n",
|
||
"}\n",
|
||
"function cssObjectToString(obj) {\n",
|
||
" return Object.entries(obj || {})\n",
|
||
" .map(([k, v]) => `${k.replace(/[A-Z]/g, m => '-' + m.toLowerCase())}: ${v};`)\n",
|
||
" .join(' ');\n",
|
||
"}\n",
|
||
"// helper: конвертирует объект CSS в строку\n",
|
||
"function cssObjectToString(obj = {}) {\n",
|
||
" return Object.entries(obj)\n",
|
||
" .map(([k, v]) => `${k}: ${v};`)\n",
|
||
" .join(' ');\n",
|
||
"}\n",
|
||
"\n",
|
||
"async function element_create(pc_node, tablet_node, mob_node) {\n",
|
||
" const cssRules = [];\n",
|
||
"\n",
|
||
" const randomString5 = () => Math.random().toString(36).substring(2, 5);\n",
|
||
"\n",
|
||
" function nodeExists(node, idx) {\n",
|
||
" return node && Array.isArray(node.children) && node.children[idx];\n",
|
||
" }\n",
|
||
"\n",
|
||
" async function getStyle(node) {\n",
|
||
" if (!node) return {};\n",
|
||
" if (typeof node.getCSSAsync === 'function') {\n",
|
||
" return await node.getCSSAsync();\n",
|
||
" }\n",
|
||
" return node.style || {};\n",
|
||
" }\n",
|
||
"\n",
|
||
" function cssObjectToString(cssObj) {\n",
|
||
" if (!cssObj || typeof cssObj !== 'object') return '';\n",
|
||
" return Object.entries(cssObj)\n",
|
||
" .map(([prop, value]) => `${prop}: ${value};`)\n",
|
||
" .sort()\n",
|
||
" .join(' ');\n",
|
||
" }\n",
|
||
"\n",
|
||
" function findExistingClass(pcBody, tableBody, mobBody) {\n",
|
||
" for (const r of cssRules) {\n",
|
||
" if (r.pcBody === pcBody && \n",
|
||
" r.tableBody === tableBody && \n",
|
||
" r.mobBody === mobBody) {\n",
|
||
" return r.cls;\n",
|
||
" }\n",
|
||
" }\n",
|
||
" return null;\n",
|
||
" }\n",
|
||
"\n",
|
||
" async function build(pcN, tabN, mobN) {\n",
|
||
" if (!pcN?.name) return document.createElement('div');\n",
|
||
"\n",
|
||
" const tagName = pcN.name.replace(/Desktop|desktop/gi, 'section').toLowerCase();\n",
|
||
" const el = document.createElement(tagName);\n",
|
||
"\n",
|
||
" if (pcN.characters != null) {\n",
|
||
" el.textContent = pcN.characters;\n",
|
||
" }\n",
|
||
"\n",
|
||
" // Рекурсия по детям\n",
|
||
" if (Array.isArray(pcN.children) && pcN.children.length) {\n",
|
||
" for (let i = 0; i < pcN.children.length; i++) {\n",
|
||
" const pcChild = pcN.children[i];\n",
|
||
" const tabChild = nodeExists(tabN, i) ? tabN.children[i] : pcChild;\n",
|
||
" const mobChild = nodeExists(mobN, i) ? mobN.children[i] : pcChild;\n",
|
||
"\n",
|
||
" if (typeof isHtmlTag === 'function' && isHtmlTag(pcChild.name)) {\n",
|
||
" const childEl = await build(pcChild, tabChild, mobChild);\n",
|
||
" el.appendChild(childEl);\n",
|
||
" }\n",
|
||
" }\n",
|
||
" }\n",
|
||
"\n",
|
||
" const pcCss = await getStyle(pcN);\n",
|
||
" const tabCss = await getStyle(tabN);\n",
|
||
" const mobCss = await getStyle(mobN);\n",
|
||
"\n",
|
||
" const pcBody = cssObjectToString(pcCss);\n",
|
||
" const tableBody = cssObjectToString(tabCss);\n",
|
||
" const mobBody = cssObjectToString(mobCss);\n",
|
||
"\n",
|
||
" let cls = findExistingClass(pcBody, tableBody, mobBody);\n",
|
||
"\n",
|
||
" if (!cls) {\n",
|
||
" cls = 'c_' + randomString5();\n",
|
||
" const baseCls = 'b_' + randomString5();\n",
|
||
"\n",
|
||
" cssRules.push({\n",
|
||
" cls,\n",
|
||
" baseCls,\n",
|
||
" pcBody,\n",
|
||
" tableBody,\n",
|
||
" mobBody,\n",
|
||
" baseStyle: '' // заполним ниже\n",
|
||
" });\n",
|
||
" }\n",
|
||
"\n",
|
||
" // Добавляем оба класса к элементу\n",
|
||
" el.classList.add(cls);\n",
|
||
" // base-класс добавим только если есть общие стили (позже)\n",
|
||
"\n",
|
||
" return el;\n",
|
||
" }\n",
|
||
"\n",
|
||
" const rootEl = await build(pc_node, tablet_node, mob_node);\n",
|
||
"\n",
|
||
" // === Определяем общие стили и различия ===\n",
|
||
" const baseBlockParts = [];\n",
|
||
"\n",
|
||
" for (const rule of cssRules) {\n",
|
||
" const { cls, baseCls, pcBody, tableBody, mobBody } = rule;\n",
|
||
"\n",
|
||
" let baseStyle = '';\n",
|
||
"\n",
|
||
" // Определяем, есть ли общие стили\n",
|
||
" if (pcBody && pcBody === tableBody && tableBody === mobBody) {\n",
|
||
" baseStyle = pcBody;\n",
|
||
" } else if (pcBody && pcBody === tableBody) {\n",
|
||
" baseStyle = pcBody; // desktop + tablet одинаковые\n",
|
||
" } else if (pcBody && pcBody === mobBody) {\n",
|
||
" baseStyle = pcBody;\n",
|
||
" } else if (tableBody && tableBody === mobBody) {\n",
|
||
" baseStyle = tableBody;\n",
|
||
" }\n",
|
||
"\n",
|
||
" rule.baseStyle = baseStyle;\n",
|
||
"\n",
|
||
" // Добавляем base-класс только если есть общие стили\n",
|
||
" if (baseStyle) {\n",
|
||
" baseBlockParts.push(`.${baseCls} { ${baseStyle} }`);\n",
|
||
" \n",
|
||
" // Находим все элементы с этим cls и добавляем им baseCls\n",
|
||
" // (поскольку build уже завершён, делаем это через DOM)\n",
|
||
" rootEl.querySelectorAll(`.${cls}`).forEach(el => {\n",
|
||
" el.classList.add(baseCls);\n",
|
||
" });\n",
|
||
" }\n",
|
||
"\n",
|
||
" // Различия для медиа-запросов (только то, что отличается от base)\n",
|
||
" rule.mobDiff = (mobBody && mobBody !== baseStyle) ? `.${cls} { ${mobBody} }` : '';\n",
|
||
" rule.tableDiff = (tableBody && tableBody !== baseStyle) ? `.${cls} { ${tableBody} }` : '';\n",
|
||
" rule.pcDiff = (pcBody && pcBody !== baseStyle) ? `.${cls} { ${pcBody} }` : '';\n",
|
||
" }\n",
|
||
"\n",
|
||
" const baseBlock = baseBlockParts.join('\\n');\n",
|
||
" const mobBlock = cssRules.map(r => r.mobDiff).filter(Boolean).join('\\n');\n",
|
||
" const tableBlock = cssRules.map(r => r.tableDiff).filter(Boolean).join('\\n');\n",
|
||
" const pcBlock = cssRules.map(r => r.pcDiff).filter(Boolean).join('\\n');\n",
|
||
"\n",
|
||
" // === Создаём <style> ===\n",
|
||
" const styleEl = document.createElement('style');\n",
|
||
" styleEl.type = 'text/css';\n",
|
||
" styleEl.textContent = `\n",
|
||
"/* Base (common) styles */\n",
|
||
"${baseBlock}\n",
|
||
"\n",
|
||
"/* Mobile */\n",
|
||
"@media (max-width: 699px) {\n",
|
||
"${mobBlock}\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Tablet */\n",
|
||
"@media (min-width: 700px) and (max-width: 900px) {\n",
|
||
"${tableBlock}\n",
|
||
"}\n",
|
||
"\n",
|
||
"/* Desktop */\n",
|
||
"@media (min-width: 901px) {\n",
|
||
"${pcBlock}\n",
|
||
"}\n",
|
||
"`.trim();\n",
|
||
"\n",
|
||
" const ret = document.createElement('div');\n",
|
||
" ret.appendChild(rootEl);\n",
|
||
" ret.appendChild(styleEl);\n",
|
||
"\n",
|
||
" return ret;\n",
|
||
"}\n",
|
||
"\n",
|
||
"sss = await element_create(pc, tablet, mob)\n",
|
||
"sss.innerHTML"
|
||
],
|
||
"display_name": ".venv"
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": ".venv (3.14.6.final.0)",
|
||
"language": "python",
|
||
"name": "python3"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.14.6"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|