ci: run the offline Tor keygen in CI, add a non-blocking network e2e job
Split the rootless Tor e2e skip so the deterministic offline checks (the real offline onion keygen and the production-flag guard) run whenever the tor binary is present, while only the live onion round-trip stays gated on LIM_E2E_TOR=1. The pytest job now installs tor so the keygen — which validates the exact production keygen path — runs on every push. A separate continue-on-error tor-network-e2e job exercises the full round-trip without making the public Tor network a blocking merge gate. The full QEMU build/boot/unlock e2e still needs root + KVM + Arch tooling and stays local/opt-in. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
17
.github/workflows/test.yml
vendored
17
.github/workflows/test.yml
vendored
@@ -18,5 +18,22 @@ jobs:
|
|||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
python-version: "3.12"
|
||||||
|
# tor lets the deterministic offline onion-keygen test run (it validates
|
||||||
|
# the real production keygen path); that test needs no network.
|
||||||
|
- run: sudo apt-get update && sudo apt-get install -y tor
|
||||||
- run: pip install pytest pyyaml
|
- run: pip install pytest pyyaml
|
||||||
- run: make test
|
- run: make test
|
||||||
|
|
||||||
|
tor-network-e2e:
|
||||||
|
# The live onion round-trip depends on the public Tor network, so it is
|
||||||
|
# informational (continue-on-error) rather than a blocking merge gate.
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
- run: sudo apt-get update && sudo apt-get install -y tor
|
||||||
|
- run: pip install pytest pyyaml
|
||||||
|
- run: LIM_E2E_TOR=1 make test-tor PYTHON=python
|
||||||
|
|||||||
@@ -27,9 +27,17 @@ import pytest
|
|||||||
from lim.image import tor as tor_module
|
from lim.image import tor as tor_module
|
||||||
from tests.e2e import tor_harness
|
from tests.e2e import tor_harness
|
||||||
|
|
||||||
pytestmark = pytest.mark.skipif(
|
# The offline checks only need the tor binary (no network) and are
|
||||||
os.environ.get("LIM_E2E_TOR") != "1" or shutil.which("tor") is None,
|
# deterministic, so they run in CI whenever tor is installed. Only the live
|
||||||
reason="needs LIM_E2E_TOR=1 and the tor binary (live network, slow).",
|
# onion round-trip needs the public Tor network, so it stays opt-in behind
|
||||||
|
# LIM_E2E_TOR=1 to keep an external, occasionally-flaky dependency out of the
|
||||||
|
# blocking gate.
|
||||||
|
_needs_tor = pytest.mark.skipif(
|
||||||
|
shutil.which("tor") is None, reason="needs the tor binary"
|
||||||
|
)
|
||||||
|
_needs_tor_network = pytest.mark.skipif(
|
||||||
|
shutil.which("tor") is None or os.environ.get("LIM_E2E_TOR") != "1",
|
||||||
|
reason="needs the tor binary and LIM_E2E_TOR=1 (live Tor network, slow)",
|
||||||
)
|
)
|
||||||
|
|
||||||
PASSPHRASE = b"correct horse battery staple"
|
PASSPHRASE = b"correct horse battery staple"
|
||||||
@@ -51,6 +59,7 @@ def test_offline_keygen_matches_production_flags():
|
|||||||
assert "--SocksPort 0" in script
|
assert "--SocksPort 0" in script
|
||||||
|
|
||||||
|
|
||||||
|
@_needs_tor
|
||||||
def test_onion_keygen_is_deterministic_and_offline(workdir):
|
def test_onion_keygen_is_deterministic_and_offline(workdir):
|
||||||
"""Keys generate without network and the .onion address is stable."""
|
"""Keys generate without network and the .onion address is stable."""
|
||||||
address = tor_harness.generate_onion_keys(
|
address = tor_harness.generate_onion_keys(
|
||||||
@@ -62,6 +71,7 @@ def test_onion_keygen_is_deterministic_and_offline(workdir):
|
|||||||
assert (workdir / "onion" / name).is_file()
|
assert (workdir / "onion" / name).is_file()
|
||||||
|
|
||||||
|
|
||||||
|
@_needs_tor_network
|
||||||
def test_unlock_passphrase_travels_over_onion(workdir):
|
def test_unlock_passphrase_travels_over_onion(workdir):
|
||||||
"""Full rootless round-trip: client -> Tor -> onion -> dropbear stand-in."""
|
"""Full rootless round-trip: client -> Tor -> onion -> dropbear stand-in."""
|
||||||
onion_dir = workdir / "onion"
|
onion_dir = workdir / "onion"
|
||||||
|
|||||||
Reference in New Issue
Block a user