Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
200 commits
Select commit Hold shift + click to select a range
07b9d32
refactor(events): give each bus event its own type
ephraimduncan Nov 5, 2026
46edf3d
refactor(sandbox): one guest contract in internal/sandbox/guest
ephraimduncan Nov 5, 2026
4097200
refactor(version): move semver and the release rule into internal/ver…
ephraimduncan Nov 5, 2026
9a41471
Merge branch 'untangle/f2' into refactor/untangle
ephraimduncan Nov 5, 2026
8e0bbb6
refactor(ghrest): use one REST leaf for all GitHub calls
ephraimduncan Nov 5, 2026
033b499
refactor(atomicfile): use one file kit for temp files, counts, and di…
ephraimduncan Nov 5, 2026
c1c8feb
Merge branch 'untangle/f1' into refactor/untangle
ephraimduncan Nov 5, 2026
08a13a7
refactor(web): move the data layer into web/src/api
ephraimduncan Nov 5, 2026
cbc4c0c
Merge branch 'untangle/w1' into refactor/untangle
ephraimduncan Nov 5, 2026
4afff8f
refactor(runner): move the runner bundles out of internal/image
ephraimduncan Nov 5, 2026
aa34acc
refactor(images): build all builtin images from one Dockerfile
ephraimduncan Nov 5, 2026
dcce798
chore(store): reserve the migration number 0005
ephraimduncan Nov 5, 2026
d055feb
refactor(runner): keep the runner versions in internal/runner/versions
ephraimduncan Nov 5, 2026
b28cb8b
refactor(cache): one disk rule for the cache and the mirror
ephraimduncan Nov 5, 2026
ef33a99
Merge branch 'untangle/h' into refactor/untangle
ephraimduncan Nov 5, 2026
030b1e7
refactor(scheduler): move job state to store, GitHub protocol to github
ephraimduncan Nov 5, 2026
01d1982
refactor(api): give the web its limits from the OpenAPI spec
ephraimduncan Nov 5, 2026
b66e388
refactor(web): use shared widgets and keep pages out of route files
ephraimduncan Nov 5, 2026
2e58b7f
Merge branch 'untangle/w2a' into refactor/untangle
ephraimduncan Nov 5, 2026
c239e1a
Merge branch 'untangle/d' into refactor/untangle
ephraimduncan Nov 5, 2026
ce35acb
refactor(sandbox): complete the driver contract and share one lifecyc…
ephraimduncan Nov 5, 2026
092400a
Merge branch 'untangle/s1' into refactor/untangle
ephraimduncan Nov 5, 2026
47eab83
refactor(cmd): make cmd/runplane only the composition root
ephraimduncan Nov 5, 2026
d2200da
Merge branch 'untangle/e1' into refactor/untangle
ephraimduncan Nov 5, 2026
b4eb9f9
docs(cache): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
04b0f8c
docs(mirror): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
0645459
docs(image): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
b6b4133
docs(runner): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
8f942c7
docs(keylock,atomicfile): remove comments that only tell what the cod…
ephraimduncan Nov 5, 2026
bccc415
docs(github): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
e80ee6f
docs(scheduler): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
5b56fa0
docs(update): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
20529d6
docs(backup): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
160a0c2
docs(tlsutil): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
1384ea6
docs(secret): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
2cc461d
docs(webui): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
17fd1f2
Merge branch 'untangle/c3' into refactor/untangle
ephraimduncan Nov 5, 2026
8c29221
docs(init): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
c39d367
docs(sandbox): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
1b6ff1b
docs(joblog): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
db56e53
Merge branch 'untangle/c1' into refactor/untangle
ephraimduncan Nov 5, 2026
ad9c720
docs(web/ui): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
11c0b71
docs(web/shell): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
72a1633
docs(web/styles): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
d253648
docs(web/dev): remove comments that only tell what the code does
ephraimduncan Nov 5, 2026
a717c59
refactor(fleet): one agent protocol, fleet domain types, one alert so…
ephraimduncan Nov 5, 2026
07afea4
Merge branch 'refactor/untangle' into untangle/g
ephraimduncan Nov 5, 2026
20018f0
refactor(fleet): the harness reads the local server from the store
ephraimduncan Nov 5, 2026
8a8af9d
refactor(doctor): host holds facts, each driver gives its doctor checks
ephraimduncan Nov 5, 2026
f14008f
refactor(api): domain services own their changes, one mode module
ephraimduncan Nov 5, 2026
1f8d98b
docs(firecracker): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
96bef8c
docs(sysbox): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
02969e8
docs(devdocker): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
fd69f62
docs(host): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
0946386
docs(doctor): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
1856f77
Merge branch 'refactor/untangle' into untangle/e2
ephraimduncan Nov 6, 2026
7bc5c77
Merge branch 'untangle/e2' into refactor/untangle
ephraimduncan Nov 6, 2026
5d65f4b
docs(agent): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
6496ca7
docs(fleet): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
c488885
docs(notify): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
8301477
docs(store): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
44b0646
docs(api): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
cb1b358
docs(auth,pools): remove comments that only tell what the code does
ephraimduncan Nov 6, 2026
8470663
test(install): compare the copies in install.sh and the release files…
ephraimduncan Nov 6, 2026
8c0248e
Merge branch 'untangle/i' into refactor/untangle
ephraimduncan Nov 6, 2026
3aebfa7
refactor(web): read the results of the Go rules from the API
ephraimduncan Nov 6, 2026
8f6d846
Merge branch 'untangle/w2b' into refactor/untangle
ephraimduncan Nov 6, 2026
0a377e1
refactor(cmd): open the primary database in one function
ephraimduncan Nov 6, 2026
dcc27ca
refactor(config): remove Config.SandboxDir
ephraimduncan Nov 6, 2026
c21d9b1
refactor(initbin): remove the runplane-init next to the executable
ephraimduncan Nov 6, 2026
6893fc1
fix(install): read the version of /usr/local/bin/firecracker
ephraimduncan Nov 6, 2026
f466c60
test(install): run install.sh through one test helper
ephraimduncan Nov 6, 2026
fbbc5f1
refactor(atomicfile): make the key files with one CreateOnce
ephraimduncan Nov 6, 2026
30d8b12
refactor(datadisk): read the room of a cache folder with datadisk.Of
ephraimduncan Nov 6, 2026
b1bf3cc
refactor(shell): record the debug shells through audit.Log
ephraimduncan Nov 6, 2026
79ec671
ci(images): build the images only when the Dockerfile changes
ephraimduncan Nov 6, 2026
31fc69c
refactor(cache): give the cache server the sandbox of an agent as typ…
ephraimduncan Nov 6, 2026
b38b8b4
test(fleet): wait for the pull work before the image counts
ephraimduncan Nov 6, 2026
f142584
refactor(sandbox): give each contract of the sandboxes one source
ephraimduncan Nov 6, 2026
bcc68f1
refactor(agent): keep only the protocol in agent, and move LocalNode
ephraimduncan Nov 6, 2026
b10fd67
refactor(fleet): give the fleet its own host type, and seed the pool …
ephraimduncan Nov 6, 2026
fa1e170
refactor(fleet): get the runner versions to try from the versions ser…
ephraimduncan Nov 6, 2026
b857d8c
refactor(store,scheduler): give the finish step its own mark
ephraimduncan Nov 6, 2026
9390188
Merge branch 'refactor/untangle' into untangle/fx2
ephraimduncan Nov 6, 2026
0e81132
refactor(fleet): keep the doctor result in the fleet
ephraimduncan Nov 6, 2026
3fe3ba3
refactor(fleet): record the server audit entries in the fleet
ephraimduncan Nov 6, 2026
d2efc18
refactor(api): move the API rules into their services
ephraimduncan Nov 6, 2026
e6c120e
Merge branch 'refactor/untangle' into untangle/fx3
ephraimduncan Nov 6, 2026
5382d7a
Merge branch 'refactor/untangle' into untangle/fx4
ephraimduncan Nov 6, 2026
cdc3043
refactor(store): drop the unused path columns and the address index
ephraimduncan Nov 6, 2026
54407d4
feat(api): give the systems of install.sh to the add-server dialog
ephraimduncan Nov 6, 2026
a8e490c
ci: run the sandbox tests on Docker and Sysbox
ephraimduncan Nov 6, 2026
92f3267
Merge branch 'refactor/untangle' into untangle/fx1
ephraimduncan Nov 6, 2026
25a7d9d
test(fleet): wait for the audit entry of the default label
ephraimduncan Nov 6, 2026
6e8e9a7
Merge branch 'refactor/untangle' into untangle/fx4
ephraimduncan Nov 6, 2026
dbb5fe4
refactor(api): give the web the page paths, events, and facts of Go
ephraimduncan Nov 6, 2026
a031942
refactor(web): give each copied page rule one place
ephraimduncan Nov 6, 2026
4dd9463
fix(api): count the vCPUs of disabled servers in the overview
ephraimduncan Nov 6, 2026
609d91d
refactor: merge origin/main into the new structure
ephraimduncan Nov 6, 2026
a730dd2
Merge branch 'refactor/untangle' into untangle/fx1
ephraimduncan Nov 6, 2026
09cf5bf
refactor(web): remove the hold poll of Job detail
ephraimduncan Nov 6, 2026
c6e6d68
refactor(web): read has_jobs on the Overview
ephraimduncan Nov 6, 2026
fbeaaed
refactor(web): keep the muted server statuses next to StatusDot
ephraimduncan Nov 6, 2026
0525199
refactor(api): give each job step its status from Go
ephraimduncan Nov 6, 2026
107baf0
refactor(api): remove auto_update from the update status
ephraimduncan Nov 6, 2026
b8acfc9
fix(agent): keep the last settings of the primary for the next start
ephraimduncan Nov 6, 2026
d7d97ba
fix(fleet): close the connect window for settings and removals
ephraimduncan Nov 6, 2026
5768141
fix(fleet): examine the status change before UpdateServer writes the …
ephraimduncan Nov 6, 2026
6898cc1
refactor(settings): accept only the egress entries that netrules applies
ephraimduncan Nov 6, 2026
cf50680
fix(fleet): record the size of an image that the server gives
ephraimduncan Nov 6, 2026
7b86f9b
fix(image): let the image GC and the runner prune wait for Ensure
ephraimduncan Nov 6, 2026
91a33ee
test(image): run TestRootDiskMounts as root
ephraimduncan Nov 6, 2026
4d485f3
docs(readme): tell which changes start the images workflow
ephraimduncan Nov 6, 2026
abbaa52
refactor(api): give auth, audit, and the API one owner for each rule
ephraimduncan Nov 6, 2026
ee11b0c
Merge branch 'refactor/untangle' into untangle/fy3
ephraimduncan Nov 6, 2026
bc1a9b2
Merge branch 'refactor/untangle' into untangle/fy2
ephraimduncan Nov 6, 2026
b226976
Merge branch 'untangle/fy2' into refactor/untangle
ephraimduncan Nov 6, 2026
317ef1c
refactor(github): move the GitHub App domain to ghapp
ephraimduncan Nov 6, 2026
13d2246
refactor(store): give jobs one wait rule and one status list
ephraimduncan Nov 6, 2026
dfc4db4
Merge branch 'refactor/untangle' into untangle/fy1
ephraimduncan Nov 6, 2026
22a00c1
refactor(netrules): make dropChains internal
ephraimduncan Nov 6, 2026
c3ecca6
refactor(guest): give init one cache URL
ephraimduncan Nov 6, 2026
50b2f9e
fix(sysbox): reach runplane at the network gateway on a local Docker
ephraimduncan Nov 6, 2026
902b139
fix(sysbox): measure the scratch volumes of dev mode through Docker
ephraimduncan Nov 6, 2026
b022313
test(sandbox): run the runplane-init of make init in the sandbox tests
ephraimduncan Nov 6, 2026
0dc0838
fix(doctor): use the mode rule and the settings of the service
ephraimduncan Nov 6, 2026
763cecb
Merge branch 'refactor/untangle' into untangle/fy5
ephraimduncan Nov 6, 2026
b403c7f
refactor: merge origin/main into the new structure
ephraimduncan Nov 6, 2026
eb28da1
fix(install): make the setup code before the first start
ephraimduncan Nov 6, 2026
1c7c712
ci: run the init tests as root, and all tests of the sandbox step
ephraimduncan Nov 6, 2026
ac52245
refactor(web): write the role in a sentence with one function
ephraimduncan Nov 6, 2026
14d4337
Merge branch 'refactor/untangle' into untangle/fz3
ephraimduncan Nov 6, 2026
c11c7a7
fix(fleet): let the image GC wait for the pulls of the server
ephraimduncan Nov 6, 2026
5ffd9bc
fix(fleet): send the settings to a server one at a time
ephraimduncan Nov 6, 2026
9712649
fix(firecracker): write the VM firewall at each Configure
ephraimduncan Nov 6, 2026
dba3c52
docs(api): tell that the servers remove a removed image later
ephraimduncan Nov 6, 2026
f4d98d8
Merge branch 'refactor/untangle' into untangle/fz2
ephraimduncan Nov 6, 2026
8fc59ec
Merge branch 'untangle/fz2' into refactor/untangle
ephraimduncan Nov 6, 2026
04e9b82
fix(store): reset the assignment time of a job that opens again
ephraimduncan Nov 6, 2026
c556ba0
refactor(api): remove GitHubStatus.connected and JobSummary.result
ephraimduncan Nov 6, 2026
335b637
refactor(policy): one rule for the jobs of public repositories
ephraimduncan Nov 6, 2026
cda9707
fix(web): refetch the queries that the settings and the servers change
ephraimduncan Nov 6, 2026
318b77f
refactor(web): let PullRequestForm read the GitHub status itself
ephraimduncan Nov 6, 2026
c0c1dfa
Merge branch 'refactor/untangle' into untangle/fz1
ephraimduncan Nov 6, 2026
e18f55f
fix(scheduler): write the sandbox row before the JIT config
ephraimduncan Nov 6, 2026
9b8044a
fix(settings): keep allow_public_repos when set-mode sets VM mode
ephraimduncan Nov 6, 2026
dae398e
fix(install): stop the primary before the new binary opens the database
ephraimduncan Nov 6, 2026
bae1fc9
test(web): run the tests in one time zone and locale
ephraimduncan Nov 6, 2026
07bb250
test(web/api): type the event fixtures and test the route guards
ephraimduncan Nov 6, 2026
586053b
test(web/app): examine barScale, not its niceStep helper
ephraimduncan Nov 6, 2026
9e610e4
test(web/lib): name the locale that the formatCount test examines
ephraimduncan Nov 6, 2026
862ee41
test(web/overview): read the chart labels in the zone of the config
ephraimduncan Nov 6, 2026
1741314
test(web/runners): examine the PATCH body through poolUpdate
ephraimduncan Nov 6, 2026
a98358d
test(web/jobs): examine the results, not the shape of the objects
ephraimduncan Nov 6, 2026
c12d172
test(web/github): examine the search query, not the full request URLs
ephraimduncan Nov 6, 2026
a38fc9c
test(web/settings): examine lineNumber and saveError each on its own
ephraimduncan Nov 6, 2026
be8efec
test(config): use one rule for the folder modes
ephraimduncan Nov 6, 2026
c637ec7
test(initbin): examine the runplane-init that make init embeds
ephraimduncan Nov 6, 2026
12a1b6c
refactor(web): remove three exports that only the tests used
ephraimduncan Nov 6, 2026
ce8976f
test(init): examine the control channel and the shell through effects
ephraimduncan Nov 6, 2026
eea696b
test(lifecycle): examine the end state and the time limit through Core
ephraimduncan Nov 6, 2026
3be3201
test(netrules): send packets to the cloud services, remove internal t…
ephraimduncan Nov 6, 2026
a5c1048
test(agent): wait for the next connection, not for log text
ephraimduncan Nov 6, 2026
f270b48
test(scratch): find a mount after Detach without mountSource
ephraimduncan Nov 6, 2026
de43597
test(firecracker): check only the boot arguments that the guest needs
ephraimduncan Nov 6, 2026
34be7ab
test(sysbox): check the mounts that the guest needs, not a list copy
ephraimduncan Nov 6, 2026
a61f57e
test(host): give TestRegion answers for Vultr and DigitalOcean
ephraimduncan Nov 6, 2026
264c9fe
test(doctor): check the ports of a running server through Run
ephraimduncan Nov 6, 2026
258d16e
Merge branch 'untangle/t2' into refactor/untangle
ephraimduncan Nov 6, 2026
3dce6c8
test(fleet): examine the agent update and host stats through the API
ephraimduncan Nov 6, 2026
bd75b78
test(shell): examine Target.Access, refuse a sandbox before its job
ephraimduncan Nov 6, 2026
9303045
test(sshinstall): read known_hosts as OpenSSH, cancel at the command
ephraimduncan Nov 6, 2026
7435232
test(cache): examine the cleanup and the counts through Run and HTTP
ephraimduncan Nov 6, 2026
05660c0
test(image): put the ext4 content checks in a subtest
ephraimduncan Nov 6, 2026
d3be9d1
test(runner): put the ext4 content checks in a subtest
ephraimduncan Nov 6, 2026
ec1911a
test(ext4): skip the checks that need e2fsprogs
ephraimduncan Nov 6, 2026
74dc71e
Merge branch 'untangle/t3' into refactor/untangle
ephraimduncan Nov 6, 2026
162ee10
test(update): use KernelName, and end the busy test at once
ephraimduncan Nov 6, 2026
c42a472
test(events): see the end of a subscription through Publish
ephraimduncan Nov 6, 2026
237983e
test(ghrest): read the pages of a list through List
ephraimduncan Nov 6, 2026
97b533a
test(joblog): read the steps of a stored log through Logs.Job
ephraimduncan Nov 6, 2026
ecdb6e0
test(tlsutil): remove the copy of Fingerprint from TestAgentCertPersists
ephraimduncan Nov 6, 2026
1d21cd2
test(backup): examine the backups through Service.Create
ephraimduncan Nov 6, 2026
a3512c0
test(auth): examine the hashes and the setup codes through the API
ephraimduncan Nov 6, 2026
fd6004a
test(notify): examine the alerts through the bus and the channels
ephraimduncan Nov 6, 2026
5217481
test(api): examine the shell answers through HTTP and WebSocket
ephraimduncan Nov 6, 2026
1dff6ba
test(github): examine the service through its exported methods
ephraimduncan Nov 6, 2026
e3c9991
Merge branch 'untangle/t4' into refactor/untangle
ephraimduncan Nov 6, 2026
3751e2e
Merge branch 'refactor/untangle' into untangle/fw1
ephraimduncan Nov 6, 2026
fe6a7a0
fix(fleet): write the host samples at each end of Run
ephraimduncan Nov 6, 2026
ad91ecb
ci: run make init before go test
ephraimduncan Nov 6, 2026
01e5268
test(guest): name images/Dockerfile in the layout test comment
ephraimduncan Nov 6, 2026
f4599ce
fix(install): reject each --domain that set-domain rejects
ephraimduncan Nov 6, 2026
a8ddea5
fix(install): stop the primary before write_units
ephraimduncan Nov 6, 2026
3b5ffcf
test(scheduler): examine the scheduler through Scale, Run, and its ev…
ephraimduncan Nov 6, 2026
2464050
test(store): change the database outside the store with its own conne…
ephraimduncan Nov 6, 2026
fad352f
test(settings): read the settings events without a wait
ephraimduncan Nov 6, 2026
f4b284b
test(cmd): run the operator commands through the command line
ephraimduncan Nov 6, 2026
dd9fa49
Merge branch 'untangle/t5' into refactor/untangle
ephraimduncan Nov 6, 2026
f7d7c26
test(lifecycle): power off the guest after the shutdown request in Te…
ephraimduncan Nov 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
27 changes: 25 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,13 @@ jobs:
- run: go vet ./...
# The non-Linux files must also compile, for development on macOS.
- run: GOOS=darwin go vet ./...
# The tests of internal/initbin examine the runplane-init of make init.
- run: make init
- run: go test ./...
# Tests of netlink, nftables, loop devices, and mounts skip without root.
# Tests of netlink, nftables, loop devices, mounts, and the debug shell
# of runplane-init skip without root.
- name: go test as root
run: sudo --preserve-env=GOCACHE,GOMODCACHE,GOPATH,HOME "$(go env GOROOT)/bin/go" test ./internal/...
run: sudo --preserve-env=GOCACHE,GOMODCACHE,GOPATH,HOME "$(go env GOROOT)/bin/go" test ./init/... ./internal/...
env:
GOCACHE: /tmp/go-root-cache

Expand All @@ -53,6 +56,11 @@ jobs:
cache: pnpm
cache-dependency-path: web/pnpm-lock.yaml
- run: pnpm install --frozen-lockfile
- uses: actions/setup-go@v7
with:
go-version-file: go.mod
# The committed spec, types, and limits must match the Go API.
- run: pnpm gen:api && git diff --exit-code -- src/api
- run: pnpm typecheck
- run: pnpm test
- run: pnpm build
Expand Down Expand Up @@ -97,3 +105,18 @@ jobs:
test ! -e /usr/local/bin/runplane
test ! -e /etc/systemd/system/runplane.service
sudo test ! -e /var/lib/runplane
# The tests that start real sandboxes, on the Docker and Sysbox that
# the uninstall keeps. The service and its firewall rules are gone, so
# the tests can own the runplane network. -p 1 runs one package at a
# time, because the two packages use the same network. The sandboxes
# run the runplane-init that make binary embedded.
- name: Sandbox tests on Docker and Sysbox
run: |
sudo apt-get update -q
sudo apt-get install -y -q --no-install-recommends nftables
sudo docker build -q -t runplane-test internal/sandbox/sysbox/sysboxtest
sudo --preserve-env=GOCACHE,GOMODCACHE,GOPATH,HOME \
RUNPLANE_TEST_DOCKER=1 RUNPLANE_TEST_IMAGE=runplane-test \
"$(go env GOROOT)/bin/go" test -count=1 -p 1 -v ./internal/sandbox/sysbox/ ./internal/sandbox/devdocker/
env:
GOCACHE: /tmp/go-root-cache
33 changes: 23 additions & 10 deletions .github/workflows/images.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
# Builds the base images for linux/amd64 and linux/arm64 and pushes them to
# ghcr.io/<owner>/<repo>/runner-ubuntu-24.04 and -26.04. runplane pulls the
# "latest" tag. A weekly build gets the new packages and tool versions.
# ghcr.io/<owner>/<repo>/runner-<name>. runplane pulls the "latest" tag. A
# weekly build gets the new packages and tool versions. The two matrices
# must name the images and the build args of images/images.go
# (images_test.go compares them).
#
# The builds use the runplane runners. QEMU builds the architecture that the
# runner does not have, which makes that build much slower.
#
# The build context is the images folder, and images/.dockerignore keeps
# only the Dockerfile in it. A change to images.go, its test, or the README
# does not change an image, so it starts no build. A new image changes this
# file too, because the matrices must name it.
name: Images

on:
push:
branches: [main]
paths: ['images/**', '.github/workflows/images.yml']
paths: ['images/Dockerfile', 'images/.dockerignore', '.github/workflows/images.yml']
pull_request:
paths: ['images/**', '.github/workflows/images.yml']
paths: ['images/Dockerfile', 'images/.dockerignore', '.github/workflows/images.yml']
schedule:
- cron: '23 4 * * 1'
workflow_dispatch:
Expand All @@ -24,7 +31,9 @@ jobs:
strategy:
fail-fast: false
matrix:
image: [ubuntu-24.04, ubuntu-26.04]
image:
- {name: ubuntu-24.04, ubuntu: '24.04', image_os: ubuntu24}
- {name: ubuntu-26.04, ubuntu: '26.04', image_os: ubuntu26}
arch: [amd64, arm64]
runs-on: runplane
permissions:
Expand All @@ -33,7 +42,7 @@ jobs:
steps:
- uses: actions/checkout@v7
- name: Image name
run: echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}/runner-${{ matrix.image }}" >> "$GITHUB_ENV"
run: echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}/runner-${{ matrix.image.name }}" >> "$GITHUB_ENV"
- uses: docker/setup-qemu-action@v4
- uses: docker/setup-buildx-action@v4
- uses: docker/login-action@v4
Expand All @@ -46,20 +55,24 @@ jobs:
id: build
uses: docker/build-push-action@v7
with:
context: images/${{ matrix.image }}
context: images
platforms: linux/${{ matrix.arch }}
build-args: |
UBUNTU=${{ matrix.image.ubuntu }}
IMAGE_OS=${{ matrix.image.image_os }}
labels: |
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.revision=${{ github.sha }}
outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
# VM mode copies the image into an ext4 root disk, so keep it small.
- name: Check the size (3 GB or less)
run: |
docker buildx build --platform linux/${{ matrix.arch }} --load -t size-check -q images/${{ matrix.image }} >/dev/null
docker buildx build --platform linux/${{ matrix.arch }} --load -t size-check -q \
--build-arg UBUNTU=${{ matrix.image.ubuntu }} --build-arg IMAGE_OS=${{ matrix.image.image_os }} images >/dev/null
mb=$(docker run --rm size-check du -sxm / | cut -f 1)
echo "Image size: $mb MB"
if [ "$mb" -gt 3072 ]; then
echo "::error::${{ matrix.image }} uses $mb MB. The limit is 3072 MB."
echo "::error::${{ matrix.image.name }} uses $mb MB. The limit is 3072 MB."
exit 1
fi
- name: Check that jobs find rustup
Expand All @@ -73,7 +86,7 @@ jobs:
- uses: actions/upload-artifact@v7
if: github.event_name != 'pull_request'
with:
name: digests-${{ matrix.image }}-${{ matrix.arch }}
name: digests-${{ matrix.image.name }}-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error

Expand Down
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ dev: init

# runner-smoke downloads the latest actions/runner for this arch and starts
# it in the local base image runplane/runner-ubuntu-24.04:local (docker build
# --provenance=false -t runplane/runner-ubuntu-24.04:local images/ubuntu-24.04):
# the .NET libraries must be in the image, and a bad JIT config must end the
# runner.
# --provenance=false -t runplane/runner-ubuntu-24.04:local --build-arg
# UBUNTU=24.04 --build-arg IMAGE_OS=ubuntu24 images): the .NET libraries must
# be in the image, and a bad JIT config must end the runner.
runner-smoke:
go test -tags integration -count=1 -timeout 20m -v -run TestRealRunnerInBaseImage ./internal/image/
go test -tags integration -count=1 -timeout 20m -v -run TestRealRunnerInBaseImage ./internal/runner/

# clean keeps the other files in .dev, such as notes.
clean:
Expand Down
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ The script does these steps:
3. It downloads runplane and makes sure that the signature of `SHA256SUMS` and the SHA-256 of each file are correct (refer to [Release](#release)).
4. In container mode, it installs Docker Engine (only if the server does not have it) and Sysbox.
5. In VM mode, it installs Firecracker v1.17.0, the jailer, and the guest kernel. It also gives the user `runplane-vm` a range of uids and gids, one for each VM. If the base image of the release repository is not public on GHCR, it installs Docker Engine, because runplane then builds the base image on the server. Docker builds images only, and the jobs operate in VMs.
6. It writes `/etc/runplane/runplane.env` and the systemd units, then it starts `runplane.service`.
7. It runs `runplane doctor` and shows the dashboard URL and a one-time setup code.
6. It writes `/etc/runplane/runplane.env` and the systemd units, and it makes a one-time setup code. Then it starts `runplane.service`.
7. It runs `runplane doctor` and shows the dashboard URL and the setup code.

To see each step before the install, add `--dry-run`. The dry run changes nothing on the server.

Expand Down Expand Up @@ -66,7 +66,7 @@ In VM mode, the script installs Firecracker v1.17.0, which the runplane tests us
curl -fsSL https://github.com/runplane/runplane/releases/latest/download/install.sh | sudo RUNPLANE_FIRECRACKER_VERSION=v1.16.1 sh
```

To update runplane, run the install command again. You can also select the update in **Settings > General**, or run `sudo runplane update` on the server. In VM mode, the update also replaces the guest kernel with the kernel of the release. A restart of runplane does not stop the jobs that operate. A shutdown of the server stops the jobs that operate with the result `cancelled`.
To update runplane, run the install command again. You can also select the update in **Settings > General**, or run `sudo runplane update` on the primary. In VM mode, the update also replaces the guest kernel with the kernel of the release. A restart of runplane does not stop the jobs that operate. A shutdown of the server stops the jobs that operate with the result `cancelled`.

The primary updates its agents. When an agent connects with a different version, the primary sends it the update to its own release. After an update of the primary, the agents connect again and get the new release. The primary tries each version one time on each agent. If the update is not successful, the **Servers** page shows **Update failed** after the name of the server. The page of the server shows the reason. You can start the update again with **Update agent** in the menu of the server. A primary that is not a release build does not update its agents.

Expand All @@ -76,7 +76,7 @@ You can also update an agent by hand. Run this command on the agent server:
curl -fsSL http://203.0.113.10:8484/install.sh | sudo sh
```

The primary serves this script. Thus the agent gets the version of the primary. On an agent, the script keeps the registration in `/etc/runplane/agent.json` and does not install a primary. On the agent server, `sudo runplane update` installs the latest release.
The primary serves this script. Thus the agent gets the version of the primary. On an agent, the script keeps the registration in `/etc/runplane/agent.json` and does not install a primary. An agent must run the release of its primary, so `sudo runplane update` does not operate on an agent.

To remove runplane, run this command:

Expand Down Expand Up @@ -187,7 +187,7 @@ An agent must run the same release as the primary. The primary updates each agen

**Warning:** Use runplane only with private repositories. A pull request from a fork of a public repository can run code on your server.

In container mode, runplane always rejects jobs from public repositories. All Sysbox containers share the host kernel and one ID mapping, thus the isolation between jobs is weaker. In VM mode, runplane rejects jobs from public repositories and from fork pull requests, unless you change these settings. You can let jobs from public repositories run only if each server operates in VM mode.
In container mode, runplane never runs jobs from public repositories. All Sysbox containers share the host kernel and one ID mapping, thus the isolation between jobs is weaker. In VM mode, runplane rejects jobs from public repositories and from fork pull requests, unless you change these settings. You can turn on the setting for public repositories only if each server operates in VM mode. While the setting is on, a server that connects in a different mode gets no runners, and the **Servers** page tells the cause. To give runners to that server again, turn the setting off.

| Item | Container mode (Sysbox CE) | VM mode (Firecracker) |
| --- | --- | --- |
Expand All @@ -196,7 +196,7 @@ In container mode, runplane always rejects jobs from public repositories. All Sy
| Network model | One Docker bridge, with the MAC and IP binding in `bridge runplane` | A TAP with a /30 for each VM |
| AppArmor | The Sysbox profile | Not applicable |
| Host daemon on the `/proc` path | `sysbox-fs` (Sysbox issue 1018) | None |
| Public repositories | Rejected | Permitted with the setting |
| Public repositories | Never | Permitted with the setting |

Sandboxes cannot connect to the host, to other sandboxes, to private networks, to `169.254.169.254`, or to the Azure host endpoint `168.63.129.16`. They can connect only to the public internet and to the runplane cache service on the host.

Expand Down Expand Up @@ -295,10 +295,10 @@ Other commands:
| `sh deploy/test-install.sh` | Dry runs of `install.sh` in Ubuntu, Debian, and Fedora containers |
| `kernel/build.sh --config-only` | A check of the guest kernel config, without a kernel build |

The tests of netlink, nftables, loop devices, and mounts must have root access on Linux. To do these tests on macOS, use a Linux container:
The tests of netlink, nftables, loop devices, mounts, and the debug shell of `runplane-init` must have root access on Linux. To do these tests on macOS, use a Linux container:

```sh
docker run --rm --privileged -v "$PWD":/src -v "$HOME/go/pkg/mod":/go/pkg/mod -w /src golang:1.27 go test ./internal/...
docker run --rm --privileged -v "$PWD":/src -v "$HOME/go/pkg/mod":/go/pkg/mod -w /src golang:1.27 go test ./init/... ./internal/...
```

## Release
Expand All @@ -321,4 +321,4 @@ A person who can change the release files can also change the `install.sh` of th

**Caution:** Do not change the key after the first release. A binary with the earlier key cannot do a self-update to a release with a new key. On these servers, run the install command of the new release again.

The `images.yml` workflow pushes the base images to GHCR each week and after each change in `images/`. The builds use the `runplane` label. QEMU builds the architecture that the runner does not have. After the first push, set the visibility of each image package on GHCR to public. Then servers pull the base images without a login, and VM mode does not need Docker. To do a check, run `docker logout ghcr.io && docker pull ghcr.io/<owner>/<repo>/runner-ubuntu-24.04:latest`.
The `images.yml` workflow pushes the base images to GHCR each week and after each change of `images/Dockerfile`. The builds use the `runplane` label. QEMU builds the architecture that the runner does not have. After the first push, set the visibility of each image package on GHCR to public. Then servers pull the base images without a login, and VM mode does not need Docker. To do a check, run `docker logout ghcr.io && docker pull ghcr.io/<owner>/<repo>/runner-ubuntu-24.04:latest`.
30 changes: 17 additions & 13 deletions cmd/runplane/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,38 @@ import (
"context"
"errors"
"flag"
"net/netip"
"slices"

"github.com/runplane/runplane/internal/agent"
"github.com/runplane/runplane/internal/config"
"github.com/runplane/runplane/internal/sandbox"
"github.com/runplane/runplane/internal/localnode"
"github.com/runplane/runplane/internal/policy"
"github.com/runplane/runplane/internal/version"
)

// runAgent operates the sandboxes of this server for the primary in
// agent.json. The primary sends the settings when the agent connects.
// agent.json. The primary sends the settings when the agent connects. The
// agent keeps them, so that after a restart the sandboxes keep their egress
// allowlist before the primary connects.
func runAgent(ctx context.Context, args []string) error {
cfg, err := config.Parse(flag.NewFlagSet("agent", flag.ContinueOnError), args)
cfg, err := config.Parse(flag.NewFlagSet("agent", flag.ContinueOnError), args,
config.ServicePort, config.DataDir, config.Mode, config.Dev, config.DevInsecure)
if err != nil {
return err
}
log := newLogger(ctx, cfg)
if err := checkMode(cfg.Mode, cfg.DevInsecure); err != nil {
if err := policy.CheckMode(cfg.Mode, cfg.DevInsecure); err != nil {
return err
}
if err := cfg.EnsureDirs(); err != nil {
return err
}
l, err := newLocal(ctx, cfg, localConfig{mode: cfg.Mode, unit: "runplane-agent", listen: []string{servicePortAddr(cfg)}}, log)
settings, err := localnode.ReadSettings(cfg.AgentSettingsPath())
if err != nil {
log.Warn("the sandboxes have no egress allowlist until the primary connects", "err", err)
}
l, err := newLocal(ctx, cfg, localConfig{
mode: cfg.Mode, settings: settings, settingsFile: cfg.AgentSettingsPath(), doctor: doctorOptions(cfg, cfg.Mode, true, ""),
}, log)
if err != nil {
return err
}
Expand All @@ -38,18 +46,14 @@ func runAgent(ctx context.Context, args []string) error {
defer func() { stopNode(); <-nodeDone }()

proxy := agent.NewCacheProxy(l.driver, log.With("component", "cache"))
hasSandbox := func(ip netip.Addr) bool {
list, err := l.driver.List(context.Background())
return err == nil && slices.ContainsFunc(list, func(b sandbox.Sandbox) bool { return b.IP == ip.String() })
}
mir, stopPort, err := serveServicePort(cfg, cfg.Mode, hasSandbox, proxy, log)
stopPort, err := serveServicePort(cfg, l.node.Mirror(), proxy, log)
if err != nil {
return err
}
defer stopPort()

log.Info("runplane agent started", "version", version.String(), "mode", cfg.Mode, "config", cfg.AgentConfigPath())
err = agent.Run(ctx, agent.Config{Path: cfg.AgentConfigPath(), Node: l.node, CacheProxy: proxy, Mirror: mir.Stats, Logger: log})
err = agent.Run(ctx, agent.Config{Path: cfg.AgentConfigPath(), Node: l.node, CacheProxy: proxy, Version: version.Version, Logger: log})
if errors.Is(err, agent.ErrUpdated) {
// systemd starts the new binary. The sandboxes keep operating, and
// the driver takes them over after the restart.
Expand Down
Loading
Loading