Compare commits

...
5 Commits
Author SHA1 Message Date
ubuntu de978187d0 fix(ci): align runs-on labels with gitea/act_runner defaults — advertise ubuntu-22.04 instead of self-hosted
ci / lint (ruff) (push) Successful in 1m22s
ci / pytest (py3.10) (push) Successful in 9m41s
ci / pytest (py3.11) (push) Successful in 9m38s
ci / pytest (py3.12) (push) Successful in 9m25s
ci / pytest (py3.13) (push) Successful in 9m42s
2026-07-08 08:19:55 +00:00
truetype 388b0a87c3 fix(ci): switch runner label to self-hosted, extend matrix to 3.13
ci / lint (ruff) (push) Has been cancelled
ci / pytest (py3.10) (push) Has been cancelled
ci / pytest (py3.11) (push) Has been cancelled
ci / pytest (py3.12) (push) Has been cancelled
ci / pytest (py3.13) (push) Has been cancelled
The build steps now declare 'runs-on: self-hosted' (default label
advertised by an act_runner registered with Docker mode). Previously
they used 'ubuntu-22.04' which would not match any default runner and
would leave every job in 'no runner available'.

ci.yml matrix extended to ['3.10','3.11','3.12','3.13'] for forward
coverage on Python 3.13 (current stable as of 2026).

docs/development.md 'CI/CD - Gitea Actions' section also corrected:
- the egress workaround now uses the actual Gitea 1.26 key
  [actions].DEFAULT_ACTIONS_URL (not ENABLE_GITHUB_ACTIONS_MIRROR)
- the act_runner docker command uses --rm -it for the first run to
  surface registration errors in the terminal before daemonization
- runner-scoping note clarifies global vs repo-scoped token URLs

Verified by ruff_exit=0 and pytest 66/66 still green locally.
2026-07-07 17:19:32 +00:00
truetype e0e7ea0c8f docs(ci): replace stale CI-placeholder with full Gitea Actions guide
ci / lint (ruff) (push) Has been cancelled
ci / pytest (py3.10) (push) Has been cancelled
ci / pytest (py3.11) (push) Has been cancelled
ci / pytest (py3.12) (push) Has been cancelled
The '## CI minima' section claimed CI was optional and pointed to a
sample YAML, which is now wrong: real workflows live in .gitea/workflows/
and the missing piece is the runner registration, not the YAML.

New section covers:
- inventory of ci.yml + release.yml (matrix, trigger, concurrency)
- step-by-step act_runner registration with docker command
- egress to github.com requirement + mirror workaround
- pip cache key behaviour for the matrix
- tag pattern + manual v0.2.0 badge update checklist
2026-07-07 17:17:08 +00:00
truetype b20f3c0f31 ci(actions): add Gitea Actions ci+release workflows + fix ruff findings
ci / lint (ruff) (push) Has been cancelled
ci / pytest (py3.10) (push) Has been cancelled
ci / pytest (py3.11) (push) Has been cancelled
ci / pytest (py3.12) (push) Has been cancelled
- .gitea/workflows/ci.yml: ruff + matrix pytest on 3.10/3.11/3.12
  on push and PR to main; concurrency cancels superseded runs
- .gitea/workflows/release.yml: gate (ruff + pytest) + build sdist/wheel
  on tag 'v*', uploads via actions/upload-artifact@v4
- README.md: add ci and version badges right under H1
- src/viandante/cli.py: drop unused prompt_toolkit.patch_stdout import
- tests/test_deadsouls.py: add missing RoomBlock import (F821)
- tests/test_logger.py: drop unused local 'raw' in unicode test
- tests/test_mapper.py: rename unused locals to _a/_b/_c (F841) to
  preserve intent (B has 's' back-edge; C is orphan)
2026-07-07 17:15:54 +00:00
truetype 2a8b472d4c docs: add brand block with viandante etymology + mapped-graph motif
Position: between the intro paragraph and the Changelog section.
Tagline surfaces project identity (Italian for 'wanderer');
the tiny ASCII map mirrors the renderer's actual output.
2026-07-07 16:18:52 +00:00
8 changed files with 231 additions and 24 deletions

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
name: ci
"on":
push:
branches: [main]
pull_request:
branches: [main]
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
ruff:
name: lint (ruff)
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python 3.12 (for ruff)
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dev extras (pulls ruff from pyproject)
run: |
python -m pip install -U pip
python -m pip install -e ".[dev]"
- name: Run ruff
run: python -m ruff check src tests
pytest:
name: pytest (py${{ matrix.python-version }})
runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev extras
run: |
python -m pip install -U pip
python -m pip install -e ".[dev]"
- name: Run pytest
run: python -m pytest -q
+71
View File
@@ -0,0 +1,71 @@
name: release
"on":
push:
tags:
- "v*"
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
jobs:
gate:
name: gate (ruff + pytest)
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install dev extras
run: |
python -m pip install -U pip
python -m pip install -e ".[dev]"
- name: Ruff
run: python -m ruff check src tests
- name: Pytest
run: python -m pytest -q
build:
name: build (sdist + wheel)
needs: gate
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip
cache-dependency-path: pyproject.toml
- name: Install build + dev extras
run: |
python -m pip install -U pip
python -m pip install build
python -m pip install -e ".[dev]"
- name: Build sdist and wheel
run: python -m build
- name: Inspect artifacts
run: ls -la dist/
- name: Upload distributions as artifact
uses: actions/upload-artifact@v4
with:
name: viandante-dist
path: dist/*
if-no-files-found: error
retention-days: 90
+20
View File
@@ -1,5 +1,8 @@
# viandante
[![ci](http://192.168.0.183:8085/truetype/viandante/badges/ci/main.svg)](http://192.168.0.183:8085/truetype/viandante/actions?workflow=ci)
[![version](https://img.shields.io/badge/version-v0.2.0-blue)](http://192.168.0.183:8085/truetype/viandante/releases/tag/v0.2.0)
`viandante` ospita un **client MUD CLI** pensato per collegarsi a un MUD
LP‑MUD basato sul driver **FluffOS** (per esempio **Dead Souls**, libreria
3.8.6). Il client parla telnet con estensioni standard: `ECHO`, `NAWS`,
@@ -8,6 +11,23 @@ per ora). Tiene traccia delle stanze visitate e le renderizza come **mappa
ASCII** on-demand.
---
> **viandante** — *Italian for "wanderer"*.
> A telnet client + ASCII mapper for LP-MUDs (FluffOS, Dead Souls),
> with GMCP vitals/room decoder and append-only session logging.
```
[ Town ] -- n -- [ Bank ]
| |
s e
| |
[ Gate ] ---------- [ Inn ]
```
> *Mapping the world, one step at a time.*
## Changelog
Le novità di `viandante` rispetto alla release 0.1 (bootstrap del client, prima del rename a `viandante`).
+78 -19
View File
@@ -150,25 +150,84 @@ Esempio: nuovo modulo `directions.py` che assorbe `EXIT_ALIASES` da
---
## CI minima (Gitea Actions, opzionale)
## CI/CD — Gitea Actions
Esempio `.gitea/workflows/ci.yml`:
I workflow vivono in `.gitea/workflows/`:
```yaml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
- run: python -m pip install -e ".[dev]"
- run: pytest
- run: ruff check src tests
```
- **`ci.yml`** — ruff + matrix pytest su Python 3.10/3.11/3.12, trigger
su `push` e `pull_request` verso `main`. `concurrency.cancel-in-progress`
annulla i run sorpassati (utile per push consecutivi su PR).
- **`release.yml`** — `gate` (ruff + pytest) → `build` (`python -m build`,
sdist + wheel) su tag `v*`. Gli artifact `viandante-*.tar.gz` e
`viandante-*.whl` finiscono nella pagina del job, scaricabili.
Adatta ai vincoli del tuo runner Gitea (alcuni runner non hanno
`actions/setup-python@v5`; pinning a versioni disponibili è tipico).
**Stato operativit\u00e0**: l'infrastruttura YAML \u00e8 committata e pushata
(v0.2.0 \u2192 `b20f3c0f`). Finch\u00e9 non registri un **runner** sul Gitea,
i job restano in `queued` e il badge `[![ci](...)](...)` rimane grigio.
Senza runner la pipeline non gira.
### Setup del runner (una tantum)
Sulla macchina che eseguir\u00e0 i job serve **Docker** (l'immagine
`ubuntu-22.04` parte in un container):
1. Genera il token di registrazione dalla UI:
`http://192.168.0.183:8085/-/admin/runners \u2192 "Crea nuovo runner"`
(NON \u00e8 il token account, \u00e8 un one-shot scelto da te).
2. Al primo avvio usa `--rm -it` per vedere in chiaro eventuali errori
di registrazione (token sbagliato, permessi su `/var/run/docker.sock`):
```bash
docker run --rm -it --name act_runner \
-e GITEA_INSTANCE_URL=http://192.168.0.183:8085 \
-e GITEA_RUNNER_REGISTRATION_TOKEN=<TOKEN_DEL_PUNTO_1> \
-e GITEA_RUNNER_NAME=homelab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitea/act_runner:latest
```
3. Quando vedi `Runner is now online` nel log, sostituisci con la
versione daemonizzata (`-d`, `--restart unless-stopped`). Un
`act_runner` Docker (`gitea/act_runner:latest`) di default
pubblica le label `ubuntu-latest`, `ubuntu-24.04`, `ubuntu-22.04`;
i workflow di `viandante` usano `runs-on: ubuntu-22.04`
(in `.gitea/workflows/*.yml`) che le matcha — ogni job gira in
un container pulito basato su Ubuntu 22.04 (Docker‑in‑Docker).
> NB sul token: l'URL `/-/admin/runners` genera un **runner globale**
> (visibile a tutti i repo del Gitea). Per limitare il runner a un solo
> repo, il token si legge da `/-/settings/actions/runners` di quel repo
> (la riga registrata appare nella sezione "Runners" del repo specifico,
> non nella pagina admin globale).
### Egress verso github.com (possibile blocker)
Senza egress dal runner host a `github.com`, le action composite
(`actions/checkout@v4`, `actions/setup-python@v5`,
`actions/upload-artifact@v4`) non possono essere scaricate e il primo
step fallisce con `failed to download action`. Workaround:
- **Ridireziona il download delle action** in `app.ini` del server
([chiave `DEFAULT_ACTIONS_URL`](https://docs.gitea.com/administration/config-cheat-sheet#actions-actions),
introdotta in Gitea 1.21+, default `https://github.com`):
```ini
[actions]
DEFAULT_ACTIONS_URL = https://<your-mirror-url>
```
NB: nomi pi\u00f9 vecchi tipo `ENABLE_GITHUB_ACTIONS_MIRROR` /
`ACTIONS_DEFAULT_BASE_URL` **non esistono in 1.26** \u2014 usa solo
`DEFAULT_ACTIONS_URL`.
- Oppure bundle locale: pre-popolare le action in un image di runner.
### Note pratiche
- **Cache `pip`**: `cache: pip` + `cache-dependency-path: pyproject.toml`.
Cache key = `python-version + hash(pyproject.toml)`, quindi 3.10/3.11/3.12
hanno cache separate (no cross-version poisoning).
- **Tag release pattern**: trigger su `v*` (`v0.2.0`, `v0.3`, `v1.0.0-rc1`).
Workflow di release: `git tag vX.Y.Z && git push origin vX.Y.Z`.
- **Badge `[![version](https://img.shields.io/...)](...)`** in README.md
\u00e8 hardcoded a `v0.2.0`: aggiornalo a mano a ogni release
(vedi checklist in `docs/gitea.md`).
-1
View File
@@ -24,7 +24,6 @@ from dataclasses import dataclass, field
from prompt_toolkit import PromptSession, print_formatted_text
from prompt_toolkit.formatted_text import ANSI, FormattedText
from prompt_toolkit.patch_stdout import patch_stdout
from prompt_toolkit.shortcuts import clear
from prompt_toolkit.styles import Style
+1
View File
@@ -4,6 +4,7 @@ from __future__ import annotations
from viandante.deadsouls import (
EXIT_ALIASES,
RollingRoomParser,
RoomBlock,
parse_exits,
parse_room_block,
)
-1
View File
@@ -262,7 +262,6 @@ def test_json_sink_preserves_unicode(tmp_path: Path) -> None:
log = EventLogger(json_path=str(out))
log.text("ilà ★")
log.close()
raw = out.read_text(encoding="utf-8")
events = _read_jsonl(out)
assert events[0]["data"]["raw"] == "ilà ★"
+3 -3
View File
@@ -55,8 +55,8 @@ def test_backtracking_visits_are_connected() -> None:
B's exits include the back-edge to A.
"""
m = Mapper()
a = m.visit("A", "", ["n"])
b = m.visit("B", "", ["s"])
_a = m.visit("A", "", ["n"])
_b = m.visit("B", "", ["s"])
# No link_rooms() — but B has 's' which would point to A.
out = m.render(max_cols=20, max_rows=20)
assert "A" in out
@@ -93,7 +93,7 @@ def test_multi_source_render_does_not_split_obviously_connected_rooms() -> None:
a = m.visit("A", "", ["n", "s"])
b = m.visit("B", "", ["s"])
m.link_rooms(a, "n", b)
c = m.visit("C", "", [])
_c = m.visit("C", "", []) # orphan: no exits
out = m.render(max_cols=10, max_rows=10)
assert "A" in out
assert "B" in out