atfield 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- atfield-0.4.2/.github/workflows/ci.yml +78 -0
- atfield-0.4.2/.github/workflows/release.yml +291 -0
- atfield-0.4.2/.gitignore +61 -0
- atfield-0.4.2/CHANGELOG.md +357 -0
- atfield-0.4.2/LICENSE +21 -0
- atfield-0.4.2/LICENSE-third-party.md +57 -0
- atfield-0.4.2/PKG-INFO +277 -0
- atfield-0.4.2/README.md +235 -0
- atfield-0.4.2/at-field-tray/.gitignore +20 -0
- atfield-0.4.2/at-field-tray/README.md +66 -0
- atfield-0.4.2/at-field-tray/index.html +13 -0
- atfield-0.4.2/at-field-tray/package-lock.json +2771 -0
- atfield-0.4.2/at-field-tray/package.json +33 -0
- atfield-0.4.2/at-field-tray/public/app-icon.png +0 -0
- atfield-0.4.2/at-field-tray/scripts/gen_icons.py +224 -0
- atfield-0.4.2/at-field-tray/src/App.tsx +176 -0
- atfield-0.4.2/at-field-tray/src/components/AboutModal.tsx +199 -0
- atfield-0.4.2/at-field-tray/src/components/AdvancedRuleControls.tsx +272 -0
- atfield-0.4.2/at-field-tray/src/components/KillToast.tsx +117 -0
- atfield-0.4.2/at-field-tray/src/components/ProfilePresetRow.tsx +125 -0
- atfield-0.4.2/at-field-tray/src/components/RuleThresholdSlider.tsx +201 -0
- atfield-0.4.2/at-field-tray/src/components/Sparkline.tsx +345 -0
- atfield-0.4.2/at-field-tray/src/components/StatusHeader.tsx +98 -0
- atfield-0.4.2/at-field-tray/src/lib/api.ts +329 -0
- atfield-0.4.2/at-field-tray/src/lib/format.ts +601 -0
- atfield-0.4.2/at-field-tray/src/lib/hooks.ts +80 -0
- atfield-0.4.2/at-field-tray/src/lib/preferences.ts +62 -0
- atfield-0.4.2/at-field-tray/src/lib/signal-order.ts +69 -0
- atfield-0.4.2/at-field-tray/src/lib/signal-visibility.ts +107 -0
- atfield-0.4.2/at-field-tray/src/lib/tauri.ts +76 -0
- atfield-0.4.2/at-field-tray/src/lib/theme.ts +281 -0
- atfield-0.4.2/at-field-tray/src/main.tsx +13 -0
- atfield-0.4.2/at-field-tray/src/screens/EventsScreen.tsx +284 -0
- atfield-0.4.2/at-field-tray/src/screens/PrefsScreen.tsx +188 -0
- atfield-0.4.2/at-field-tray/src/screens/RulesScreen.tsx +255 -0
- atfield-0.4.2/at-field-tray/src/screens/SetupScreen.tsx +202 -0
- atfield-0.4.2/at-field-tray/src/screens/SignalDetailScreen.tsx +557 -0
- atfield-0.4.2/at-field-tray/src/screens/SignalsScreen.tsx +484 -0
- atfield-0.4.2/at-field-tray/src/screens/StatusScreen.tsx +274 -0
- atfield-0.4.2/at-field-tray/src/styles/globals.css +735 -0
- atfield-0.4.2/at-field-tray/src-tauri/Cargo.toml +43 -0
- atfield-0.4.2/at-field-tray/src-tauri/build.rs +3 -0
- atfield-0.4.2/at-field-tray/src-tauri/capabilities/default.json +19 -0
- atfield-0.4.2/at-field-tray/src-tauri/icons/128x128.png +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/icons/128x128@2x.png +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/icons/32x32.png +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/icons/icon.ico +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/icons/icon.png +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/icons/tray.png +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/installer/header.bmp +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/installer/hooks.nsh +33 -0
- atfield-0.4.2/at-field-tray/src-tauri/installer/sidebar.bmp +0 -0
- atfield-0.4.2/at-field-tray/src-tauri/src/autostart.rs +147 -0
- atfield-0.4.2/at-field-tray/src-tauri/src/caption_color.rs +131 -0
- atfield-0.4.2/at-field-tray/src-tauri/src/lib.rs +519 -0
- atfield-0.4.2/at-field-tray/src-tauri/src/main.rs +6 -0
- atfield-0.4.2/at-field-tray/src-tauri/src/service_installer.rs +249 -0
- atfield-0.4.2/at-field-tray/src-tauri/tauri.conf.json +88 -0
- atfield-0.4.2/at-field-tray/tsconfig.json +21 -0
- atfield-0.4.2/at-field-tray/tsconfig.node.json +11 -0
- atfield-0.4.2/at-field-tray/vite.config.ts +29 -0
- atfield-0.4.2/brand/README.md +50 -0
- atfield-0.4.2/brand/logo_1024.png +0 -0
- atfield-0.4.2/brand/logo_1024_thick.png +0 -0
- atfield-0.4.2/brand/logo_16.png +0 -0
- atfield-0.4.2/brand/logo_28.png +0 -0
- atfield-0.4.2/brand/logo_32.png +0 -0
- atfield-0.4.2/brand/logo_48.png +0 -0
- atfield-0.4.2/docs/blog/awesome-list-submissions.md +55 -0
- atfield-0.4.2/docs/blog/launch-post.md +197 -0
- atfield-0.4.2/docs/faq.md +325 -0
- atfield-0.4.2/docs/footprint.md +170 -0
- atfield-0.4.2/docs/install.md +123 -0
- atfield-0.4.2/docs/packaging.md +192 -0
- atfield-0.4.2/docs/sensors.md +362 -0
- atfield-0.4.2/docs/tuning.md +169 -0
- atfield-0.4.2/helper/AtfieldSensors.cs +324 -0
- atfield-0.4.2/packaging/pyinstaller/atf_entry.py +40 -0
- atfield-0.4.2/packaging/pyinstaller/atfield.spec +173 -0
- atfield-0.4.2/packaging/pyinstaller/atfield_service_entry.py +36 -0
- atfield-0.4.2/pyproject.toml +90 -0
- atfield-0.4.2/scripts/bench_tick.py +128 -0
- atfield-0.4.2/scripts/build_helper.ps1 +41 -0
- atfield-0.4.2/scripts/config.example.toml +134 -0
- atfield-0.4.2/scripts/fetch_lhm.ps1 +118 -0
- atfield-0.4.2/scripts/gen_installer_images.py +94 -0
- atfield-0.4.2/scripts/grant_service_control.ps1 +77 -0
- atfield-0.4.2/scripts/install_service.ps1 +323 -0
- atfield-0.4.2/scripts/measure_idle.py +109 -0
- atfield-0.4.2/scripts/probe_lhm_lib.ps1 +88 -0
- atfield-0.4.2/scripts/uninstall_service.ps1 +56 -0
- atfield-0.4.2/scripts/vendor/nssm.exe +0 -0
- atfield-0.4.2/src/atfield/__init__.py +22 -0
- atfield-0.4.2/src/atfield/actuator.py +728 -0
- atfield-0.4.2/src/atfield/audit.py +221 -0
- atfield-0.4.2/src/atfield/cli.py +1216 -0
- atfield-0.4.2/src/atfield/collectors/__init__.py +195 -0
- atfield-0.4.2/src/atfield/collectors/amd.py +269 -0
- atfield-0.4.2/src/atfield/collectors/lhm.py +394 -0
- atfield-0.4.2/src/atfield/collectors/lhmlib.py +473 -0
- atfield-0.4.2/src/atfield/collectors/nvml.py +336 -0
- atfield-0.4.2/src/atfield/collectors/system.py +176 -0
- atfield-0.4.2/src/atfield/config.py +613 -0
- atfield-0.4.2/src/atfield/config_writer.py +393 -0
- atfield-0.4.2/src/atfield/forensics.py +331 -0
- atfield-0.4.2/src/atfield/http_api.py +1120 -0
- atfield-0.4.2/src/atfield/lhm_config.py +281 -0
- atfield-0.4.2/src/atfield/lhm_supervisor.py +734 -0
- atfield-0.4.2/src/atfield/policy.py +340 -0
- atfield-0.4.2/src/atfield/prometheus_exporter.py +234 -0
- atfield-0.4.2/src/atfield/rule_profiles.py +150 -0
- atfield-0.4.2/src/atfield/service.py +657 -0
- atfield-0.4.2/src/atfield/signals.py +356 -0
- atfield-0.4.2/tests/__init__.py +0 -0
- atfield-0.4.2/tests/conftest.py +41 -0
- atfield-0.4.2/tests/test_actuator.py +577 -0
- atfield-0.4.2/tests/test_amd_collector.py +168 -0
- atfield-0.4.2/tests/test_audit.py +215 -0
- atfield-0.4.2/tests/test_cli_doctor_setprofile.py +209 -0
- atfield-0.4.2/tests/test_cli_install.py +140 -0
- atfield-0.4.2/tests/test_cli_install_lhm.py +156 -0
- atfield-0.4.2/tests/test_collectors.py +241 -0
- atfield-0.4.2/tests/test_config.py +341 -0
- atfield-0.4.2/tests/test_config_writer.py +296 -0
- atfield-0.4.2/tests/test_forensics.py +248 -0
- atfield-0.4.2/tests/test_http_api.py +843 -0
- atfield-0.4.2/tests/test_lhm_config.py +189 -0
- atfield-0.4.2/tests/test_lhm_supervisor.py +621 -0
- atfield-0.4.2/tests/test_lhmlib.py +142 -0
- atfield-0.4.2/tests/test_multires_history.py +231 -0
- atfield-0.4.2/tests/test_policy.py +274 -0
- atfield-0.4.2/tests/test_prometheus_exporter.py +223 -0
- atfield-0.4.2/tests/test_rule_profiles.py +79 -0
- atfield-0.4.2/tests/test_signals.py +261 -0
- atfield-0.4.2/vendor/lhm/.gitignore +8 -0
- atfield-0.4.2/vendor/lhm/README.md +70 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Test (${{ matrix.os }} / Python ${{ matrix.python-version }})
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
# Production target is Windows; cross-platform tests guard with skipif
|
|
20
|
+
# so the suite is green on Linux too. Two OS rows ensures we don't
|
|
21
|
+
# accidentally introduce a Windows-only or Linux-only regression.
|
|
22
|
+
os: [windows-latest, ubuntu-latest]
|
|
23
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
|
|
27
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
28
|
+
uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
31
|
+
cache: pip
|
|
32
|
+
cache-dependency-path: pyproject.toml
|
|
33
|
+
|
|
34
|
+
- name: Install package + dev deps
|
|
35
|
+
run: |
|
|
36
|
+
python -m pip install --upgrade pip
|
|
37
|
+
python -m pip install -e ".[dev]"
|
|
38
|
+
|
|
39
|
+
- name: Lint with ruff
|
|
40
|
+
run: ruff check src/ tests/
|
|
41
|
+
|
|
42
|
+
- name: Run tests
|
|
43
|
+
run: pytest tests/ -v --tb=short
|
|
44
|
+
|
|
45
|
+
smoke:
|
|
46
|
+
# Fast end-to-end sanity check: build the wheel, install it into a fresh
|
|
47
|
+
# venv, run `atf inputs` (which exercises every collector probe) and `atf
|
|
48
|
+
# version`. Catches packaging regressions that pure pytest can miss.
|
|
49
|
+
name: Wheel + CLI smoke
|
|
50
|
+
runs-on: windows-latest
|
|
51
|
+
needs: test
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
- uses: actions/setup-python@v5
|
|
55
|
+
with:
|
|
56
|
+
python-version: '3.12'
|
|
57
|
+
|
|
58
|
+
- name: Build wheel
|
|
59
|
+
run: |
|
|
60
|
+
python -m pip install --upgrade pip build
|
|
61
|
+
python -m build --wheel
|
|
62
|
+
|
|
63
|
+
- name: Install built wheel into a fresh venv
|
|
64
|
+
run: |
|
|
65
|
+
python -m venv ci-smoke-venv
|
|
66
|
+
ci-smoke-venv\Scripts\python.exe -m pip install --upgrade pip
|
|
67
|
+
$wheel = (Get-ChildItem -Path dist -Filter atfield-*.whl | Select-Object -First 1).FullName
|
|
68
|
+
ci-smoke-venv\Scripts\python.exe -m pip install $wheel
|
|
69
|
+
shell: pwsh
|
|
70
|
+
|
|
71
|
+
- name: atf version
|
|
72
|
+
run: ci-smoke-venv\Scripts\atf.exe version
|
|
73
|
+
|
|
74
|
+
- name: atf inputs (probes every collector)
|
|
75
|
+
# CI has no NVIDIA GPU and no LHM, so this is the
|
|
76
|
+
# capability-negotiation-on-bare-metal scenario. Should report system
|
|
77
|
+
# collector OK, NVML unavailable, LHM unavailable -- and exit 0.
|
|
78
|
+
run: ci-smoke-venv\Scripts\atf.exe inputs
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Triggered on annotated tag pushes that match v* (semver tags).
|
|
4
|
+
# Builds the Python wheel + the standalone PyInstaller bundle + the
|
|
5
|
+
# Tauri tray app installer, then attaches everything to a GitHub
|
|
6
|
+
# Release. Manual runs are also allowed via workflow_dispatch so you
|
|
7
|
+
# can produce a draft release without tagging first.
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
tags:
|
|
11
|
+
- "v*"
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
tag:
|
|
15
|
+
description: "Release tag to publish (e.g. v0.2.0). Leave blank to draft from current main."
|
|
16
|
+
required: false
|
|
17
|
+
default: ""
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
# Need write access to publish a release + upload assets. The
|
|
21
|
+
# built-in GITHUB_TOKEN is used; no PAT.
|
|
22
|
+
contents: write
|
|
23
|
+
|
|
24
|
+
# Avoid two concurrent release runs (e.g. tag push + manual dispatch
|
|
25
|
+
# at the same time) racing for the same release upload.
|
|
26
|
+
concurrency:
|
|
27
|
+
group: release-${{ github.ref }}
|
|
28
|
+
cancel-in-progress: false
|
|
29
|
+
|
|
30
|
+
jobs:
|
|
31
|
+
# ─────────────────────────────────────────────────────────────────
|
|
32
|
+
# 1. Pure-Python wheel (cross-platform, no GPU deps in the build).
|
|
33
|
+
# ─────────────────────────────────────────────────────────────────
|
|
34
|
+
wheel:
|
|
35
|
+
name: Build wheel + sdist
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v4
|
|
39
|
+
|
|
40
|
+
- uses: actions/setup-python@v5
|
|
41
|
+
with:
|
|
42
|
+
python-version: "3.12"
|
|
43
|
+
cache: pip
|
|
44
|
+
cache-dependency-path: pyproject.toml
|
|
45
|
+
|
|
46
|
+
- name: Build wheel + sdist
|
|
47
|
+
run: |
|
|
48
|
+
python -m pip install --upgrade pip build
|
|
49
|
+
python -m build
|
|
50
|
+
|
|
51
|
+
- name: Upload artifacts
|
|
52
|
+
uses: actions/upload-artifact@v4
|
|
53
|
+
with:
|
|
54
|
+
name: python-dists
|
|
55
|
+
path: dist/*
|
|
56
|
+
retention-days: 7
|
|
57
|
+
|
|
58
|
+
# ─────────────────────────────────────────────────────────────────
|
|
59
|
+
# 1b. Publish the wheel + sdist to PyPI via Trusted Publishing (OIDC).
|
|
60
|
+
#
|
|
61
|
+
# No API token/secret: PyPI verifies the GitHub OIDC identity. This
|
|
62
|
+
# requires a one-time "pending publisher" set up on PyPI pointing at
|
|
63
|
+
# this repo + workflow + the `pypi` environment (see docs/packaging.md).
|
|
64
|
+
# Runs only for real (non-prerelease) version tags. A failure here does
|
|
65
|
+
# NOT block the GitHub Release job below -- they're independent.
|
|
66
|
+
# ─────────────────────────────────────────────────────────────────
|
|
67
|
+
publish-pypi:
|
|
68
|
+
name: Publish to PyPI
|
|
69
|
+
needs: wheel
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
if: startsWith(github.ref, 'refs/tags/v') && !contains(github.ref_name, '-')
|
|
72
|
+
environment:
|
|
73
|
+
name: pypi
|
|
74
|
+
url: https://pypi.org/project/atfield/
|
|
75
|
+
permissions:
|
|
76
|
+
id-token: write
|
|
77
|
+
steps:
|
|
78
|
+
- name: Download wheel + sdist
|
|
79
|
+
uses: actions/download-artifact@v4
|
|
80
|
+
with:
|
|
81
|
+
name: python-dists
|
|
82
|
+
path: dist
|
|
83
|
+
|
|
84
|
+
- name: Publish to PyPI
|
|
85
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
86
|
+
|
|
87
|
+
# ─────────────────────────────────────────────────────────────────
|
|
88
|
+
# 2. Standalone PyInstaller bundle (Windows-only).
|
|
89
|
+
# Produces dist/atfield/ with atfield-service.exe + atf.exe and
|
|
90
|
+
# a shared _internal/. Zips it for the GitHub release.
|
|
91
|
+
# ─────────────────────────────────────────────────────────────────
|
|
92
|
+
standalone:
|
|
93
|
+
name: Standalone Windows bundle
|
|
94
|
+
runs-on: windows-latest
|
|
95
|
+
steps:
|
|
96
|
+
- uses: actions/checkout@v4
|
|
97
|
+
|
|
98
|
+
- uses: actions/setup-python@v5
|
|
99
|
+
with:
|
|
100
|
+
python-version: "3.12"
|
|
101
|
+
cache: pip
|
|
102
|
+
cache-dependency-path: pyproject.toml
|
|
103
|
+
|
|
104
|
+
- name: Install package + PyInstaller
|
|
105
|
+
run: |
|
|
106
|
+
python -m pip install --upgrade pip
|
|
107
|
+
python -m pip install -e ".[dev]"
|
|
108
|
+
python -m pip install "pyinstaller>=6.20"
|
|
109
|
+
|
|
110
|
+
- name: Build standalone bundle
|
|
111
|
+
run: pyinstaller --noconfirm --clean packaging/pyinstaller/atfield.spec
|
|
112
|
+
|
|
113
|
+
# Vendor LHM into the bundle so the watchdog ships VRAM-junction
|
|
114
|
+
# and CPU-package temp support out of the box. fetch_lhm.ps1 drops
|
|
115
|
+
# LibreHardwareMonitor.exe + its DLLs into dist/atfield/ where
|
|
116
|
+
# find_lhm_executable() looks first (next to atfield-service.exe).
|
|
117
|
+
- name: Vendor LibreHardwareMonitor
|
|
118
|
+
shell: pwsh
|
|
119
|
+
run: pwsh scripts/fetch_lhm.ps1
|
|
120
|
+
|
|
121
|
+
# Compile the headless sensor helper (atfield-sensors.exe) against the
|
|
122
|
+
# LibreHardwareMonitorLib.dll just vendored. Uses the in-box .NET
|
|
123
|
+
# Framework csc.exe (present on windows-latest), so no SDK install.
|
|
124
|
+
# The tray installer's resources manifest REQUIRES this exe, so the
|
|
125
|
+
# tray-installer job would fail without it.
|
|
126
|
+
- name: Build headless sensor helper
|
|
127
|
+
shell: pwsh
|
|
128
|
+
run: pwsh scripts/build_helper.ps1
|
|
129
|
+
|
|
130
|
+
- name: Smoke-test bundled binaries
|
|
131
|
+
# Make sure the frozen exes at least respond to --help before we
|
|
132
|
+
# ship them. Catches missing hidden imports / data files, and that
|
|
133
|
+
# the sensor helper actually built.
|
|
134
|
+
shell: pwsh
|
|
135
|
+
run: |
|
|
136
|
+
dist/atfield/atf.exe version
|
|
137
|
+
dist/atfield/atf.exe inputs
|
|
138
|
+
if (-not (Test-Path dist/atfield/atfield-sensors.exe)) {
|
|
139
|
+
throw "atfield-sensors.exe missing -- build_helper.ps1 did not produce the sensor helper."
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
- name: Zip standalone bundle
|
|
143
|
+
shell: pwsh
|
|
144
|
+
run: |
|
|
145
|
+
$version = "${{ github.ref_name }}".TrimStart('v')
|
|
146
|
+
if (-not $version) { $version = "dev" }
|
|
147
|
+
Compress-Archive -Path dist/atfield/* -DestinationPath "dist/atfield-$version-windows-x64.zip"
|
|
148
|
+
|
|
149
|
+
- name: Upload standalone bundle
|
|
150
|
+
uses: actions/upload-artifact@v4
|
|
151
|
+
with:
|
|
152
|
+
name: standalone-bundle
|
|
153
|
+
path: dist/atfield-*-windows-x64.zip
|
|
154
|
+
retention-days: 7
|
|
155
|
+
|
|
156
|
+
# ─────────────────────────────────────────────────────────────────
|
|
157
|
+
# 3. Tauri tray app installer (Windows NSIS).
|
|
158
|
+
#
|
|
159
|
+
# Depends on `standalone` so we can stage dist/atfield/ -- the Tauri
|
|
160
|
+
# config references it as bundle.resources, producing a single
|
|
161
|
+
# installer that ships BOTH the tray app AND the watchdog binaries.
|
|
162
|
+
# ─────────────────────────────────────────────────────────────────
|
|
163
|
+
tray-installer:
|
|
164
|
+
name: Tauri tray installer
|
|
165
|
+
runs-on: windows-latest
|
|
166
|
+
needs: standalone
|
|
167
|
+
steps:
|
|
168
|
+
- uses: actions/checkout@v4
|
|
169
|
+
|
|
170
|
+
- uses: actions/setup-node@v4
|
|
171
|
+
with:
|
|
172
|
+
node-version: "20"
|
|
173
|
+
cache: "npm"
|
|
174
|
+
cache-dependency-path: at-field-tray/package-lock.json
|
|
175
|
+
|
|
176
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
177
|
+
with:
|
|
178
|
+
targets: x86_64-pc-windows-msvc
|
|
179
|
+
|
|
180
|
+
- uses: Swatinem/rust-cache@v2
|
|
181
|
+
with:
|
|
182
|
+
workspaces: "at-field-tray/src-tauri -> target"
|
|
183
|
+
|
|
184
|
+
# Re-stage the standalone bundle artifact at dist/atfield/ so
|
|
185
|
+
# bundle.resources in tauri.conf.json resolves correctly.
|
|
186
|
+
- name: Download standalone bundle
|
|
187
|
+
uses: actions/download-artifact@v4
|
|
188
|
+
with:
|
|
189
|
+
name: standalone-bundle
|
|
190
|
+
path: standalone-zip
|
|
191
|
+
|
|
192
|
+
- name: Stage standalone at dist/atfield/
|
|
193
|
+
shell: pwsh
|
|
194
|
+
run: |
|
|
195
|
+
$zip = Get-ChildItem standalone-zip -Filter atfield-*-windows-x64.zip |
|
|
196
|
+
Select-Object -First 1
|
|
197
|
+
if (-not $zip) { throw "Standalone bundle artifact missing." }
|
|
198
|
+
New-Item -ItemType Directory -Path dist/atfield -Force | Out-Null
|
|
199
|
+
Expand-Archive -Path $zip.FullName -DestinationPath dist/atfield -Force
|
|
200
|
+
Get-ChildItem dist/atfield | Format-Table -AutoSize
|
|
201
|
+
|
|
202
|
+
- name: Install npm deps
|
|
203
|
+
working-directory: at-field-tray
|
|
204
|
+
run: npm ci
|
|
205
|
+
|
|
206
|
+
- name: Build Tauri NSIS installer
|
|
207
|
+
working-directory: at-field-tray
|
|
208
|
+
run: npm run tauri build -- --bundles nsis
|
|
209
|
+
|
|
210
|
+
- name: Locate installer
|
|
211
|
+
id: locate
|
|
212
|
+
shell: pwsh
|
|
213
|
+
run: |
|
|
214
|
+
$exe = Get-ChildItem -Path at-field-tray/src-tauri/target/release/bundle/nsis -Filter *-setup.exe |
|
|
215
|
+
Select-Object -First 1
|
|
216
|
+
if (-not $exe) { throw "No NSIS installer produced." }
|
|
217
|
+
"exe=$($exe.FullName)" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
|
|
218
|
+
|
|
219
|
+
- name: Upload tray installer
|
|
220
|
+
uses: actions/upload-artifact@v4
|
|
221
|
+
with:
|
|
222
|
+
name: tray-installer
|
|
223
|
+
path: ${{ steps.locate.outputs.exe }}
|
|
224
|
+
retention-days: 7
|
|
225
|
+
|
|
226
|
+
# ─────────────────────────────────────────────────────────────────
|
|
227
|
+
# 4. Publish: gather every artifact and create / update the release.
|
|
228
|
+
# ─────────────────────────────────────────────────────────────────
|
|
229
|
+
publish:
|
|
230
|
+
name: Publish GitHub Release
|
|
231
|
+
needs: [wheel, standalone, tray-installer]
|
|
232
|
+
runs-on: ubuntu-latest
|
|
233
|
+
# Only publish for real on actual tag pushes. workflow_dispatch
|
|
234
|
+
# runs upload artifacts but skip the release step (lets you
|
|
235
|
+
# validate the build without making noise).
|
|
236
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
237
|
+
steps:
|
|
238
|
+
- uses: actions/checkout@v4
|
|
239
|
+
# Need full history so the release notes generator can walk
|
|
240
|
+
# since the previous tag.
|
|
241
|
+
with:
|
|
242
|
+
fetch-depth: 0
|
|
243
|
+
|
|
244
|
+
- name: Download all artifacts
|
|
245
|
+
uses: actions/download-artifact@v4
|
|
246
|
+
with:
|
|
247
|
+
path: release-assets
|
|
248
|
+
merge-multiple: true
|
|
249
|
+
|
|
250
|
+
- name: List collected assets
|
|
251
|
+
run: ls -lh release-assets/
|
|
252
|
+
|
|
253
|
+
- name: Extract changelog section for this version
|
|
254
|
+
id: changelog
|
|
255
|
+
shell: bash
|
|
256
|
+
run: |
|
|
257
|
+
set -euo pipefail
|
|
258
|
+
version_tag="${GITHUB_REF_NAME}" # e.g. v0.2.0
|
|
259
|
+
version_no_v="${version_tag#v}" # e.g. 0.2.0
|
|
260
|
+
# Pull the section between `## [<version>]` and the next `## `.
|
|
261
|
+
# Falls back to a generic message if no matching section.
|
|
262
|
+
notes=$(awk -v ver="$version_no_v" '
|
|
263
|
+
BEGIN { inside=0 }
|
|
264
|
+
/^## \[/ {
|
|
265
|
+
if (inside) exit
|
|
266
|
+
if ($0 ~ "\\[" ver "\\]") { inside=1; next }
|
|
267
|
+
}
|
|
268
|
+
inside { print }
|
|
269
|
+
' CHANGELOG.md || true)
|
|
270
|
+
if [ -z "$notes" ]; then
|
|
271
|
+
notes="See CHANGELOG.md for details."
|
|
272
|
+
fi
|
|
273
|
+
# Multi-line outputs go through GITHUB_OUTPUT with a delimiter.
|
|
274
|
+
delim=$(openssl rand -hex 8)
|
|
275
|
+
{
|
|
276
|
+
printf 'notes<<%s\n' "$delim"
|
|
277
|
+
printf '%s\n' "$notes"
|
|
278
|
+
printf '%s\n' "$delim"
|
|
279
|
+
} >> "$GITHUB_OUTPUT"
|
|
280
|
+
|
|
281
|
+
- name: Create / update GitHub Release
|
|
282
|
+
uses: softprops/action-gh-release@v2
|
|
283
|
+
with:
|
|
284
|
+
tag_name: ${{ github.ref_name }}
|
|
285
|
+
name: AT-Field ${{ github.ref_name }}
|
|
286
|
+
body: ${{ steps.changelog.outputs.notes }}
|
|
287
|
+
files: release-assets/*
|
|
288
|
+
draft: false
|
|
289
|
+
prerelease: ${{ contains(github.ref_name, '-') }}
|
|
290
|
+
env:
|
|
291
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
atfield-0.4.2/.gitignore
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
*.egg
|
|
11
|
+
.eggs/
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.tox/
|
|
16
|
+
.coverage
|
|
17
|
+
htmlcov/
|
|
18
|
+
|
|
19
|
+
# Virtual environments
|
|
20
|
+
.venv/
|
|
21
|
+
venv/
|
|
22
|
+
env/
|
|
23
|
+
ENV/
|
|
24
|
+
|
|
25
|
+
# IDE
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
.cursor/
|
|
31
|
+
|
|
32
|
+
# OS
|
|
33
|
+
.DS_Store
|
|
34
|
+
Thumbs.db
|
|
35
|
+
desktop.ini
|
|
36
|
+
|
|
37
|
+
# AT-Field local artifacts
|
|
38
|
+
local_state/
|
|
39
|
+
*.log
|
|
40
|
+
events.jsonl
|
|
41
|
+
nssm.exe
|
|
42
|
+
# ...but the vendored NSSM that ships in the installer IS tracked on purpose
|
|
43
|
+
# (install_service.ps1 copies it so setup never depends on the flaky nssm.cc).
|
|
44
|
+
!scripts/vendor/nssm.exe
|
|
45
|
+
resources/LibreHardwareMonitor/
|
|
46
|
+
|
|
47
|
+
# PyInstaller -- generated specs only. Keep our authored spec under packaging/.
|
|
48
|
+
/*.spec
|
|
49
|
+
/build/
|
|
50
|
+
/dist/
|
|
51
|
+
|
|
52
|
+
# Planning / handoff docs — kept local, not in git history
|
|
53
|
+
/PLANNING.md
|
|
54
|
+
/docs/chat-history.md
|
|
55
|
+
/docs/planning/
|
|
56
|
+
|
|
57
|
+
# Ad-hoc diagnostic scripts + reports (crash investigations, font A/Bs, etc.)
|
|
58
|
+
/diag-*.ps1
|
|
59
|
+
/diag-*-report.txt
|
|
60
|
+
/font-comparison.html
|
|
61
|
+
/nul
|