From f436950bda7ecf3f6754c41076824f1b5eff3327 Mon Sep 17 00:00:00 2001 From: igor04091968 Date: Sat, 2 May 2026 19:36:25 +0300 Subject: [PATCH] Update after codex restore --- ansible/deploy_aw_server.yml | 83 +++++++++++++++++++---- ansible/deploy_aw_windows.yml | 13 ++++ ansible/group_vars/all.example.yml | 14 +++- ansible/group_vars/all.yml | 9 ++- aw-server/activitywatch-server.service | 2 +- windows/ActivityWatch.Windows.Common.psm1 | 32 +++++++++ 6 files changed, 135 insertions(+), 18 deletions(-) diff --git a/ansible/deploy_aw_server.yml b/ansible/deploy_aw_server.yml index 3f84e58..f553a4c 100644 --- a/ansible/deploy_aw_server.yml +++ b/ansible/deploy_aw_server.yml @@ -54,6 +54,10 @@ - "{{ aw_server_webui_dir }}" - "{{ aw_server_webui_dir }}/js" - "{{ aw_server_data_dir }}" + - "{{ aw_server_data_dir }}/.config" + - "{{ aw_server_data_dir }}/.config/activitywatch" + - "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust" + - "{{ aw_server_data_dir }}/backups" - "{{ aw_server_log_dir }}" - /etc/activitywatch - "{{ aw_bootstrap_dir }}" @@ -74,6 +78,10 @@ - "{{ aw_server_webui_dir }}" - "{{ aw_server_webui_dir }}/js" - "{{ aw_server_data_dir }}" + - "{{ aw_server_data_dir }}/.config" + - "{{ aw_server_data_dir }}/.config/activitywatch" + - "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust" + - "{{ aw_server_data_dir }}/backups" - "{{ aw_server_log_dir }}" - name: (Check mode) Пропустить установку релиза ActivityWatch @@ -290,6 +298,19 @@ AW_SERVER_USER={{ aw_server_user }} AW_SERVER_GROUP={{ aw_server_group }} + - name: Записать aw-server-rust config.toml с разрешёнными CORS origin + ansible.builtin.copy: + dest: "{{ aw_server_data_dir }}/.config/activitywatch/aw-server-rust/config.toml" + owner: "{{ aw_server_user }}" + group: "{{ aw_server_group }}" + mode: "0644" + content: | + cors = [ + {% for origin in aw_server_cors_origins | default([]) %} + "{{ origin }}"{% if not loop.last %},{% endif %} + {% endfor %} + ] + - name: Включить и запустить сервис ansible.builtin.systemd: name: activitywatch-server.service @@ -307,6 +328,46 @@ delay: 3 until: aw_api.status == 200 + - name: Считать текущие server-side settings + ansible.builtin.uri: + url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/" + method: GET + status_code: 200 + register: aw_settings_current + when: aw_apply_worktime_settings | default(false) | bool + + - name: Считать текущие server-side views + ansible.builtin.uri: + url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/views" + method: GET + status_code: 200 + register: aw_views_current + when: aw_apply_worktime_settings | default(false) | bool + + - name: Считать текущие server-side classes + ansible.builtin.uri: + url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/classes" + method: GET + status_code: 200 + register: aw_classes_current + when: aw_apply_worktime_settings | default(false) | bool + + - name: Сохранить backup текущих server-side settings/views/classes + ansible.builtin.copy: + dest: "{{ aw_server_data_dir }}/backups/{{ item.name }}-{{ ansible_date_time.iso8601_basic_short }}.json" + owner: "{{ aw_server_user }}" + group: "{{ aw_server_group }}" + mode: "0644" + content: "{{ item.payload | to_nice_json }}" + loop: + - name: settings + payload: "{{ aw_settings_current.json | default({}) }}" + - name: views + payload: "{{ aw_views_current.json | default(none) }}" + - name: classes + payload: "{{ aw_classes_current.json | default(none) }}" + when: aw_apply_worktime_settings | default(false) | bool + - name: Применить базовые worktime settings (classes) ansible.builtin.uri: url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/classes" @@ -327,16 +388,12 @@ - name: Вычислить worktime durationDefault из aw_worktime_from/to ansible.builtin.set_fact: - aw_worktime_from_h: "{{ (aw_worktime_from | default('08:00')).split(':')[0] | int }}" - aw_worktime_from_m: "{{ (aw_worktime_from | default('08:00')).split(':')[1] | int }}" - aw_worktime_to_h: "{{ (aw_worktime_to | default('17:00')).split(':')[0] | int }}" - aw_worktime_to_m: "{{ (aw_worktime_to | default('17:00')).split(':')[1] | int }}" aw_worktime_duration_default_derived: >- {{ ( ( - ((aw_worktime_to_h | int) * 60 + (aw_worktime_to_m | int)) - - ((aw_worktime_from_h | int) * 60 + (aw_worktime_from_m | int)) + (((aw_worktime_to | default('17:00')).split(':')[0] | int) * 60 + ((aw_worktime_to | default('17:00')).split(':')[1] | int)) - + (((aw_worktime_from | default('08:00')).split(':')[0] | int) * 60 + ((aw_worktime_from | default('08:00')).split(':')[1] | int)) ) * 60 ) }} @@ -364,18 +421,20 @@ ansible.builtin.uri: url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/startOfDay" method: POST - body: "{{ aw_worktime_start_of_day }}" - body_format: json - status_code: 200 + body: "\"{{ aw_worktime_start_of_day }}\"" + headers: + Content-Type: application/json + status_code: [200, 201] when: aw_apply_worktime_settings | default(false) | bool - name: Применить базовый период worktime (durationDefault seconds) ansible.builtin.uri: url: "http://127.0.0.1:{{ aw_server_port }}/api/0/settings/durationDefault" method: POST - body: "{{ aw_worktime_duration_default_effective }}" - body_format: json - status_code: 200 + body: "{{ aw_worktime_duration_default_effective | string }}" + headers: + Content-Type: application/json + status_code: [200, 201] when: aw_apply_worktime_settings | default(false) | bool handlers: diff --git a/ansible/deploy_aw_windows.yml b/ansible/deploy_aw_windows.yml index 9fac90b..349f262 100644 --- a/ansible/deploy_aw_windows.yml +++ b/ansible/deploy_aw_windows.yml @@ -161,6 +161,19 @@ {% endif %} & "{{ aw_windows_deploy_root }}\windows\deploy-ensemble.ps1" @params + - name: Удалить лишние ActivityWatch Launch tasks вне текущего deployment-config + ansible.windows.win_powershell: + script: | + $ErrorActionPreference = 'Stop' + $config = Get-Content -Raw -LiteralPath "{{ aw_windows_state_root }}\deployment-config.json" | ConvertFrom-Json + $desired = @($config.userTasks | ForEach-Object { [string]$_.LaunchTaskName }) + foreach ($task in @(Get-ScheduledTask | Where-Object { $_.TaskName -like 'ActivityWatch Launch *' })) { + if ($desired -notcontains [string]$task.TaskName) { + Unregister-ScheduledTask -TaskName $task.TaskName -Confirm:$false -ErrorAction SilentlyContinue + & cmd.exe /c "schtasks /Delete /TN `"$($task.TaskName)`" /F >nul 2>&1" | Out-Null + } + } + - name: Принудительно запустить ActivityWatch recovery и launch tasks when: aw_windows_force_task_restart | bool ansible.windows.win_powershell: diff --git a/ansible/group_vars/all.example.yml b/ansible/group_vars/all.example.yml index 27d5703..7da0ad8 100644 --- a/ansible/group_vars/all.example.yml +++ b/ansible/group_vars/all.example.yml @@ -10,9 +10,17 @@ aw_server_group: "activitywatch" aw_repo_root: "{{ playbook_dir | dirname }}" -# Опционально: применить базовые категории и views для рабочего времени через AW settings API. -# Внимание: это перезаписывает существующие server-side settings/classes/views. -aw_apply_worktime_settings: false +# Применить базовые категории и views для рабочего времени через AW settings API. +# При прод-обновлениях это нужно оставлять включённым, иначе UI остаётся без views/classes. +aw_apply_worktime_settings: true + +# Дополнительные origin для aw-server-rust CORS. +# Обязательно включите тот origin, с которого реально открывается Web UI. +aw_server_cors_origins: + - "http://127.0.0.1:5600" + - "http://localhost:5600" + - "http://10.10.10.13:5600" + - "http://aw-server:5600" # Опциональные значения периода рабочего времени в Web UI. # startOfDay задаёт границу дня и стартовое время окна отчёта. diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml index 405771f..77fbcde 100644 --- a/ansible/group_vars/all.yml +++ b/ansible/group_vars/all.yml @@ -11,9 +11,14 @@ aw_server_group: "activitywatch" aw_repo_root: "{{ playbook_dir | dirname }}" # Optional: apply worktime settings via server-side settings API. -aw_apply_worktime_settings: false +aw_apply_worktime_settings: true + +aw_server_cors_origins: + - "http://127.0.0.1:5600" + - "http://localhost:5600" + - "http://10.10.10.13:5600" + - "http://aw-server:5600" aw_worktime_from: "08:00" aw_worktime_to: "17:00" aw_worktime_start_of_day: "{{ aw_worktime_from }}" - diff --git a/aw-server/activitywatch-server.service b/aw-server/activitywatch-server.service index e8f26e3..8481021 100755 --- a/aw-server/activitywatch-server.service +++ b/aw-server/activitywatch-server.service @@ -9,7 +9,7 @@ EnvironmentFile=/etc/activitywatch/aw-server.env User=__AW_SERVER_USER__ Group=__AW_SERVER_GROUP__ WorkingDirectory=__AW_SERVER_DATA_DIR__ -ExecStart=/bin/sh -lc 'exec /opt/activitywatch/bin/aw-server-rust --host "$AW_SERVER_BIND_HOST" --port "$AW_SERVER_PORT"' +ExecStart=/bin/sh -lc 'exec /opt/activitywatch/bin/aw-server-rust --host "$AW_SERVER_BIND_HOST" --port "$AW_SERVER_PORT" --webpath "$AW_SERVER_WEBUI_DIR"' Restart=on-failure RestartSec=5s StateDirectory=activitywatch diff --git a/windows/ActivityWatch.Windows.Common.psm1 b/windows/ActivityWatch.Windows.Common.psm1 index 6be39bd..c9954f1 100755 --- a/windows/ActivityWatch.Windows.Common.psm1 +++ b/windows/ActivityWatch.Windows.Common.psm1 @@ -908,6 +908,37 @@ function Get-ActivityWatchScheduledTaskByCommand { return $null } +function Remove-StaleActivityWatchUserTasks { + param( + [Parameter(Mandatory = $true)] + [pscustomobject[]]$TaskDefinitions, + [Parameter(Mandatory = $true)] + [string]$LaunchScriptPath + ) + + $launcherPath = Get-ActivityWatchHiddenLauncherPath -ScriptPath $LaunchScriptPath + $desiredTaskNames = @($TaskDefinitions | ForEach-Object { [string]$_.LaunchTaskName }) + + foreach ($candidate in @(Get-ScheduledTask | Where-Object { $_.TaskName -like 'ActivityWatch Launch*' })) { + $taskName = [string]$candidate.TaskName + if ($desiredTaskNames -contains $taskName) { + continue + } + + $usesCurrentLauncher = $false + foreach ($action in @($candidate.Actions)) { + if ([string]$action.Arguments -like "*$launcherPath*") { + $usesCurrentLauncher = $true + break + } + } + + if ($usesCurrentLauncher) { + Remove-ActivityWatchScheduledTask -TaskName $taskName + } + } +} + function Register-ActivityWatchUserTasks { param( [Parameter(Mandatory = $true)] @@ -921,6 +952,7 @@ function Register-ActivityWatchUserTasks { $wscriptExe = Join-Path $env:SystemRoot 'System32\wscript.exe' $launcherPath = Get-ActivityWatchHiddenLauncherPath -ScriptPath $LaunchScriptPath Write-ActivityWatchHiddenPowerShellWrapper -Path $launcherPath -ScriptPath $LaunchScriptPath -ConfigPath $ConfigPath + Remove-StaleActivityWatchUserTasks -TaskDefinitions $TaskDefinitions -LaunchScriptPath $LaunchScriptPath foreach ($definition in $TaskDefinitions) { $action = New-ScheduledTaskAction -Execute $wscriptExe -Argument "//B //NoLogo `"$launcherPath`""