diff --git a/.github/workflows/xe-experimental-vm-test.yml b/.github/workflows/xe-experimental-vm-test.yml new file mode 100644 index 000000000..a95d468d3 --- /dev/null +++ b/.github/workflows/xe-experimental-vm-test.yml @@ -0,0 +1,36 @@ +name: "integration-vms" + +on: + # # NOTE(Xe): uncomment this region when testing the test + # pull_request: + # branches: + # - 'main' + release: + types: [ created ] + schedule: + # At minute 0 past hour 6 and 18 + # https://crontab.guru/#00_6,18_*_*_* + - cron: '00 6,18 * * *' + +jobs: + experimental-linux-vm-test: + # To set up a new runner, see tstest/integration/vms/runner.nix + runs-on: [ self-hosted, linux, vm_integration_test ] + + if: "!contains(github.event.head_commit.message, '[ci skip]')" + + steps: + - name: Checkout Code + uses: actions/checkout@v1 + + - name: Download VM Images + run: go test ./tstest/integration/vms -run-vm-tests -run=Download -timeout=60m + env: + XDG_CACHE_HOME: "/var/lib/ghrunner/cache" + + - name: Run VM tests + run: go test ./tstest/integration/vms -v -run-vm-tests + env: + TMPDIR: "/tmp" + XDG_CACHE_HOME: "/var/lib/ghrunner/cache" + diff --git a/tstest/integration/vms/runner.nix b/tstest/integration/vms/runner.nix new file mode 100644 index 000000000..39360d24d --- /dev/null +++ b/tstest/integration/vms/runner.nix @@ -0,0 +1,77 @@ +# This is a NixOS module to allow a machine to act as an integration test +# runner. This is used for the end-to-end VM test suite. + +{ lib, config, pkgs, ... }: + +{ + # The GitHub Actions self-hosted runner service. + services.github-runner = { + enable = true; + url = "https://github.com/tailscale/tailscale"; + replace = true; + extraLabels = [ "vm_integration_test" ]; + + # Justifications for the packages: + extraPackages = with pkgs; [ + # The test suite is written in Go. + go + + # This contains genisoimage, which is needed to create cloud-init + # seeds. + cdrkit + + # This package is the virtual machine hypervisor we use in tests. + qemu + + # This package contains tools like `ssh-keygen`. + openssh + + # The C complier so cgo builds work. + gcc + ]; + + # Customize this to include your GitHub username so we can track + # who is running which node. + name = "YOUR-GITHUB-USERNAME-tstest-integration-vms"; + + # Replace this with the path to the GitHub Actions runner token on + # your disk. + tokenFile = "/run/decrypted/ts-oss-ghaction-token"; + }; + + # A user account so there is a home directory and so they have kvm + # access. Please don't change this account name. + users.users.ghrunner = { + createHome = true; + isSystemUser = true; + extraGroups = [ "kvm" ]; + }; + + # The default github-runner service sets a lot of isolation features + # that attempt to limit the damage that malicious code can use. + # Unfortunately we rely on some "dangerous" features to do these tests, + # so this shim will peel some of them away. + systemd.services.github-runner = { + serviceConfig = { + # We need access to /dev to poke /dev/kvm. + PrivateDevices = lib.mkForce false; + + # /dev/kvm is how qemu creates a virtual machine with KVM. + DeviceAllow = lib.mkForce [ "/dev/kvm" ]; + + # Ensure the service has KVM permissions with the `kvm` group. + ExtraGroups = [ "kvm" ]; + + # The service runs as a dynamic user by default. This makes it hard + # to persistently store things in /var/lib/ghrunner. This line + # disables the dynamic user feature. + DynamicUser = lib.mkForce false; + + # Run this service as our ghrunner user. + User = "ghrunner"; + + # We need access to /var/lib/ghrunner to store VM images. + ProtectSystem = lib.mkForce null; + }; + }; +}