Repository navigation
140 lines (135 loc) · 5.23 KB
/
Copy pathci.yml
File metadata and controls
140 lines (135 loc) · 5.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
name: CI
on:
push:
branches: [main]
pull_request:
# CI only reads the repo; deny everything else on the GITHUB_TOKEN.
permissions:
contents: read
jobs:
python:
name: python ${{ matrix.python }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python: ["3.11", "3.13"] # Debian stable + latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Install deps
run: pip install -r requirements.txt
- name: Byte-compile all Python
run: python -m compileall -q .
- name: Pipeline test (fixtures, no network)
run: python tests/test_pipeline.py
- name: Card contract + network-cards adapter
run: python tests/test_cards.py
- name: Dashboard routing (boots the server on a free port)
run: python tests/test_routes.py
- name: UniFi transforms + request path
run: python -m collectors.unifi
- name: Node identity + link resolution
run: python -m core.identity
- name: Collector parsers (arp-scan/nmap, SNMP, docker, tailscale)
run: |
python -m collectors.arpscan
python -m collectors.unifi_snmp
python -m collectors.docker
python -m collectors.tailscale
python -m collectors.dns
python -m collectors.pingsweep
python -m collectors.opnsense
# module self-checks — each module's __main__ asserts its own contract, offline.
# Keep this list identical to CONTRIBUTING.md → Tests.
- name: Path-injection barrier (shared by both stores)
run: python renderers/html/_guard.py
- name: Push-freshness cache (live/stale/miss)
run: python renderers/html/pushcache.py
- name: Store path-injection barrier + slug policy
run: python renderers/html/store.py
- name: Widget store CRUD round-trip
run: python renderers/html/widget_store.py
- name: Service-icon slug candidates
run: python renderers/html/icons.py
- name: HTML report escaping
run: python renderers/html/report.py
- name: Proxmox guest tiles
run: python renderers/html/pve_tiles.py
- name: Agent bundle builder (tar.gz/zip)
run: python renderers/html/agent_bundle.py
- name: Collector HTTP transport (ssl ctx + get_json)
run: python collectors/transport.py
- name: Widget SSRF guard
run: python -m widgets.net
- name: Widget engine (auth/mapping)
run: python -m widgets.engine
- name: Widget stat parsers + collector-backed SSRF guard
run: python -m widgets.fetchers
- name: Widget config + secret policy
run: python -m widgets.policy
- name: Widget catalog integrity + merge
run: python -m widgets.registry
- name: Linux collector self-test
run: python scanners/make_linux_topo.py --selftest
- name: Windows scanner helpers + shared cap vocabulary
run: python scanners/make_pc_topo.py --selftest
static:
name: shell + dashboard JS
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Bash syntax
run: for f in *.sh tests/*.sh; do echo "checking $f"; bash -n "$f"; done
- name: ShellCheck (advisory)
continue-on-error: true
run: shellcheck *.sh
- name: Uninstaller leaves the Unraid boot 'go' script intact
run: bash tests/test_uninstall_unraid.sh
- name: Dashboard JS syntax
run: |
python3 - <<'PY'
s = open("renderers/html/index.html", encoding="utf-8").read()
js = s[s.index("<script>") + 8 : s.rindex("</script>")]
open("dash.tmp.js", "w", encoding="utf-8").write(js)
print(f"extracted {len(js)} chars")
PY
node --check dash.tmp.js
- name: PowerShell files must be ASCII (PS 5.1 reads BOM-less files as ANSI)
run: |
python3 - <<'PY'
import glob, sys
bad = []
for f in glob.glob("*.ps1"):
data = open(f, "rb").read()
hits = [(i, b) for i, b in enumerate(data) if b > 127]
if hits:
bad.append((f, hits[:5]))
if bad:
for f, hits in bad:
print(f"::error file={f}::non-ASCII bytes at offsets {[h[0] for h in hits]} - use ASCII in .ps1")
sys.exit(1)
print("all .ps1 files are ASCII")
PY
powershell:
name: powershell 5.1 parse
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Parse .ps1 with Windows PowerShell 5.1
shell: powershell # 5.1 Desktop edition — matches what users run
run: |
$fail = $false
Get-ChildItem -Filter *.ps1 | ForEach-Object {
$e = $null
[System.Management.Automation.Language.Parser]::ParseFile($_.FullName, [ref]$null, [ref]$e) | Out-Null
if ($e) {
$fail = $true
$e | ForEach-Object { Write-Host "::error file=$($_.Extent.File),line=$($_.Extent.StartLineNumber)::$($_.Message)" }
} else {
Write-Host "$($_.Name): OK"
}
}
if ($fail) { exit 1 }