Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions dag/extdeps/cache/sccache.dag
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ data sccache_installed_binary_path_note: String = "Single authority for WHERE th

data sccache_installed_binary_path: String = "/usr/local/bin/sccache"

// These names are part of sccache's cited configuration interface, not facts invented by the
// systemd renderer or by the readiness observer. Keeping the names here lets both consumers compose
// assignments and reads from one authority.
data sccache_cache_dir_env_var: NonEmptyStr = "SCCACHE_DIR" as NonEmptyStr
data sccache_cache_size_env_var: NonEmptyStr = "SCCACHE_CACHE_SIZE" as NonEmptyStr

fn sccache_install_script(rel: SccacheBinaryRelease, arch: NonEmptyStr, digest: Digest) -> String {
let dir = join(["sccache-", rel.version as String, "-", arch as String, "-unknown-linux-musl"], "")
let url = join(["https://github.com/mozilla/sccache/releases/download/", rel.version as String, "/", dir, ".tar.gz"], "")
Expand Down
34 changes: 34 additions & 0 deletions dag/extdeps/systemd/systemctl.dag
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ fn systemctl_enable_argv(unit: NonEmptyStr) -> List<String> {
["systemctl", "enable", unit as String]
}

// START IS NOT RESTART, AND FOR A SLICE THE DIFFERENCE IS DESTRUCTIVE RATHER THAN STYLISTIC. Stopping a
// slice kills every process in it (systemd.slice(5)), so `restart` applied to a compile pool would terminate
// the compilers the pool exists to hold. `start` on an already-active slice is a no-op that re-applies the
// unit's resource directives, which is what a converger wants. The modeled `Start` operation already exists
// on the service surface; this is its argv authority for the shell-body realization edge.
fn systemctl_start_argv(unit: NonEmptyStr) -> List<String> {
["systemctl", "start", unit as String]
}

fn systemctl_restart_argv(unit: NonEmptyStr) -> List<String> {
["systemctl", "restart", unit as String]
}
Expand Down Expand Up @@ -128,6 +137,14 @@ fn systemctl_user_start_argv(unit: NonEmptyStr) -> List<String> {
["systemctl", "--user", "start", unit as String]
}

// LoadState is the only observation that distinguishes an ABSENT unit from a present one, which is why the
// `ShowLoadState` operation on the service surface above is its own operation rather than a
// SystemdUnitProperty arm: that coproduct is numeric cgroup evidence sharing one numeric mock, and a wire
// value of `not-found` is not a magnitude. Cited to systemd.unit(5) LoadState -- `loaded`, `not-found`,
// `bad-setting`, `error`, `masked` -- of which `not-found` is the one this corpus reads positively.
// `systemctl show` exits 0 for a unit the manager has never heard of and prints not-found, so a nonzero exit
// means the MANAGER was unreadable, which is a different refusal from an absent unit and must not be folded
// into it.
fn systemctl_show_load_state_argv(unit: NonEmptyStr) -> List<String> {
["systemctl", "show", unit as String, "--property=LoadState", "--value"]
}
Expand Down Expand Up @@ -302,6 +319,23 @@ service systemd.Systemctl {
}
}

operation ShowLoadState {
input { unit: NonEmptyStr }
output {
value: String from "stdout"
success: Bool from "exit_success"
}
readonly
transport shell { argv: ["systemctl", "show", "{unit}", "--property=LoadState", "--value"] }
exit {
0 => Unit
nonzero => String "systemctl show LoadState failed"
}
mock_response {
0 => { value: "not-found", success: true } "hermetic systemd.Systemctl.ShowLoadState"
}
}

operation ListUnits {
input {
pattern: NonEmptyStr,
Expand Down
14 changes: 9 additions & 5 deletions dag/gunbc/build_cache_instance.dag
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ import extdeps.cache.sccache { SccacheServerEndpoint, SccacheServerUnixSocket, s
import gunbc.fleet_intent_network {
operator_host_srv1, operator_host_srv2, operator_host_srv3, operator_host_srv4,
}
import gunbc.host_layout { gunbc_managed_compile_pool_slice }
import gunbc.host_layout {
gunbc_managed_compile_pool_slice,
CompilePoolPlacement, CompilePoolSliceDeclared, CompilePoolInRunnerSlots,
gunbc_compile_pool_placement,
}

data build_cache_instance_scope_disposition: Disposition = SingleAuthority

Expand All @@ -34,10 +38,10 @@ type BuildCacheInstance {
intended_principal: NonEmptyStr
intended_storage: NonEmptyStr
intended_capacity: ByteSize?
intended_compile_pool: NonEmptyStr
intended_compile_pool: CompilePoolPlacement
}

data build_cache_configuration_observation_note: String = "STORAGE ROOT AND CAPACITY ARE TWO OBSERVED CONFIGURATION AXES, and each observation is bound to both the exact deployed BuildCacheInstance and the ProcessIdentity whose environment was read. A path or byte count without both subjects could be replayed across hosts, across the CI and session instances that share one sccache implementation, or across two processes after pid reuse. The owner is the process already proven to hold the instance endpoint; a unit file would answer what systemd WOULD start, not how the live server is configured, and every host in the incident population currently runs a server systemd did not start.\n\nUNSET AND READ UNAVAILABLE ARE DIFFERENT OBSERVATIONS WITH DIFFERENT REMEDIES. Unset means the owner environment was read and carries no assignment; unavailable means the read did not answer, and must never narrow to unset. Endpoint or owner absence does not appear as a third arm here: without the prerequisite endpoint-owner observation there is no configuration subject, so these carriers are not constructed at all. That is not-applicability at the join rather than malformed configuration.\n\nCAPACITY ALSO RETAINS CONFIGURED TEXT THAT CANNOT YET BE GROUNDED AS BYTES. gunbc.build_cache_unit emits a plain decimal byte count, which has one exact decoding. sccache also accepts suffixed text such as its documented 10G default, but this repository has no cited rule deciding whether G denotes 10^9 or 2^30. Choosing either would fabricate a magnitude whose seven-percent difference could silently pass or refuse convergence. BuildCacheCapacityConfiguredUngrounded therefore carries the text verbatim; it narrows when extdeps.cache.sccache cites and models the accepted size grammar. The instance itself retains whether capacity intent is declared, so a later comparison can refuse intended_capacity Absent rather than freezing a vendor default as a decision.\n\nThese are carriers only: they mint no verified flag and perform no host read. A producer must read the endpoint owner's environment into one of these arms before runner activation can replace storage_verified and capacity_verified with typed observed-versus-intended comparisons."
data build_cache_configuration_observation_note: String = "STORAGE ROOT AND CAPACITY ARE TWO OBSERVED CONFIGURATION AXES, and each observation is bound to both the exact deployed BuildCacheInstance and the ProcessIdentity whose environment was read. A path or byte count without both subjects could be replayed across hosts, across the CI and session instances that share one sccache implementation, or across two processes after pid reuse. The owner is the process already proven to hold the instance endpoint; a unit file would answer what systemd WOULD start, not how the live server is configured, and every host in the incident population currently runs a server systemd did not start.\n\nUNSET AND READ UNAVAILABLE ARE DIFFERENT OBSERVATIONS WITH DIFFERENT REMEDIES. Unset means the owner environment was read and carries no assignment; unavailable means the read did not answer, and must never narrow to unset. Endpoint or owner absence does not appear as a third arm here: without the prerequisite endpoint-owner observation there is no configuration subject, so these carriers are not constructed at all. That is not-applicability at the join rather than malformed configuration.\n\nCAPACITY ALSO RETAINS CONFIGURED TEXT THAT CANNOT YET BE GROUNDED AS BYTES. gunbc.build_cache_unit emits a plain decimal byte count, which has one exact decoding. sccache also accepts suffixed text such as its documented 10G default, but this repository has no cited rule deciding whether G denotes 10^9 or 2^30. Choosing either would fabricate a magnitude whose seven-percent difference could silently pass or refuse convergence. BuildCacheCapacityConfiguredUngrounded therefore carries the text verbatim; it narrows when extdeps.cache.sccache cites and models the accepted size grammar. The instance itself retains whether capacity intent is declared, so gunbc.build_cache_instance_readiness refuses intended_capacity Absent rather than freezing a vendor default as a decision.\n\nThese carriers are consumed by gunbc.build_cache_instance_readiness, whose producer preserves unavailable separately from observed mismatch and is the only function that mints the proof-shaped BuildCacheInstanceReady receipt."

type BuildCacheStorageConfiguration
= BuildCacheStorageRootConfigured { root: NonEmptyStr }
Expand Down Expand Up @@ -284,7 +288,7 @@ fn ci_cache_instance(host: HostIdentity) -> BuildCacheInstance {
intended_principal: "ghrunner" as NonEmptyStr,
intended_storage: "/var/lib/ctrl/sccache-ci" as NonEmptyStr,
intended_capacity: none,
intended_compile_pool: gunbc_managed_compile_pool_slice,
intended_compile_pool: gunbc_compile_pool_placement,
}
}

Expand All @@ -301,7 +305,7 @@ fn session_cache_instance(host: HostIdentity) -> BuildCacheInstance {
intended_principal: "briansrls" as NonEmptyStr,
intended_storage: "/var/lib/ctrl/sccache" as NonEmptyStr,
intended_capacity: Present { value: gibibyte_to_byte_size(g: gibibyte(50)) },
intended_compile_pool: gunbc_managed_compile_pool_slice,
intended_compile_pool: gunbc_compile_pool_placement,
}
}

Expand Down
Loading