diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 5ac0137..d705777 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -40,13 +40,36 @@ on: workflow_dispatch: jobs: + stage-firecracker-inputs: + runs-on: [self-hosted, kvm] + steps: + - name: Stage the provisioned static dropbear + run: | + mkdir -p firecracker-inputs + cp /var/cache/bot-bottle-fc/dropbear firecracker-inputs/dropbear + + - name: Upload Firecracker build inputs + uses: actions/upload-artifact@v3 + with: + name: firecracker-inputs + path: firecracker-inputs/ + build-infra: + needs: stage-firecracker-inputs runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 + - name: Download Firecracker build inputs + uses: actions/download-artifact@v3 + with: + name: firecracker-inputs + path: firecracker-inputs + - name: Build infra candidate from this checkout + env: + BOT_BOTTLE_FC_DROPBEAR: ${{ github.workspace }}/firecracker-inputs/dropbear run: python3 -m bot_bottle.backend.firecracker.publish_infra --output infra-candidate - name: Upload infra candidate diff --git a/bot_bottle/backend/firecracker/infra_artifact.py b/bot_bottle/backend/firecracker/infra_artifact.py index 8d76846..b4f5cf6 100644 --- a/bot_bottle/backend/firecracker/infra_artifact.py +++ b/bot_bottle/backend/firecracker/infra_artifact.py @@ -87,6 +87,9 @@ def infra_artifact_version(init_script: str, *, repo_root: Path = _REPO_ROOT) -> h.update((repo_root / name).read_bytes()) h.update(b"pyproject.toml\0") h.update((repo_root / "pyproject.toml").read_bytes()) + h.update(b"dropbear\0") + dropbear = util.dropbear_path() + h.update(dropbear.read_bytes() if dropbear.is_file() else b"") h.update(b"init\0") h.update(init_script.encode()) return h.hexdigest()[:16] diff --git a/bot_bottle/backend/firecracker/publish_infra.py b/bot_bottle/backend/firecracker/publish_infra.py index 495b1d1..631ec81 100644 --- a/bot_bottle/backend/firecracker/publish_infra.py +++ b/bot_bottle/backend/firecracker/publish_infra.py @@ -197,6 +197,7 @@ def main(argv: list[str] | None = None) -> int: print(f"built infra rootfs candidate {version}") return 0 + assert args.publish_dir is not None version = _publish_bundle(args.publish_dir, token) print(f"published infra rootfs {version}") return 0 diff --git a/tests/unit/test_infra_artifact.py b/tests/unit/test_infra_artifact.py index 4699354..c9dadcd 100644 --- a/tests/unit/test_infra_artifact.py +++ b/tests/unit/test_infra_artifact.py @@ -105,6 +105,20 @@ class TestVersionInputs(unittest.TestCase): after = ia.infra_artifact_version("init", repo_root=root) self.assertNotEqual(before, after) + def test_dropbear_change_bumps_version(self) -> None: + with tempfile.TemporaryDirectory() as d: + root = Path(d) + self._fake_repo(root) + dropbear = root / "dropbear" + dropbear.write_bytes(b"dropbear-v1") + with mock.patch.dict(os.environ, { + "BOT_BOTTLE_FC_DROPBEAR": str(dropbear), + }): + before = ia.infra_artifact_version("init", repo_root=root) + dropbear.write_bytes(b"dropbear-v2") + after = ia.infra_artifact_version("init", repo_root=root) + self.assertNotEqual(before, after) + def test_non_python_file_change_bumps_version(self) -> None: with tempfile.TemporaryDirectory() as d: root = Path(d) diff --git a/tests/unit/test_publish_infra.py b/tests/unit/test_publish_infra.py index b257c08..fc27e8c 100644 --- a/tests/unit/test_publish_infra.py +++ b/tests/unit/test_publish_infra.py @@ -7,6 +7,7 @@ read it into memory. Network is mocked; no Docker, no real build. from __future__ import annotations import hashlib +from email.message import Message import tempfile import unittest import urllib.error @@ -88,7 +89,7 @@ class TestPublishBundle(unittest.TestCase): with tempfile.TemporaryDirectory() as d: root = Path(d) self._bundle(root, "v1") - missing = urllib.error.HTTPError("u", 404, "missing", {}, None) + missing = urllib.error.HTTPError("u", 404, "missing", Message(), None) with mock.patch.object( pub.infra_artifact, "infra_artifact_version", return_value="v1" ), mock.patch.object(