chore(ops): harden rollout gates and sanitize generated artifacts
This commit is contained in:
+23
@@ -8,6 +8,29 @@ secrets/runtime.env
|
|||||||
*.bak
|
*.bak
|
||||||
windows/*.report.json
|
windows/*.report.json
|
||||||
.rollout-logs/
|
.rollout-logs/
|
||||||
|
reports/
|
||||||
|
tmp/
|
||||||
|
graphify-out/cache/
|
||||||
|
graphify-out/powershell-parse-results*.json
|
||||||
|
graphify-out/powershell-pssa-warn-results.json
|
||||||
|
graphify-out/shellcheck-*.txt
|
||||||
|
graphify-out/validate_dryrun_out*.txt
|
||||||
|
graphify-out/pssa_diffs.txt
|
||||||
|
.graphify_analysis.json
|
||||||
|
.graphify_ast.json
|
||||||
|
.graphify_cached.json
|
||||||
|
.graphify_chunk_list_*.txt
|
||||||
|
.graphify_detect.json
|
||||||
|
.graphify_extract.json
|
||||||
|
.graphify_labels.json
|
||||||
|
.graphify_python
|
||||||
|
.graphify_semantic.json
|
||||||
|
.graphify_uncached.txt
|
||||||
|
graphify-out/GRAPH_REPORT.md
|
||||||
|
graphify-out/graph.html
|
||||||
|
graphify-out/graph.json
|
||||||
|
.pssa_run.ps1
|
||||||
|
data/
|
||||||
|
|
||||||
# IDE
|
# IDE
|
||||||
.idea/
|
.idea/
|
||||||
|
|||||||
-11236
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -9,6 +9,7 @@
|
|||||||
- `docs/deployment.md` — пошаговый деплой LXC и ActivityWatch Server.
|
- `docs/deployment.md` — пошаговый деплой LXC и ActivityWatch Server.
|
||||||
- `docs/runbook.md` — быстрый runbook для оператора.
|
- `docs/runbook.md` — быстрый runbook для оператора.
|
||||||
- `docs/operations.md` — регламент сопровождения, бэкапов, обновлений и rollback.
|
- `docs/operations.md` — регламент сопровождения, бэкапов, обновлений и rollback.
|
||||||
|
- `docs/artifacts-policy.md` — политика generated-артефактов и rollout-gates.
|
||||||
- `docs/windows/ensemble.md` — orchestration-пакет для Windows-деплоя и проверки.
|
- `docs/windows/ensemble.md` — orchestration-пакет для Windows-деплоя и проверки.
|
||||||
- `docs/linux-client.md` — user-space rollout Linux-клиента ActivityWatch на удалённый `AW server`.
|
- `docs/linux-client.md` — user-space rollout Linux-клиента ActivityWatch на удалённый `AW server`.
|
||||||
- `docs/linux-remote-worker.md` — полный Linux remote-worker stack: GUI, SSH/console и browser admin UI вроде Proxmox `:8006`.
|
- `docs/linux-remote-worker.md` — полный Linux remote-worker stack: GUI, SSH/console и browser admin UI вроде Proxmox `:8006`.
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Artifacts Policy
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
Define which files are source-of-truth and which are generated runtime/research artifacts that must not block or pollute production rollouts.
|
||||||
|
|
||||||
|
## Source of Truth
|
||||||
|
|
||||||
|
Tracked and reviewable:
|
||||||
|
|
||||||
|
- `ansible/`
|
||||||
|
- `aw-server/`
|
||||||
|
- `windows/`
|
||||||
|
- `scripts/`
|
||||||
|
- `docs/`
|
||||||
|
- install-kit templates and manifests under `windows/installkit/innosetup/`
|
||||||
|
|
||||||
|
## Generated / Volatile Artifacts
|
||||||
|
|
||||||
|
Not for production commits:
|
||||||
|
|
||||||
|
- `.graphify_*` cache/analysis outputs
|
||||||
|
- `graphify-out/cache/*`
|
||||||
|
- `graphify-out/shellcheck-*.txt`
|
||||||
|
- `graphify-out/validate_dryrun_out*.txt`
|
||||||
|
- `graphify-out/powershell-parse-results*.json`
|
||||||
|
- `graphify-out/powershell-pssa-warn-results.json`
|
||||||
|
- `graphify-out/pssa_diffs.txt`
|
||||||
|
- `reports/*`
|
||||||
|
- `tmp/*`
|
||||||
|
|
||||||
|
These paths are ignored by `.gitignore` and additionally guarded by `scripts/quality-gate.sh`.
|
||||||
|
|
||||||
|
## Rollout Gate
|
||||||
|
|
||||||
|
`scripts/prod_rollout.sh` must run only when:
|
||||||
|
|
||||||
|
1. `AW_MAINTENANCE_ACK=YES` is set.
|
||||||
|
2. `scripts/quality-gate.sh` passes.
|
||||||
|
3. Preflight checks pass:
|
||||||
|
- `ansible ping`/`win_ping`
|
||||||
|
- `./check-aw-data.sh`
|
||||||
|
- `./check-aw-full.sh`
|
||||||
|
|
||||||
|
If any gate fails, rollout stops.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Secrets policy remains temporary by operator choice; credentials may still exist in local `inventory.ini` during this phase.
|
||||||
|
- Dedicated secrets hardening (vault/env-only enforcement) is a separate follow-up track.
|
||||||
@@ -17,6 +17,7 @@
|
|||||||
- секреты не хранить в git;
|
- секреты не хранить в git;
|
||||||
- каждое изменение фиксировать в ticket/run log;
|
- каждое изменение фиксировать в ticket/run log;
|
||||||
- публичную публикацию делать через отдельный proxy/security layer.
|
- публичную публикацию делать через отдельный proxy/security layer.
|
||||||
|
- generated-артефакты и исследовательские кэши вести по [artifacts-policy.md](/mnt/usb_hdd2/Projects/ActivityWatch-Russian/docs/artifacts-policy.md).
|
||||||
|
|
||||||
## Регулярные проверки
|
## Регулярные проверки
|
||||||
|
|
||||||
@@ -124,3 +125,4 @@ systemctl restart activitywatch-server.service
|
|||||||
- не обновлять поверх рабочего бинарника без backup;
|
- не обновлять поверх рабочего бинарника без backup;
|
||||||
- не открывать `5600/tcp` наружу без отдельной защиты;
|
- не открывать `5600/tcp` наружу без отдельной защиты;
|
||||||
- не править `index.html` вручную без backup.
|
- не править `index.html` вручную без backup.
|
||||||
|
- не запускать `scripts/prod_rollout.sh` без `AW_MAINTENANCE_ACK=YES`.
|
||||||
|
|||||||
@@ -196,6 +196,15 @@ systemctl restart activitywatch-server.service
|
|||||||
|
|
||||||
## Перед любыми изменениями
|
## Перед любыми изменениями
|
||||||
|
|
||||||
|
0. Подтвердить maintenance window и gate:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export AW_MAINTENANCE_ACK=YES
|
||||||
|
./scripts/quality-gate.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
Если `quality-gate` падает (например, drift install-kit vs repo), rollout не запускать.
|
||||||
|
|
||||||
1. Сделать snapshot или `vzdump`.
|
1. Сделать snapshot или `vzdump`.
|
||||||
2. Сохранить текущий `/etc/activitywatch/aw-server.env`.
|
2. Сохранить текущий `/etc/activitywatch/aw-server.env`.
|
||||||
3. Сохранить текущий `index.html`.
|
3. Сохранить текущий `index.html`.
|
||||||
|
|||||||
@@ -1,101 +0,0 @@
|
|||||||
# ActivityWatch-Russian Knowledge Graph Report
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
- **Total Nodes**: 404
|
|
||||||
- **Total Edges**: 933
|
|
||||||
- **Communities**: 27
|
|
||||||
- **Source**: AST extraction (code-only corpus)
|
|
||||||
|
|
||||||
## Communities by Size
|
|
||||||
|
|
||||||
### Community 1 (62 nodes)
|
|
||||||
- install_kit_awindows_20260427_211240_windows_dlp_endpoint_signals_collector_ps1
|
|
||||||
- dlp_endpoint_signals_collector_get_deploymentconfig
|
|
||||||
- dlp_endpoint_signals_collector_write_endpointlog
|
|
||||||
- dlp_endpoint_signals_collector_invoke_awjsonpost
|
|
||||||
- dlp_endpoint_signals_collector_ensure_bucket
|
|
||||||
- ... and 57 more
|
|
||||||
|
|
||||||
### Community 2 (56 nodes)
|
|
||||||
- aw_server_aw_ru_patch_js
|
|
||||||
- aw_ru_patch_injectstyles
|
|
||||||
- aw_ru_patch_hidenoisenavigation
|
|
||||||
- aw_ru_patch_getcurrenthostfromhash
|
|
||||||
- aw_ru_patch_ispvelikehost
|
|
||||||
- ... and 51 more
|
|
||||||
|
|
||||||
### Community 3 (54 nodes)
|
|
||||||
- install_kit_awindows_20260427_211240_windows_browser_domains_native_collector_ps1
|
|
||||||
- browser_domains_native_collector_get_deploymentconfig
|
|
||||||
- browser_domains_native_collector_write_collectorlog
|
|
||||||
- browser_domains_native_collector_write_dlpincidentlog
|
|
||||||
- browser_domains_native_collector_test_domainmatch
|
|
||||||
- ... and 49 more
|
|
||||||
|
|
||||||
### Community 0 (38 nodes)
|
|
||||||
- scripts_aggregate_dlp_events_py
|
|
||||||
- aggregate_dlp_events_bucket
|
|
||||||
- aggregate_dlp_events_awevent
|
|
||||||
- aggregate_dlp_events_psycopgconnection
|
|
||||||
- protocol
|
|
||||||
- ... and 33 more
|
|
||||||
|
|
||||||
### Community 5 (34 nodes)
|
|
||||||
- aw_ru_patch_isdlpsignalbucketroute
|
|
||||||
- aw_ru_patch_getdlphostfrombucketid
|
|
||||||
- aw_ru_patch_builddlpkey
|
|
||||||
- aw_ru_patch_loadbucketevents
|
|
||||||
- aw_ru_patch_serializerulematch
|
|
||||||
- ... and 29 more
|
|
||||||
|
|
||||||
### Community 4 (34 nodes)
|
|
||||||
- install_kit_awindows_20260427_211240_windows_email_outbound_collector_ps1
|
|
||||||
- email_outbound_collector_get_deploymentconfig
|
|
||||||
- email_outbound_collector_write_collectorlog
|
|
||||||
- email_outbound_collector_invoke_awjsonpost
|
|
||||||
- email_outbound_collector_ensure_bucket
|
|
||||||
- ... and 29 more
|
|
||||||
|
|
||||||
### Community 8 (28 nodes)
|
|
||||||
- aw_ru_patch_replacetext
|
|
||||||
- aw_ru_patch_walk
|
|
||||||
- aw_ru_patch_translateattributes
|
|
||||||
- aw_ru_patch_ishomeroute
|
|
||||||
- aw_ru_patch_getdefaulthostgroupsconfig
|
|
||||||
- ... and 23 more
|
|
||||||
|
|
||||||
### Community 9 (18 nodes)
|
|
||||||
- aw_ru_patch_getdlpbucketidfromhash
|
|
||||||
- aw_ru_patch_generatedlpid
|
|
||||||
- aw_ru_patch_awapijson
|
|
||||||
- aw_ru_patch_ensureawbucket
|
|
||||||
- aw_ru_patch_saveawheartbeat
|
|
||||||
- ... and 13 more
|
|
||||||
|
|
||||||
### Community 10 (14 nodes)
|
|
||||||
- install_kit_awindows_20260427_211240_windows_migrate_awatch_rus_paths_ps1
|
|
||||||
- migrate_awatch_rus_paths_copy_directorycontents
|
|
||||||
- migrate_awatch_rus_paths_copy_ifexists
|
|
||||||
- migrate_awatch_rus_paths_convert_pathvalue
|
|
||||||
- migrate_awatch_rus_paths_stop_awatchtaskset
|
|
||||||
- ... and 9 more
|
|
||||||
|
|
||||||
### Community 6 (12 nodes)
|
|
||||||
- grafana_1c_sql_exporter_collectors_aw_activitywatch_py
|
|
||||||
- aw_activitywatch_activitywatchexporter
|
|
||||||
- aw_activitywatch_activitywatchexporter_init
|
|
||||||
- aw_activitywatch_activitywatchexporter_get_buckets
|
|
||||||
- aw_activitywatch_activitywatchexporter_get_bucket_events
|
|
||||||
- ... and 7 more
|
|
||||||
|
|
||||||
## File Types
|
|
||||||
The graph was built from code files including:
|
|
||||||
- PowerShell scripts (.ps1)
|
|
||||||
- Python scripts (.py)
|
|
||||||
- JavaScript patches (.js)
|
|
||||||
- Configuration files
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
- This is a structural (AST-based) graph showing code relationships
|
|
||||||
- No semantic extraction was performed (no docs/papers in corpus)
|
|
||||||
- Communities represent clusters of related functions and modules
|
|
||||||
File diff suppressed because one or more lines are too long
-11645
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,23 @@ cd "$ROOT_DIR"
|
|||||||
# shellcheck disable=SC2034
|
# shellcheck disable=SC2034
|
||||||
KIT_DIR="install-kit-awindows-20260427-211240"
|
KIT_DIR="install-kit-awindows-20260427-211240"
|
||||||
|
|
||||||
python - <<'PY'
|
PY_BIN="${PY_BIN:-}"
|
||||||
|
if [[ -z "$PY_BIN" ]]; then
|
||||||
|
if command -v python3 >/dev/null 2>&1; then
|
||||||
|
PY_BIN="python3"
|
||||||
|
elif command -v python >/dev/null 2>&1; then
|
||||||
|
PY_BIN="python"
|
||||||
|
else
|
||||||
|
echo "ERROR: python3/python not found"
|
||||||
|
exit 127
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$PY_BIN" - <<'PY'
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
root=Path('.')
|
root=Path('.')
|
||||||
kit=Path('install-kit-awindows-20260427-211240')
|
kit=Path('install-kit-awindows-20260427-211240')
|
||||||
@@ -25,6 +39,13 @@ missing_in_repo=[]
|
|||||||
|
|
||||||
for kp in sorted(p for p in kit.rglob('*') if p.is_file() and p.name!='MANIFEST.txt'):
|
for kp in sorted(p for p in kit.rglob('*') if p.is_file() and p.name!='MANIFEST.txt'):
|
||||||
rel=kp.relative_to(kit)
|
rel=kp.relative_to(kit)
|
||||||
|
rel_s=str(rel)
|
||||||
|
if rel_s.startswith("server-configs-192.168.100.21/"):
|
||||||
|
continue
|
||||||
|
if rel_s == "README-INSTALL-KIT.txt":
|
||||||
|
continue
|
||||||
|
if "__pycache__" in kp.parts or kp.suffix == ".pyc":
|
||||||
|
continue
|
||||||
rp=root/rel
|
rp=root/rel
|
||||||
if not rp.exists():
|
if not rp.exists():
|
||||||
missing_in_repo.append(str(rel))
|
missing_in_repo.append(str(rel))
|
||||||
@@ -51,4 +72,9 @@ if ps_mismatches:
|
|||||||
print('--- PowerShell mismatches ---')
|
print('--- PowerShell mismatches ---')
|
||||||
for p in ps_mismatches:
|
for p in ps_mismatches:
|
||||||
print(p)
|
print(p)
|
||||||
|
|
||||||
|
strict = os.getenv("ALLOW_KIT_DRIFT", "").lower() not in {"1", "true", "yes"}
|
||||||
|
if strict and (missing_in_repo or mismatches):
|
||||||
|
print("ERROR: install-kit drift detected. Set ALLOW_KIT_DRIFT=1 to bypass.")
|
||||||
|
sys.exit(1)
|
||||||
PY
|
PY
|
||||||
|
|||||||
@@ -35,6 +35,12 @@ require_cmd ansible
|
|||||||
log "Repo: ${ROOT_DIR}"
|
log "Repo: ${ROOT_DIR}"
|
||||||
log "Branch: $(git branch --show-current)"
|
log "Branch: $(git branch --show-current)"
|
||||||
|
|
||||||
|
if [[ "${AW_MAINTENANCE_ACK:-}" != "YES" ]]; then
|
||||||
|
log "ERROR: maintenance window is required."
|
||||||
|
log "Set AW_MAINTENANCE_ACK=YES to proceed."
|
||||||
|
exit 4
|
||||||
|
fi
|
||||||
|
|
||||||
log "Running local quality gate..."
|
log "Running local quality gate..."
|
||||||
./scripts/quality-gate.sh | tee -a "${LOG_DIR}/quality-gate.log"
|
./scripts/quality-gate.sh | tee -a "${LOG_DIR}/quality-gate.log"
|
||||||
|
|
||||||
@@ -67,6 +73,10 @@ log "Preflight connectivity..."
|
|||||||
ansible -i ansible/inventory.ini aw_server -m ping | tee -a "${LOG_DIR}/ping_aw_server.log"
|
ansible -i ansible/inventory.ini aw_server -m ping | tee -a "${LOG_DIR}/ping_aw_server.log"
|
||||||
ansible -i ansible/inventory.ini aw_windows -m win_ping | tee -a "${LOG_DIR}/ping_aw_windows.log"
|
ansible -i ansible/inventory.ini aw_windows -m win_ping | tee -a "${LOG_DIR}/ping_aw_windows.log"
|
||||||
|
|
||||||
|
log "Preflight ActivityWatch API/data checks..."
|
||||||
|
./check-aw-data.sh | tee -a "${LOG_DIR}/check_aw_data.log"
|
||||||
|
./check-aw-full.sh | tee -a "${LOG_DIR}/check_aw_full.log"
|
||||||
|
|
||||||
log "Dry-run aw_server..."
|
log "Dry-run aw_server..."
|
||||||
ansible-playbook -i ansible/inventory.ini ansible/deploy_aw_server.yml --check --diff | tee -a "${LOG_DIR}/check_aw_server.log"
|
ansible-playbook -i ansible/inventory.ini ansible/deploy_aw_server.yml --check --diff | tee -a "${LOG_DIR}/check_aw_server.log"
|
||||||
|
|
||||||
|
|||||||
+15
-6
@@ -4,33 +4,42 @@ set -euo pipefail
|
|||||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
cd "$ROOT_DIR"
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
echo "[1/4] Bash syntax check"
|
echo "[1/6] Bash syntax check"
|
||||||
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r -n1 bash -n
|
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r -n1 bash -n
|
||||||
|
|
||||||
echo "[2/4] Shellcheck (if available)"
|
echo "[2/6] Shellcheck (if available)"
|
||||||
if command -v shellcheck >/dev/null 2>&1; then
|
if command -v shellcheck >/dev/null 2>&1; then
|
||||||
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r shellcheck -e SC1007,SC1090,SC2016
|
find aw-server proxmox -type f -name "*.sh" -print0 | xargs -0 -r shellcheck -e SC1007,SC1090,SC2016
|
||||||
else
|
else
|
||||||
echo "shellcheck not found, skipping."
|
echo "shellcheck not found, skipping."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[3/4] PowerShell parse check (if pwsh available)"
|
echo "[3/6] PowerShell parse check (if pwsh available)"
|
||||||
if command -v pwsh >/dev/null 2>&1; then
|
if command -v pwsh >/dev/null 2>&1; then
|
||||||
pwsh -NoLogo -NoProfile -Command '
|
if ! pwsh -NoLogo -NoProfile -Command '
|
||||||
$ErrorActionPreference = "Stop"
|
$ErrorActionPreference = "Stop"
|
||||||
Get-ChildItem windows -Filter *.ps1 | ForEach-Object {
|
Get-ChildItem windows -Filter *.ps1 | ForEach-Object {
|
||||||
[void][System.Management.Automation.Language.Parser]::ParseFile($_.FullName,[ref]$null,[ref]$null)
|
[void][System.Management.Automation.Language.Parser]::ParseFile($_.FullName,[ref]$null,[ref]$null)
|
||||||
}
|
}
|
||||||
[void][System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path "windows/ActivityWatch.Windows.Common.psm1"),[ref]$null,[ref]$null)
|
[void][System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path "windows/ActivityWatch.Windows.Common.psm1"),[ref]$null,[ref]$null)
|
||||||
[void][System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path "windows/ActivityWatch.Windows.Common.psd1"),[ref]$null,[ref]$null)
|
[void][System.Management.Automation.Language.Parser]::ParseFile((Resolve-Path "windows/ActivityWatch.Windows.Common.psd1"),[ref]$null,[ref]$null)
|
||||||
'
|
'; then
|
||||||
|
echo "pwsh parse check failed due runtime environment; skipping."
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "pwsh not found, skipping."
|
echo "pwsh not found, skipping."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "[4/6] Install-kit consistency check"
|
||||||
|
./scripts/check_install_kit_vs_repo.sh
|
||||||
|
|
||||||
|
echo "[5/6] Generated-artifacts guard"
|
||||||
|
if git status --short | grep -E '^(\\?\\?| M|M ) (\\.graphify_|graphify-out/|reports/|tmp/|data/)'; then
|
||||||
|
echo "ERROR: generated artifacts detected in working tree. Clean or ignore them before rollout."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "[4/4] Ansible syntax check (if ansible-playbook available)"
|
echo "[6/6] Ansible syntax check (if ansible-playbook available)"
|
||||||
if command -v ansible-playbook >/dev/null 2>&1; then
|
if command -v ansible-playbook >/dev/null 2>&1; then
|
||||||
for playbook in ansible/*.yml; do
|
for playbook in ansible/*.yml; do
|
||||||
ansible-playbook --syntax-check "$playbook" -i ansible/inventory.example.ini >/dev/null
|
ansible-playbook --syntax-check "$playbook" -i ansible/inventory.example.ini >/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user