11 Commits

Author SHA1 Message Date
engel 215e264e5f v1.2.3: fully Gitea-hosted; self-contained CI
Release / build (push) Successful in 47s
2026-06-01 13:44:49 +03:00
engel 99573cba5c ci: resolve version in pwsh (bash shell broken on Windows host runner)
Release / build (push) Successful in 29s
2026-06-01 12:42:59 +03:00
engel ac1c40d754 ci: make release workflow fully self-contained (no GitHub actions)
Release / build (push) Failing after 13s
Replace actions/checkout + actions/setup-python (pulled from github.com by
default) with a manual git clone at the tag and the runner's system Python.
2026-06-01 12:40:41 +03:00
engel 9ef788fe5b ci: use built-in Gitea Actions token for release publish
Drops the need for a manually-managed RELEASE_TOKEN secret; adds
contents:write permission so github.token can create the release.
2026-06-01 12:36:26 +03:00
engel 27304992a0 chore: cut GitHub, make project Gitea-only
- relink README/CHANGELOG/pyproject/SECURITY to git.engelgardt23.ru
- port CI from GitHub Actions to .gitea/workflows (publishes Gitea release via API)
- rename GITHUB_REPO -> REPO; drop GitHub mentions in code/docs/comments
- remove .github (workflow + issue templates); drop made-by lines
2026-06-01 12:35:28 +03:00
engel 07b93d1382 chore: switch update-check and release URLs to self-hosted Forgejo
GitHub-репо заморожены; релизы теперь на git.engelgardt23.ru.
2026-05-28 07:14:45 +00:00
engel 816cc9a459 v1.2.1: clickable update-available hyperlink in header 2026-05-18 12:51:21 +03:00
engel 88f282f1e0 i18n(ru): trim tagline ('для инженера' -> dropped) 2026-05-18 12:03:33 +03:00
engel 33c28128b8 docs: use US/RU flags in language switcher 2026-05-18 12:00:35 +03:00
engel 97fed974fc docs: drop flag emojis from language switcher 2026-05-18 11:59:22 +03:00
engel e8910f0f02 docs: drop vendor-specific examples (vegman -> generic) 2026-05-18 11:56:42 +03:00
15 changed files with 92 additions and 154 deletions
@@ -8,24 +8,30 @@ on:
permissions: permissions:
contents: write contents: write
# Self-contained: no external (GitHub-hosted) actions. Runs on a self-hosted
# Windows runner (label `windows`) that already has Python 3.12 on PATH.
jobs: jobs:
build: build:
runs-on: windows-latest runs-on: windows
steps: steps:
- uses: actions/checkout@v4 - name: Checkout repository at tag
shell: pwsh
- name: Set up Python env:
uses: actions/setup-python@v5 TOKEN: ${{ github.token }}
with: run: |
python-version: '3.12' $base = "${{ github.server_url }}" -replace '^https://', ''
$url = "https://oauth2:$env:TOKEN@$base/${{ github.repository }}.git"
git clone --depth 1 --branch "$env:GITHUB_REF_NAME" $url .
- name: Install build dependencies - name: Install build dependencies
run: python -m pip install --upgrade pip pyinstaller rich run: python -m pip install --upgrade pip pyinstaller rich
- name: Resolve version from tag - name: Resolve version from tag
id: ver id: ver
shell: bash shell: pwsh
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" run: |
$v = "$env:GITHUB_REF_NAME" -replace '^v', ''
"version=$v" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8
- name: Build executable - name: Build executable
run: python -m PyInstaller --onefile --uac-admin --console --name dhcpsrv --icon assets/icon.ico --paths src dhcpsrv-launcher.py run: python -m PyInstaller --onefile --uac-admin --console --name dhcpsrv --icon assets/icon.ico --paths src dhcpsrv-launcher.py
@@ -39,7 +45,6 @@ jobs:
Copy-Item dist/dhcpsrv.exe $folder/ Copy-Item dist/dhcpsrv.exe $folder/
@" @"
dhcpsrv v$ver - portable edition dhcpsrv v$ver - portable edition
made by engelgardt
Minimal laptop-side DHCP server for storage/server engineers. Minimal laptop-side DHCP server for storage/server engineers.
@@ -71,10 +76,19 @@ jobs:
"$hash $zip" | Out-File -FilePath "$zip.sha256" -Encoding ASCII -NoNewline "$hash $zip" | Out-File -FilePath "$zip.sha256" -Encoding ASCII -NoNewline
Get-Content "$zip.sha256" Get-Content "$zip.sha256"
- name: Create release - name: Publish Gitea release
uses: softprops/action-gh-release@v2 shell: pwsh
with: env:
files: | TOKEN: ${{ github.token }}
dhcpsrv-portable-v${{ steps.ver.outputs.version }}.zip run: |
dhcpsrv-portable-v${{ steps.ver.outputs.version }}.zip.sha256 $ver = '${{ steps.ver.outputs.version }}'
generate_release_notes: true $tag = "v$ver"
$api = "${{ github.server_url }}/api/v1/repos/${{ github.repository }}"
$hdr = @{ Authorization = "token $env:TOKEN" }
$body = @{ tag_name = $tag; name = $tag; draft = $false; prerelease = $false } | ConvertTo-Json
$rel = Invoke-RestMethod -Method Post -Uri "$api/releases" -Headers $hdr -ContentType 'application/json' -Body $body
$rid = $rel.id
foreach ($f in @("dhcpsrv-portable-v$ver.zip", "dhcpsrv-portable-v$ver.zip.sha256")) {
curl.exe -s -H "Authorization: token $env:TOKEN" -F "attachment=@$f" "$api/releases/$rid/assets?name=$f" | Out-Null
Write-Host "uploaded $f"
}
-56
View File
@@ -1,56 +0,0 @@
name: Bug report
description: Something doesn't work as expected
labels: ["bug"]
body:
- type: input
id: version
attributes:
label: Version
description: Visible in the startup banner.
placeholder: v1.1.0
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to reproduce
placeholder: |
1. ...
2. ...
3. ...
validations:
required: true
- type: textarea
id: expected
attributes:
label: What you expected to happen
validations:
required: true
- type: textarea
id: actual
attributes:
label: What actually happened
description: Paste any error output verbatim. Screenshots are welcome.
validations:
required: true
- type: input
id: os
attributes:
label: Windows version
placeholder: e.g. Windows 11 24H2
- type: input
id: network
attributes:
label: Network setup (if relevant)
placeholder: e.g. USB Realtek NIC to a server's BMC port via an 8-port switch
- type: textarea
id: extra
attributes:
label: Anything else?
description: Workarounds tried, related links, etc.
-5
View File
@@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/Engelgardt23/dhcpsrv/security/advisories/new
about: Please report security issues privately via GitHub Security Advisories — not as a public issue.
@@ -1,23 +0,0 @@
name: Feature request
description: Suggest a new feature or an improvement
labels: ["enhancement"]
body:
- type: textarea
id: motivation
attributes:
label: What's the use case?
description: What are you trying to do, and why is the current behavior not enough?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed solution
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
+4 -1
View File
@@ -7,7 +7,10 @@ dist/
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
# Distribution staging folders (built per-version, attached to GitHub Releases) # Local build cache (prod/test/old portable folders per version)
builds/
# Legacy staging folders (kept for compatibility with old checkouts)
portable-v*/ portable-v*/
# Local backup of release archives (kept locally for history, not in repo) # Local backup of release archives (kept locally for history, not in repo)
+21 -9
View File
@@ -6,6 +6,16 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
## [Unreleased] ## [Unreleased]
## [1.2.3] - 2026-06-01
### Changed
- Project is now fully self-hosted on Gitea (`git.engelgardt23.ru`): update-check, links and badges no longer reference GitHub.
- CI moved to self-contained Gitea Actions (no GitHub-hosted actions); releases are built on a self-hosted Windows runner and published to the local instance.
## [1.2.1] - 2026-05-18
### Changed
- The `Update available (vX.Y.Z)` hint in the header is now a clickable hyperlink that opens the releases page (OSC 8 terminal hyperlink). Modern terminals (Windows Terminal, VS Code, WezTerm, most Linux/macOS terminals) render it as a link — `Ctrl+Click` to follow. Older consoles show the plain text, so nothing breaks.
- Russian tagline tightened: dropped the `для инженера` phrase, the wording was carried over from an earlier draft and felt out of place.
## [1.2.0] - 2026-05-18 ## [1.2.0] - 2026-05-18
### Added ### Added
- Russian UI translation. On first launch the application asks which language to use (`1) English`, `2) Русский`) and writes the answer to a fresh `config.ini` next to `dhcpsrv.exe`. To change the language later, edit `language = en` / `language = ru` in that file — the comment at the top of the file explains how, in both languages. - Russian UI translation. On first launch the application asks which language to use (`1) English`, `2) Русский`) and writes the answer to a fresh `config.ini` next to `dhcpsrv.exe`. To change the language later, edit `language = en` / `language = ru` in that file — the comment at the top of the file explains how, in both languages.
@@ -30,11 +40,11 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
## [1.1.0] - 2026-05-16 ## [1.1.0] - 2026-05-16
### Added ### Added
- Auto-update check on startup. Polls GitHub `/releases/latest` with a 3-second timeout. If a newer version is available, prints a yellow notice and offers to open the download page in your browser. Silent on offline / API errors. - Auto-update check on startup. Polls the Gitea instance `/releases/latest` with a 3-second timeout. If a newer version is available, prints a yellow notice and offers to open the download page in your browser. Silent on offline / API errors.
## [1.0.0] - 2026-05-16 ## [1.0.0] - 2026-05-16
### Added ### Added
- First public release on GitHub. - First public release.
- Single portable `.exe` (~12 MB) — no Python required on target machines. - Single portable `.exe` (~12 MB) — no Python required on target machines.
- Full-screen TUI built on `rich`: header with server config + live counters (Leases / Pkts / DISCOVER / REQUEST / RELEASE), clients table (`#`, IP, Hostname, MAC, Last seen, Ping), scrolling events panel. - Full-screen TUI built on `rich`: header with server config + live counters (Leases / Pkts / DISCOVER / REQUEST / RELEASE), clients table (`#`, IP, Hostname, MAC, Last seen, Ping), scrolling events panel.
- Hardcoded sensible defaults: server `10.10.10.1/24`, pool `10.10.10.2..10.10.10.51` (50 addresses), lease `7200 s`, TFTP option (66/150) = server IP. - Hardcoded sensible defaults: server `10.10.10.1/24`, pool `10.10.10.2..10.10.10.51` (50 addresses), lease `7200 s`, TFTP option (66/150) = server IP.
@@ -46,10 +56,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
- Scrollback cleared on startup so mouse-wheel doesn't expose pre-launch text. - Scrollback cleared on startup so mouse-wheel doesn't expose pre-launch text.
- MIT licensed. - MIT licensed.
[Unreleased]: https://github.com/Engelgardt23/dhcpsrv/compare/v1.2.0...HEAD [Unreleased]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.2.3...HEAD
[1.2.0]: https://github.com/Engelgardt23/dhcpsrv/compare/v1.1.3...v1.2.0 [1.2.3]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.2.1...v1.2.3
[1.1.3]: https://github.com/Engelgardt23/dhcpsrv/compare/v1.1.2...v1.1.3 [1.2.1]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.2.0...v1.2.1
[1.1.2]: https://github.com/Engelgardt23/dhcpsrv/compare/v1.1.1...v1.1.2 [1.2.0]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.1.3...v1.2.0
[1.1.1]: https://github.com/Engelgardt23/dhcpsrv/compare/v1.1.0...v1.1.1 [1.1.3]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.1.2...v1.1.3
[1.1.0]: https://github.com/Engelgardt23/dhcpsrv/compare/v1.0.0...v1.1.0 [1.1.2]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.1.1...v1.1.2
[1.0.0]: https://github.com/Engelgardt23/dhcpsrv/releases/tag/v1.0.0 [1.1.1]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.1.0...v1.1.1
[1.1.0]: https://git.engelgardt23.ru/engel/dhcpsrv/compare/v1.0.0...v1.1.0
[1.0.0]: https://git.engelgardt23.ru/engel/dhcpsrv/releases/tag/v1.0.0
+5 -6
View File
@@ -6,15 +6,14 @@
``` ```
dhcpsrv/ dhcpsrv/
├── .github/ ├── .gitea/
── workflows/release.yml ← CI: tag-driven build + GitHub Release ── workflows/release.yml ← CI: tag-driven build + Gitea Release
│ └── ISSUE_TEMPLATE/ ← bug / feature / security routing
├── src/dhcpsrv/ ← package source (≤200 lines per module) ├── src/dhcpsrv/ ← package source (≤200 lines per module)
│ ├── __init__.py ← single source of truth for __version__ │ ├── __init__.py ← single source of truth for __version__
│ ├── __main__.py ← entry: python -m dhcpsrv │ ├── __main__.py ← entry: python -m dhcpsrv
│ ├── app.py ← main flow, wires everything │ ├── app.py ← main flow, wires everything
│ ├── platform_win.py ← VT enable + UAC self-elevate │ ├── platform_win.py ← VT enable + UAC self-elevate
│ ├── update_check.py ← GitHub /releases/latest poll │ ├── update_check.py ← Gitea /releases/latest poll
│ ├── network.py ← list_adapters, netsh, ping (no shared state) │ ├── network.py ← list_adapters, netsh, ping (no shared state)
│ ├── dhcp.py ← DhcpConfig, DhcpServer, packet parse/build │ ├── dhcp.py ← DhcpConfig, DhcpServer, packet parse/build
│ └── ui.py ← rich-based full-screen TUI │ └── ui.py ← rich-based full-screen TUI
@@ -64,7 +63,7 @@ flag tells PyInstaller where to find the `dhcpsrv` package itself. Output:
4. Tag: `git tag vX.Y.Z`. 4. Tag: `git tag vX.Y.Z`.
5. Push: `git push && git push --tags`. 5. Push: `git push && git push --tags`.
That's it. GitHub Actions picks up the tag, builds the exe, writes the SHA-256, and creates the GitHub Release with the zip attached. That's it. Gitea Actions picks up the tag, builds the exe, writes the SHA-256, and creates the Gitea Release with the zip attached.
## Where features go ## Where features go
@@ -76,4 +75,4 @@ That's it. GitHub Actions picks up the tag, builds the exe, writes the SHA-256,
| Something shown in the header | `ui.py``Ui._render_header` | | Something shown in the header | `ui.py``Ui._render_header` |
| A startup check or banner line | `app.py``main()` | | A startup check or banner line | `app.py``main()` |
| A change to UAC / VT logic | `platform_win.py` | | A change to UAC / VT logic | `platform_win.py` |
| Tweaking the GitHub update-check UX | `update_check.py` | | Tweaking the update-check UX | `update_check.py` |
+7 -9
View File
@@ -1,22 +1,20 @@
# dhcpsrv # dhcpsrv
[![Latest release](https://img.shields.io/github/v/release/Engelgardt23/dhcpsrv)](https://github.com/Engelgardt23/dhcpsrv/releases/latest) [![Latest release](https://img.shields.io/gitea/v/release/engel/dhcpsrv?gitea_url=https%3A%2F%2Fgit.engelgardt23.ru&label=release)](https://git.engelgardt23.ru/engel/dhcpsrv/releases/latest)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
🇬🇧 English | [🇷🇺 На русском](README.ru.md) 🇺🇸 English | [🇷🇺 Русский](README.ru.md)
A tiny portable **DHCP server** for the laptop of a storage/server engineer. A tiny portable **DHCP server** for the laptop of a storage/server engineer.
One double-click — pick a NIC — done. Live table of clients, ping status, packet counters. No install, no Python required on the target machine. One double-click — pick a NIC — done. Live table of clients, ping status, packet counters. No install, no Python required on the target machine.
Built for the “plug the cable in, watch a BMC pop up with an IP” workflow during firmware updates, recovery, and benchmarks. Built for the “plug the cable in, watch a BMC pop up with an IP” workflow during firmware updates, recovery, and benchmarks.
> **Made by engelgardt.**
--- ---
## Download ## Download
Grab the latest release: [**releases page**](https://github.com/Engelgardt23/dhcpsrv/releases/latest). Grab the latest release: [**releases page**](https://git.engelgardt23.ru/engel/dhcpsrv/releases/latest).
The asset is `dhcpsrv-portable-vX.Y.Z.zip` (~12 MB). The asset is `dhcpsrv-portable-vX.Y.Z.zip` (~12 MB).
## Run ## Run
@@ -39,14 +37,14 @@ The asset is `dhcpsrv-portable-vX.Y.Z.zip` (~12 MB).
## What's on screen ## What's on screen
``` ```
┌─ dhcpsrv v1.0.0 made by engelgardt ────────────────────────────────────┐ ┌─ dhcpsrv v1.0.0 ────────────────────────────────────────────────────────┐
│ Server: 10.10.10.1/255.255.255.0 Pool: 10.10.10.210.10.10.51 … │ │ Server: 10.10.10.1/255.255.255.0 Pool: 10.10.10.210.10.10.51 … │
│ Leases: 3/50 Pkts: 47 DISCOVER: 12 REQUEST: 11 RELEASE: 0 │ │ Leases: 3/50 Pkts: 47 DISCOVER: 12 REQUEST: 11 RELEASE: 0 │
└─────────────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────────────┘
┌─ Clients ───────────────────────────────────────────────────────────────┐ ┌─ Clients ───────────────────────────────────────────────────────────────┐
│ # │ IP │ Hostname │ MAC │ Last seen │ Ping │ │ # │ IP │ Hostname │ MAC │ Last seen │ Ping │
│ 1 │ 10.10.10.2 │ vegman-r120 │ a0:c5:f2:13:57:46 │ 17:42:18 │ OK │ │ 1 │ 10.10.10.2 │ server-01 │ a0:c5:f2:13:57:46 │ 17:42:18 │ OK │
│ 2 │ 10.10.10.3 │ vegman-s220 │ 70:b3:d5:11:22:33 │ 17:42:21 │ -- │ │ 2 │ 10.10.10.3 │ server-02 │ 70:b3:d5:11:22:33 │ 17:42:21 │ -- │
└─────────────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────────────┘
┌─ Events ────────────────────────────────────────────────────────────────┐ ┌─ Events ────────────────────────────────────────────────────────────────┐
│ [17:42:18] DISCOVER a0:c5:f2:13:57:46 → OFFER 10.10.10.2 │ │ [17:42:18] DISCOVER a0:c5:f2:13:57:46 → OFFER 10.10.10.2 │
@@ -56,7 +54,7 @@ The asset is `dhcpsrv-portable-vX.Y.Z.zip` (~12 MB).
## Typical scenarios ## Typical scenarios
- **VEGMAN with shared LOM** — one cable into the BMC/host port, BMC and the host OS both get IPs from this DHCP. - **Server with shared LOM** — one cable into the BMC/host port, BMC and the host OS both get IPs from this DHCP.
- **8-port switch** — laptop on one port, up to 7 servers on the rest; the 50-address pool covers everyone. - **8-port switch** — laptop on one port, up to 7 servers on the rest; the 50-address pool covers everyone.
- **Direct cable into a dedicated Mgmt port** — single client (the BMC). - **Direct cable into a dedicated Mgmt port** — single client (the BMC).
+6 -8
View File
@@ -1,22 +1,20 @@
# dhcpsrv # dhcpsrv
[![Последний релиз](https://img.shields.io/github/v/release/Engelgardt23/dhcpsrv)](https://github.com/Engelgardt23/dhcpsrv/releases/latest) [![Последний релиз](https://img.shields.io/gitea/v/release/engel/dhcpsrv?gitea_url=https%3A%2F%2Fgit.engelgardt23.ru&label=release)](https://git.engelgardt23.ru/engel/dhcpsrv/releases/latest)
[![Лицензия: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Лицензия: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[🇬🇧 English](README.md) | 🇷🇺 На русском [🇺🇸 English](README.md) | 🇷🇺 Русский
Маленький портативный **DHCP-сервер** для ноутбука инженера хранения / серверов. Маленький портативный **DHCP-сервер** для ноутбука инженера хранения / серверов.
Двойной клик — выбрал сетевую — готово. Живая таблица клиентов, статус ping, счётчики пакетов. Ничего не устанавливается, Python на целевой машине не нужен. Двойной клик — выбрал сетевую — готово. Живая таблица клиентов, статус ping, счётчики пакетов. Ничего не устанавливается, Python на целевой машине не нужен.
Сделан под сценарий «воткнул кабель, увидел как BMC получил IP» во время прошивки, восстановления и бенчмарков. Сделан под сценарий «воткнул кабель, увидел как BMC получил IP» во время прошивки, восстановления и бенчмарков.
> **Автор: engelgardt.**
--- ---
## Скачать ## Скачать
Последний релиз: [**страница релизов**](https://github.com/Engelgardt23/dhcpsrv/releases/latest). Последний релиз: [**страница релизов**](https://git.engelgardt23.ru/engel/dhcpsrv/releases/latest).
Архив `dhcpsrv-portable-vX.Y.Z.zip` (~12 МБ). Архив `dhcpsrv-portable-vX.Y.Z.zip` (~12 МБ).
## Запуск ## Запуск
@@ -46,8 +44,8 @@
└─────────────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────────────┘
┌─ Клиенты ───────────────────────────────────────────────────────────────┐ ┌─ Клиенты ───────────────────────────────────────────────────────────────┐
│ # │ IP │ Имя хоста │ MAC │ Последний │ Пинг │ │ # │ IP │ Имя хоста │ MAC │ Последний │ Пинг │
│ 1 │ 10.10.10.2 │ vegman-r120 │ a0:c5:f2:13:57:46 │ 17:42:18 │ OK │ │ 1 │ 10.10.10.2 │ server-01 │ a0:c5:f2:13:57:46 │ 17:42:18 │ OK │
│ 2 │ 10.10.10.3 │ vegman-s220 │ 70:b3:d5:11:22:33 │ 17:42:21 │ -- │ │ 2 │ 10.10.10.3 │ server-02 │ 70:b3:d5:11:22:33 │ 17:42:21 │ -- │
└─────────────────────────────────────────────────────────────────────────┘ └─────────────────────────────────────────────────────────────────────────┘
┌─ События ───────────────────────────────────────────────────────────────┐ ┌─ События ───────────────────────────────────────────────────────────────┐
│ [17:42:18] DISCOVER a0:c5:f2:13:57:46 → OFFER 10.10.10.2 │ │ [17:42:18] DISCOVER a0:c5:f2:13:57:46 → OFFER 10.10.10.2 │
@@ -57,7 +55,7 @@
## Типичные сценарии ## Типичные сценарии
- **VEGMAN с общим LOM** — один кабель в порт BMC/host, и BMC и хост-ОС получают IP с этого DHCP. - **Сервер с общим LOM** — один кабель в порт BMC/host, и BMC и хост-ОС получают IP с этого DHCP.
- **8-портовый свитч** — ноут на одном порту, до 7 серверов на остальных; пул из 50 адресов покрывает всех. - **8-портовый свитч** — ноут на одном порту, до 7 серверов на остальных; пул из 50 адресов покрывает всех.
- **Прямой кабель в выделенный Mgmt-порт** — один клиент (BMC). - **Прямой кабель в выделенный Mgmt-порт** — один клиент (BMC).
+2 -4
View File
@@ -6,16 +6,14 @@ on the host — so vulnerability reports are very welcome.
## Supported versions ## Supported versions
Only the latest tagged release on GitHub is supported. Older versions will not Only the latest tagged release is supported. Older versions will not
get fixes; please upgrade first. get fixes; please upgrade first.
## How to report a vulnerability ## How to report a vulnerability
**Please do not open a public issue** for security-sensitive findings. **Please do not open a public issue** for security-sensitive findings.
Use GitHub's private security advisories: go to the Report privately by email to the maintainer at engelgardt2024@gmail.com.
[Security tab](../../security/advisories/new) of this repo and click
"Report a vulnerability". GitHub will route it privately.
Please include: Please include:
- The version you tested (the startup banner is enough). - The version you tested (the startup banner is enough).
+2 -2
View File
@@ -13,8 +13,8 @@ dependencies = ["rich>=13"]
dynamic = ["version"] dynamic = ["version"]
[project.urls] [project.urls]
Homepage = "https://github.com/Engelgardt23/dhcpsrv" Homepage = "https://git.engelgardt23.ru/engel/dhcpsrv"
Issues = "https://github.com/Engelgardt23/dhcpsrv/issues" Issues = "https://git.engelgardt23.ru/engel/dhcpsrv/issues"
[project.scripts] [project.scripts]
dhcpsrv = "dhcpsrv.app:main" dhcpsrv = "dhcpsrv.app:main"
+2 -3
View File
@@ -1,10 +1,9 @@
""" """
dhcpsrv - portable laptop-side DHCP server for storage/server engineers. dhcpsrv - portable laptop-side DHCP server for storage/server engineers.
made by engelgardt
The single source of truth for the project version. Bump this before tagging The single source of truth for the project version. Bump this before tagging
a release; CI reads the tag, the code reads this constant. a release; CI reads the tag, the code reads this constant.
""" """
__version__ = "1.2.0" __version__ = "1.2.3"
GITHUB_REPO = "Engelgardt23/dhcpsrv" REPO = "engel/dhcpsrv" # self-hosted Gitea (git.engelgardt23.ru)
+4 -2
View File
@@ -11,7 +11,7 @@ from rich.console import Console
from rich.prompt import Confirm, Prompt from rich.prompt import Confirm, Prompt
from rich.table import Table from rich.table import Table
from . import __version__ from . import __version__, REPO
from .platform_win import enable_vt, require_admin from .platform_win import enable_vt, require_admin
from .update_check import check_for_update from .update_check import check_for_update
from .network import list_adapters, set_static_ip, revert_to_dhcp from .network import list_adapters, set_static_ip, revert_to_dhcp
@@ -53,10 +53,12 @@ def main() -> None:
title = f"[bold cyan]dhcpsrv v{__version__}[/] {t('tagline')}" title = f"[bold cyan]dhcpsrv v{__version__}[/] {t('tagline')}"
latest = check_for_update() latest = check_for_update()
if latest: if latest:
release_url = f"https://git.engelgardt23.ru/{REPO}/releases/latest"
notice = t("update_available", tag=latest)
header = Table.grid(expand=True) header = Table.grid(expand=True)
header.add_column(justify="left", ratio=1) header.add_column(justify="left", ratio=1)
header.add_column(justify="right") header.add_column(justify="right")
header.add_row(title, f"[dim]{t('update_available', tag=latest)}[/]") header.add_row(title, f"[dim][link={release_url}]{notice}[/link][/]")
console.print(header) console.print(header)
else: else:
console.print(title) console.print(title)
+3 -3
View File
@@ -20,7 +20,7 @@ STRINGS: dict[str, dict[str, str]] = {
"en": { "en": {
# app.py / startup # app.py / startup
"tagline": "- portable laptop-side DHCP server", "tagline": "- portable laptop-side DHCP server",
"update_available": "update available ({tag})", "update_available": "Update available ({tag})",
"available_adapters": "Available adapters", "available_adapters": "Available adapters",
"no_adapters": "No suitable wired adapters found.", "no_adapters": "No suitable wired adapters found.",
"select_adapter": "Select adapter number", "select_adapter": "Select adapter number",
@@ -56,8 +56,8 @@ STRINGS: dict[str, dict[str, str]] = {
"no_events": "(no events yet)", "no_events": "(no events yet)",
}, },
"ru": { "ru": {
"tagline": "— портативный DHCP-сервер для инженера", "tagline": "— портативный DHCP-сервер",
"update_available": "доступно обновление ({tag})", "update_available": "Доступно обновление ({tag})",
"available_adapters": "Доступные адаптеры", "available_adapters": "Доступные адаптеры",
"no_adapters": "Подходящие проводные адаптеры не найдены.", "no_adapters": "Подходящие проводные адаптеры не найдены.",
"select_adapter": "Введите номер адаптера", "select_adapter": "Введите номер адаптера",
+5 -6
View File
@@ -1,16 +1,16 @@
""" """
Auto-update check. Auto-update check.
On startup, ask GitHub for the latest release tag. If it's newer than the On startup, ask the Gitea instance for the latest release tag. If it's newer
local `__version__`, return the tag string so the caller can show a quiet than the local `__version__`, return the tag string so the caller can show a
hint in the header. Silent on any error (offline, rate-limit, etc.). quiet hint in the header. Silent on any error (offline, rate-limit, etc.).
""" """
from __future__ import annotations from __future__ import annotations
import json import json
import urllib.request import urllib.request
from . import __version__, GITHUB_REPO from . import __version__, REPO
def _parse_version(s: str) -> tuple[int, int, int]: def _parse_version(s: str) -> tuple[int, int, int]:
@@ -29,9 +29,8 @@ def check_for_update() -> str | None:
currently running version. Returns None when up to date, offline, or on currently running version. Returns None when up to date, offline, or on
any error — the caller decides how (or whether) to render the hint.""" any error — the caller decides how (or whether) to render the hint."""
try: try:
url = f"https://api.github.com/repos/{GITHUB_REPO}/releases/latest" url = f"https://git.engelgardt23.ru/api/v1/repos/{REPO}/releases/latest"
req = urllib.request.Request(url, headers={ req = urllib.request.Request(url, headers={
"Accept": "application/vnd.github+json",
"User-Agent": f"dhcpsrv/{__version__}", "User-Agent": f"dhcpsrv/{__version__}",
}) })
with urllib.request.urlopen(req, timeout=3) as r: with urllib.request.urlopen(req, timeout=3) as r: