@crvouga/dev-fleet 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +237 -37
- package/agents/setup.md +42 -12
- package/ansible/macos/manager.yml +7 -7
- package/ansible/macos/policy.json +2 -10
- package/ansible/monitoring/README.md +86 -25
- package/ansible/monitoring/agent.yml +40 -2
- package/ansible/monitoring/hub-route-darwin.yml +51 -0
- package/ansible/monitoring/lock.json +5 -0
- package/ansible/pyproject.toml +12 -0
- package/ansible/ubuntu/baseline.yml +1 -1
- package/ansible/ubuntu/disk-gc.py +336 -0
- package/ansible/ubuntu/policy.json +12 -3
- package/ansible/ubuntu/tailscale.yml +8 -5
- package/ansible/ubuntu/tasks/resources.yml +61 -1
- package/ansible/uv.lock +190 -0
- package/bootstrap/bootstrap.sh +25 -18
- package/bootstrap/doctor.ts +46 -1
- package/bootstrap/fleet-manager-run.sh +42 -15
- package/bootstrap/fleet-remote-bootstrap.sh +85 -12
- package/bootstrap/global-config.ts +64 -6
- package/bootstrap/install-launcher.sh +3 -0
- package/bootstrap/npm.ts +10 -2
- package/bootstrap/release-version.ts +157 -0
- package/docs/consumer-setup.md +408 -0
- package/docs/declared.md +89 -0
- package/docs/machine-setup.md +399 -0
- package/docs/operations.md +276 -0
- package/docs/releasing.md +103 -0
- package/docs/state.md +254 -0
- package/docs/topology.md +67 -0
- package/docs/ubuntu-sync.md +351 -0
- package/docs/worker-contract.md +67 -0
- package/examples/fleet.json +5 -0
- package/llms.txt +35 -0
- package/mise.lock +29 -0
- package/mise.toml +12 -1
- package/package.json +11 -2
- package/schema/fleet.schema.json +71 -15
- package/src/agents/fleet-verify.ts +9 -0
- package/src/agents/native-verify.ts +167 -22
- package/src/agents/provider-errors.ts +9 -2
- package/src/agents/registry.ts +7 -1
- package/src/cli/agent-guide.ts +39 -5
- package/src/cli/app.ts +11 -4
- package/src/cli/cli.ts +7 -0
- package/src/cli/command-index.ts +7 -0
- package/src/cli/fleet-state.ts +499 -0
- package/src/cli/fleet-sync-checkout.ts +56 -17
- package/src/cli/fleet-sync-enrollment.ts +19 -23
- package/src/cli/fleet-sync-forward.ts +1 -1
- package/src/cli/fleet-sync-manager.ts +64 -8
- package/src/cli/fleet-sync-monitoring.ts +5 -5
- package/src/cli/fleet-sync-output.ts +4 -1
- package/src/cli/fleet-sync-remote.ts +11 -5
- package/src/cli/fleet-sync-state.ts +86 -0
- package/src/cli/fleet-sync.ts +123 -57
- package/src/cli/fleet.ts +4 -2
- package/src/cli/managed-health.ts +4 -4
- package/src/cli/node-sync.ts +7 -0
- package/src/cli/program.ts +20 -4
- package/src/cli/project.ts +51 -0
- package/src/cli/register-fleet.ts +51 -1
- package/src/cli/registry.ts +28 -1
- package/src/cli/roster.ts +46 -30
- package/src/cli/settings.ts +15 -12
- package/src/cli/source-operations.ts +27 -3
- package/src/cli/tailnet.ts +2 -2
- package/src/definition.ts +31 -1
- package/src/diagnostics.ts +1 -1
- package/src/fleet-config.ts +105 -19
- package/src/machine/source.ts +3 -3
- package/src/machine/state.ts +15 -27
- package/src/manager-sync.ts +8 -3
- package/src/monitoring/agent-evidence.ts +146 -0
- package/src/monitoring/apply.ts +15 -3
- package/src/monitoring/beszel.ts +11 -4
- package/src/monitoring/enroll.ts +2 -1
- package/src/monitoring/hub-access.ts +4 -3
- package/src/monitoring/hub-backup.ts +121 -0
- package/src/monitoring/hub-viewer.ts +8 -8
- package/src/monitoring/hub.ts +3 -3
- package/src/monitoring/manager-hub.ts +30 -14
- package/src/node-converge-linux.ts +2 -0
- package/src/package-info.ts +45 -0
- package/src/platform/ansible.ts +19 -15
- package/src/platform/resource-verify.ts +8 -4
- package/src/platform/ubuntu-audit.ts +5 -2
- package/src/remote-bootstrap.ts +17 -19
- package/src/repair-catalog.ts +1 -1
- package/src/runner.ts +1 -1
- package/src/state/bucket.ts +208 -0
- package/src/state/check.ts +74 -0
- package/src/state/connection.ts +92 -0
- package/src/state/enrollment.ts +45 -0
- package/src/state/legacy.ts +89 -0
- package/src/state/litestream.ts +143 -0
- package/src/state/operator.ts +20 -0
- package/src/state/paths.ts +40 -0
- package/src/state/roster.ts +62 -0
- package/src/state/store.ts +169 -0
- package/src/state/sync.ts +352 -0
- package/src/t3-endpoint.ts +64 -8
- package/src/t3-linked-check.ts +23 -1
- package/src/toolchain-checks.ts +25 -0
- package/src/types.ts +4 -0
- package/src/worker-access-checks.ts +56 -3
- package/src/worker-host-checks.ts +5 -0
- package/src/workstation-checks.ts +1 -1
- package/src/index.ts +0 -6
- package/src/test-fixtures.ts +0 -36
|
@@ -16,13 +16,16 @@
|
|
|
16
16
|
"git": "1:2.53.0-1ubuntu1.1",
|
|
17
17
|
"python3": "3.14.3-0ubuntu2",
|
|
18
18
|
"unzip": "6.0-29ubuntu1",
|
|
19
|
-
"xz-utils": "5.8.3-1ubuntu0.1"
|
|
19
|
+
"xz-utils": "5.8.3-1ubuntu0.1",
|
|
20
|
+
"ansible-core": "2.20.1-1"
|
|
21
|
+
},
|
|
22
|
+
"tailscale": {
|
|
23
|
+
"version": "1.104.5",
|
|
24
|
+
"keySha256": "3e03dacf222698c60b8e2f990b809ca1b3e104de127767864284e6c228f1fb39"
|
|
20
25
|
},
|
|
21
26
|
"aptLockTimeoutSeconds": 120,
|
|
22
27
|
"minimumFreeDiskMiB": 4096,
|
|
23
28
|
"minimumFreeInodes": 10000,
|
|
24
|
-
"serviceStartLimitBurst": 5,
|
|
25
|
-
"serviceStartLimitIntervalSeconds": 300,
|
|
26
29
|
"alwaysOnServices": ["ssh", "tailscaled", "docker", "beszel-agent"],
|
|
27
30
|
"resourceSafety": {
|
|
28
31
|
"swapFileMiB": 8192,
|
|
@@ -37,6 +40,12 @@
|
|
|
37
40
|
"diskGuardFloorMiB": 3072,
|
|
38
41
|
"diskGuardWriteMiB": 32,
|
|
39
42
|
"diskGuardIntervalSeconds": 5,
|
|
43
|
+
"diskGcIdleDays": 7,
|
|
44
|
+
"diskGcPressureMiB": 15360,
|
|
45
|
+
"diskGcPressureIdleHours": 12,
|
|
46
|
+
"diskGcDockerAgeHours": 168,
|
|
47
|
+
"diskGcPressureDockerAgeHours": 24,
|
|
48
|
+
"diskGcPressureCaches": [".bun/install/cache"],
|
|
40
49
|
"dockerLogMaxSize": "50m",
|
|
41
50
|
"dockerLogMaxFiles": "3"
|
|
42
51
|
}
|
|
@@ -4,18 +4,21 @@
|
|
|
4
4
|
connection: local
|
|
5
5
|
become: true
|
|
6
6
|
gather_facts: true
|
|
7
|
+
# The approved version and the signing key's digest: `tailscale` in policy.json.
|
|
8
|
+
vars_files:
|
|
9
|
+
- policy.json
|
|
7
10
|
tasks:
|
|
8
11
|
- name: Require supported Ubuntu
|
|
9
12
|
ansible.builtin.assert:
|
|
10
13
|
that:
|
|
11
14
|
- ansible_facts.distribution == 'Ubuntu'
|
|
12
|
-
- ansible_facts.distribution_version ==
|
|
15
|
+
- ansible_facts.distribution_version == release
|
|
13
16
|
- name: Inspect installed packages before possible network interruption
|
|
14
17
|
ansible.builtin.package_facts:
|
|
15
18
|
manager: apt
|
|
16
19
|
- name: Require maintenance for an installed version change
|
|
17
20
|
ansible.builtin.assert:
|
|
18
|
-
that: "'tailscale' not in ansible_facts.packages or ansible_facts.packages.tailscale[0].version ==
|
|
21
|
+
that: "'tailscale' not in ansible_facts.packages or ansible_facts.packages.tailscale[0].version == tailscale.version"
|
|
19
22
|
fail_msg: TAILSCALE_UPGRADE_PENDING; upgrading an active VPN can disconnect SSH. Review an explicit maintenance operation.
|
|
20
23
|
- name: Inspect existing package-source ownership before writing
|
|
21
24
|
ansible.builtin.find:
|
|
@@ -34,7 +37,7 @@
|
|
|
34
37
|
ansible.builtin.get_url:
|
|
35
38
|
url: https://pkgs.tailscale.com/stable/ubuntu/resolute.noarmor.gpg
|
|
36
39
|
dest: /usr/share/keyrings/tailscale-archive-keyring.gpg
|
|
37
|
-
checksum: sha256:
|
|
40
|
+
checksum: 'sha256:{{ tailscale.keySha256 }}'
|
|
38
41
|
owner: root
|
|
39
42
|
group: root
|
|
40
43
|
mode: '0644'
|
|
@@ -48,11 +51,11 @@
|
|
|
48
51
|
register: tailscale_source
|
|
49
52
|
- name: Install the approved version only when absent
|
|
50
53
|
ansible.builtin.apt:
|
|
51
|
-
name: tailscale=
|
|
54
|
+
name: 'tailscale={{ tailscale.version }}'
|
|
52
55
|
state: present
|
|
53
56
|
update_cache: true
|
|
54
57
|
cache_valid_time: 0
|
|
55
|
-
lock_timeout:
|
|
58
|
+
lock_timeout: '{{ aptLockTimeoutSeconds }}'
|
|
56
59
|
allow_downgrade: false
|
|
57
60
|
allow_unauthenticated: false
|
|
58
61
|
when: "'tailscale' not in ansible_facts.packages"
|
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
# Memory and disk safety: a runaway workload is stopped on its own before the
|
|
3
3
|
# machine, SSH, Tailscale or the T3 server run out of memory or disk. These
|
|
4
4
|
# tasks run before the capacity preflight because they matter most when a disk
|
|
5
|
-
# is nearly full; they only write small files and never delete user data.
|
|
5
|
+
# is nearly full; they only write small files and never delete user data. The
|
|
6
|
+
# disk GC timer they install deletes only build output and caches a build or
|
|
7
|
+
# install recreates (ansible/ubuntu/disk-gc.py).
|
|
6
8
|
- name: Inspect active swap
|
|
7
9
|
ansible.builtin.command:
|
|
8
10
|
argv: [swapon, --show=NAME, --noheadings]
|
|
@@ -250,3 +252,61 @@
|
|
|
250
252
|
enabled: true
|
|
251
253
|
state: '{{ "restarted" if disk_guard_unit.changed else "started" }}'
|
|
252
254
|
when: development_source is defined and disk_guard_source.stat.exists
|
|
255
|
+
|
|
256
|
+
- name: Read the tracked disk GC
|
|
257
|
+
ansible.builtin.stat:
|
|
258
|
+
path: '{{ development_source }}/ansible/ubuntu/disk-gc.py'
|
|
259
|
+
checksum_algorithm: sha256
|
|
260
|
+
register: disk_gc_source
|
|
261
|
+
when: development_source is defined
|
|
262
|
+
- name: Declare the disk GC service and its hourly timer
|
|
263
|
+
ansible.builtin.copy:
|
|
264
|
+
dest: '{{ item.dest }}'
|
|
265
|
+
owner: root
|
|
266
|
+
group: root
|
|
267
|
+
mode: '0644'
|
|
268
|
+
content: '{{ item.content }}'
|
|
269
|
+
loop:
|
|
270
|
+
- dest: /etc/systemd/system/personal-fleet-disk-gc.service
|
|
271
|
+
content: |
|
|
272
|
+
# Managed by personal fleet-sync: ansible/ubuntu/disk-gc.py
|
|
273
|
+
# Source sha256 {{ disk_gc_source.stat.checksum }}
|
|
274
|
+
[Unit]
|
|
275
|
+
Description=Personal Fleet disk GC (deletes build output and caches a build recreates)
|
|
276
|
+
After=docker.service
|
|
277
|
+
[Service]
|
|
278
|
+
Type=oneshot
|
|
279
|
+
ExecStart=/usr/bin/python3 -I -B {{ disk_gc_source.stat.path }} --home {{ development_home }} --path / --path {{ development_home }} --idle-days {{ resourceSafety.diskGcIdleDays }} --pressure-mib {{ resourceSafety.diskGcPressureMiB }} --pressure-idle-hours {{ resourceSafety.diskGcPressureIdleHours }} --docker-age-hours {{ resourceSafety.diskGcDockerAgeHours }} --pressure-docker-age-hours {{ resourceSafety.diskGcPressureDockerAgeHours }}{% for cache in resourceSafety.diskGcPressureCaches %} --pressure-cache {{ cache }}{% endfor %}
|
|
280
|
+
|
|
281
|
+
TimeoutStartSec=2h
|
|
282
|
+
Nice=19
|
|
283
|
+
IOSchedulingClass=idle
|
|
284
|
+
CPUQuota=50%
|
|
285
|
+
MemoryMax=512M
|
|
286
|
+
NoNewPrivileges=true
|
|
287
|
+
PrivateTmp=true
|
|
288
|
+
LogRateLimitIntervalSec=60
|
|
289
|
+
LogRateLimitBurst=200
|
|
290
|
+
- dest: /etc/systemd/system/personal-fleet-disk-gc.timer
|
|
291
|
+
content: |
|
|
292
|
+
# Managed by personal fleet-sync: ansible/ubuntu/disk-gc.py
|
|
293
|
+
[Unit]
|
|
294
|
+
Description=Run the Personal Fleet disk GC hourly
|
|
295
|
+
[Timer]
|
|
296
|
+
OnBootSec=10min
|
|
297
|
+
OnCalendar=hourly
|
|
298
|
+
RandomizedDelaySec=5min
|
|
299
|
+
Persistent=true
|
|
300
|
+
[Install]
|
|
301
|
+
WantedBy=timers.target
|
|
302
|
+
loop_control:
|
|
303
|
+
label: '{{ item.dest }}'
|
|
304
|
+
when: development_source is defined and disk_gc_source.stat.exists
|
|
305
|
+
register: disk_gc_units
|
|
306
|
+
- name: Schedule the disk GC
|
|
307
|
+
ansible.builtin.systemd_service:
|
|
308
|
+
name: personal-fleet-disk-gc.timer
|
|
309
|
+
daemon_reload: '{{ disk_gc_units.changed }}'
|
|
310
|
+
enabled: true
|
|
311
|
+
state: started
|
|
312
|
+
when: development_source is defined and disk_gc_source.stat.exists
|
package/ansible/uv.lock
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 5
|
|
3
|
+
requires-python = "==3.13.16"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "ansible-core"
|
|
7
|
+
version = "2.19.9"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
dependencies = [
|
|
10
|
+
{ name = "cryptography" },
|
|
11
|
+
{ name = "jinja2" },
|
|
12
|
+
{ name = "packaging" },
|
|
13
|
+
{ name = "pyyaml" },
|
|
14
|
+
{ name = "resolvelib" },
|
|
15
|
+
]
|
|
16
|
+
sdist = { url = "https://files.pythonhosted.org/packages/26/5b/161275ff5fa673dfc1329ed19a44331a4f491166a9f0cb907b44037ad72e/ansible_core-2.19.9.tar.gz", hash = "sha256:74107de13d188ff579fb215bc3eb875c9198803215d6378ed588c7f35aba12f5", size = 3431475, upload-time = "2026-04-21T00:47:09.194Z" }
|
|
17
|
+
wheels = [
|
|
18
|
+
{ url = "https://files.pythonhosted.org/packages/3d/b9/f2c07e6cdba6a5882342d666ceea4eeeb6fea20ec325fac68c27bfcea722/ansible_core-2.19.9-py3-none-any.whl", hash = "sha256:18de80e3ea5a89d2ea84e4d4a3c6d7c121ea62fc3af2877ba083784e3d90b419", size = 2416269, upload-time = "2026-04-21T00:47:06.777Z" },
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[[package]]
|
|
22
|
+
name = "cffi"
|
|
23
|
+
version = "2.1.1"
|
|
24
|
+
source = { registry = "https://pypi.org/simple" }
|
|
25
|
+
dependencies = [
|
|
26
|
+
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
|
27
|
+
]
|
|
28
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9e/ef/008a1939e372c06329a3fce4279c02f328488f3526744906eeec3da7ad5f/cffi-2.1.1.tar.gz", hash = "sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be", size = 530807, upload-time = "2026-08-03T21:21:18.939Z" }
|
|
29
|
+
wheels = [
|
|
30
|
+
{ url = "https://files.pythonhosted.org/packages/9d/f4/035513d4117049066b4779dc3b7c0c0fdad175fa13731c9f4003f1cd1478/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e", size = 194248, upload-time = "2026-08-03T21:19:59.399Z" },
|
|
31
|
+
{ url = "https://files.pythonhosted.org/packages/76/af/2aeb4dbb5fc41a04161ae9ff1518de7cec08e164f44a8ce6a4cf7fd2cd1d/cffi-2.1.1-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c", size = 196908, upload-time = "2026-08-03T21:20:00.746Z" },
|
|
32
|
+
{ url = "https://files.pythonhosted.org/packages/a7/46/2e5fdde8555706dd98139a910ca11be02809f3f605ce956f655d0214e100/cffi-2.1.1-cp313-cp313-macosx_10_15_x86_64.whl", hash = "sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6", size = 184805, upload-time = "2026-08-03T21:20:02.02Z" },
|
|
33
|
+
{ url = "https://files.pythonhosted.org/packages/55/41/4c7042f317b9217502988f0873af87e16ad606dc20f84e546e3e6ce9764c/cffi-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971", size = 184764, upload-time = "2026-08-03T21:20:03.141Z" },
|
|
34
|
+
{ url = "https://files.pythonhosted.org/packages/43/1f/1c3d90d91811c8f86ced9ed637956c54bfe5b79ca98fe976d7f8c8979f6b/cffi-2.1.1-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c", size = 214722, upload-time = "2026-08-03T21:20:04.377Z" },
|
|
35
|
+
{ url = "https://files.pythonhosted.org/packages/37/6f/3b5ce4c3b2192d250f04908f2bfd91ef34552ec8f7716a5d4abdb8d67bb2/cffi-2.1.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125", size = 222369, upload-time = "2026-08-03T21:20:05.544Z" },
|
|
36
|
+
{ url = "https://files.pythonhosted.org/packages/02/10/4b3c75dde3d9663c9e02ba05c2668b954f671d4bbe346413ca8c696b295a/cffi-2.1.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264", size = 210175, upload-time = "2026-08-03T21:20:06.75Z" },
|
|
37
|
+
{ url = "https://files.pythonhosted.org/packages/df/62/14f74b9543e605d17701dc797b815958b8bb70b7624ce1b832ddad48ed6c/cffi-2.1.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3", size = 208670, upload-time = "2026-08-03T21:20:08.04Z" },
|
|
38
|
+
{ url = "https://files.pythonhosted.org/packages/95/95/86342356ff5953b3fb06f7ef7c5bee212d45e770abc7218d451b9148313c/cffi-2.1.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2", size = 221824, upload-time = "2026-08-03T21:20:09.274Z" },
|
|
39
|
+
{ url = "https://files.pythonhosted.org/packages/eb/ff/7b3429ff53aafe931ed8a5fc69f481bbef7ba6de87ddcbb63d08f483f613/cffi-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b", size = 225148, upload-time = "2026-08-03T21:20:10.7Z" },
|
|
40
|
+
{ url = "https://files.pythonhosted.org/packages/34/34/a95870b9221e09cf4f2ce3178b1a210abdfe63a1bd357da940418d7b8d15/cffi-2.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7", size = 223564, upload-time = "2026-08-03T21:20:12.165Z" },
|
|
41
|
+
{ url = "https://files.pythonhosted.org/packages/70/ea/839b50531021a647fb5e929f72cf97bc1ff702b5472166164b5b6e76b851/cffi-2.1.1-cp313-cp313-win32.whl", hash = "sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac", size = 175263, upload-time = "2026-08-03T21:20:13.559Z" },
|
|
42
|
+
{ url = "https://files.pythonhosted.org/packages/60/a6/8b149b2c3f2e11aaa1618ef64500b45f50f22c57a977a4dff1aff1f91042/cffi-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d", size = 185688, upload-time = "2026-08-03T21:20:14.69Z" },
|
|
43
|
+
{ url = "https://files.pythonhosted.org/packages/01/9a/11f687cb39d6a3504060d5242f04f48c735afb4d3d533958a20594890cb2/cffi-2.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973", size = 180078, upload-time = "2026-08-03T21:20:15.917Z" },
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[[package]]
|
|
47
|
+
name = "cryptography"
|
|
48
|
+
version = "50.0.2"
|
|
49
|
+
source = { registry = "https://pypi.org/simple" }
|
|
50
|
+
dependencies = [
|
|
51
|
+
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
|
52
|
+
]
|
|
53
|
+
sdist = { url = "https://files.pythonhosted.org/packages/9d/af/182eb91b0df3fe75c4d9f26fe70684569566745f6ba7e5c9c73a862c5252/cryptography-50.0.2.tar.gz", hash = "sha256:7b46165bb56eb4704e2eaaf86f3c940d19154535d9b0ca7d6d590b04060e00d5", size = 880623, upload-time = "2026-09-30T15:30:04.884Z" }
|
|
54
|
+
wheels = [
|
|
55
|
+
{ url = "https://files.pythonhosted.org/packages/e5/56/d194340cc4a57535e82e1bee9e89667ac4b7c13b5d3f59686deae3094dd5/cryptography-50.0.2-cp311-abi3-macosx_11_0_arm64.whl", hash = "sha256:fa8f5efb344d6908a1ce62f4a24e2e5780f825d6f53f5f50ec5ffacac72936cb", size = 3914904, upload-time = "2026-09-30T14:43:44.339Z" },
|
|
56
|
+
{ url = "https://files.pythonhosted.org/packages/d9/69/c9bd862c3bf43d6399c433caf002df16e2dffd4be49bdf515cda38038711/cryptography-50.0.2-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:79def8d059362e7831389ed3be0ecdf58a89386e1271e35dd9f5af84e81bffd0", size = 4731146, upload-time = "2026-09-30T14:43:47.113Z" },
|
|
57
|
+
{ url = "https://files.pythonhosted.org/packages/21/69/64cef1f702bf6657e0cc186ed1a2891d50d29fb41586b254e1c07adea261/cryptography-50.0.2-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:630ebfea3bf689d075f82316324ff7433dc447fe6bc1bfc76524b74b4a9567d2", size = 4719841, upload-time = "2026-09-30T14:43:49.01Z" },
|
|
58
|
+
{ url = "https://files.pythonhosted.org/packages/38/6b/61a3f8d8c5e1e49a6cddccafc4015cc1c0021360ab0acb4080e7a423644a/cryptography-50.0.2-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f9f6143a8c75945eb960d9eb98905a441394abfa24afaae239d514ffb2586480", size = 4738340, upload-time = "2026-09-30T14:43:50.932Z" },
|
|
59
|
+
{ url = "https://files.pythonhosted.org/packages/7b/2e/7212ca32fd43dc91f2f41db20160b268098874b4c9a0e7be94d6835f5b2e/cryptography-50.0.2-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:a582ab2ae1d34f67112cadc86702774c9ea4374df6bca6afe672817203c99134", size = 5367029, upload-time = "2026-09-30T14:43:52.911Z" },
|
|
60
|
+
{ url = "https://files.pythonhosted.org/packages/1a/f1/b474e930c4d910328780e3940da76f5aa5cbc48ce1fc14e44d239d9ea9db/cryptography-50.0.2-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4061c0079120205fb760c58acab6443e217307dcf05e3702cf970e0689972856", size = 4753050, upload-time = "2026-09-30T14:43:55.272Z" },
|
|
61
|
+
{ url = "https://files.pythonhosted.org/packages/7c/52/9af10e80ac16b0fcc2123f9cbd5e7afbd0fd5075bb7a607c592258a39cda/cryptography-50.0.2-cp311-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:ac9ed99d81760c62fe89d5f0815cdfa1ba9a35141cf30f1c2d044f04b4803d2e", size = 4376724, upload-time = "2026-09-30T14:43:57.24Z" },
|
|
62
|
+
{ url = "https://files.pythonhosted.org/packages/71/37/6202e488cc1eb625ea110c292c6bda92823176e023f427d8d5660ce8d632/cryptography-50.0.2-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:87e9ce85beb6b328ba370cc6e6aea483c92617b4c95b1d33a49297eb662bfb04", size = 4737859, upload-time = "2026-09-30T14:43:59.541Z" },
|
|
63
|
+
{ url = "https://files.pythonhosted.org/packages/8f/30/e86d7d518489b0ae2497091a35287abcb1a2ce4037837a34afbe9b1d6964/cryptography-50.0.2-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:f265528741e048bce55c3463ed721fb0aa45a5888d8add8cfeccb3035451bbdc", size = 5324103, upload-time = "2026-09-30T14:44:01.901Z" },
|
|
64
|
+
{ url = "https://files.pythonhosted.org/packages/d3/69/2c833a049475e0a3444e94c7d0aca0aa51d166374a449b09e92ac98138de/cryptography-50.0.2-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9dab55f57c74c3cad24c323bacbbd04be4705ba6eb0d92e920b1fc4837ed5079", size = 4752576, upload-time = "2026-09-30T14:44:04.545Z" },
|
|
65
|
+
{ url = "https://files.pythonhosted.org/packages/6c/5d/906970b83bbfc1f5bbfb677a143c181f2801f23b6a7204a3b47c42c97e65/cryptography-50.0.2-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25784ce8b9621c90c643efb9e1e2162ab3b0224cae446ad5e70e7fcb1ce18b51", size = 4870819, upload-time = "2026-09-30T14:44:06.884Z" },
|
|
66
|
+
{ url = "https://files.pythonhosted.org/packages/68/e3/f2298d3bb55e0c4a91841ec4d01b3f020ba8c5fbf15ccdcc6dcf03f97025/cryptography-50.0.2-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:85d0d9a31b9098e98534226d5686b47264b95e62ce459dc2e62fdfc809f9fe93", size = 5030152, upload-time = "2026-09-30T14:44:09.443Z" },
|
|
67
|
+
{ url = "https://files.pythonhosted.org/packages/9a/4f/adfc442765721292fff86d314ce385d3249d22db42295c0dd057727b60f3/cryptography-50.0.2-cp311-abi3-win_amd64.whl", hash = "sha256:7afa5a6602a9f29af1f3a2965f831bae7c9d5d597b7cbb716d41ab3b7d89879c", size = 3824692, upload-time = "2026-09-30T14:44:11.671Z" },
|
|
68
|
+
{ url = "https://files.pythonhosted.org/packages/2d/49/93f6a6e7a87c9aa68d44d3e1cdb5fe8f60c90d5d2f46acae9a56892816b8/cryptography-50.0.2-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:edc3342adf8f697fc5f59c887a304356f147b397809440ed64e2fa6af2f50f37", size = 4133708, upload-time = "2026-09-30T14:44:41.807Z" },
|
|
69
|
+
{ url = "https://files.pythonhosted.org/packages/8c/75/32ac2a56243d778805c16ca6a32b8f74fb757df7e28d7ecb560afafb59cf/cryptography-50.0.2-cp315-abi3.abi3t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d370b8d1dfcdf7130178137f6fbee6140774a1acc6cacefc4b42643ec11d0a3a", size = 4956267, upload-time = "2026-09-30T14:44:43.693Z" },
|
|
70
|
+
{ url = "https://files.pythonhosted.org/packages/aa/a4/2c8d734e43d97f0842ee9f1b7b4bfb3d0cf5e19edebf43c2afe6675c2320/cryptography-50.0.2-cp315-abi3.abi3t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f2f9bd7f90c64fe89253f0a2c05e3c4856072660429ce8831b4235bf29403a67", size = 4966465, upload-time = "2026-09-30T14:44:45.769Z" },
|
|
71
|
+
{ url = "https://files.pythonhosted.org/packages/c2/58/ee288c829a6f41f6235ae9dd33d82fd19b45442b65b4c8a3da36963d9f7a/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_aarch64.whl", hash = "sha256:e275096ea1e60cc595cda2836fd4a6c725d1125108b868be17f53684d164e2cc", size = 4959356, upload-time = "2026-09-30T14:44:48.211Z" },
|
|
72
|
+
{ url = "https://files.pythonhosted.org/packages/92/20/9ded6d51ddd9897f6b6e81fb9ebea7951d7cc5d6c890b0ed8abf77a51a80/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_ppc64le.whl", hash = "sha256:b13478603dcd0a2479ff8e87e2c19a7d525734686fe3c49542472293a204212d", size = 5548822, upload-time = "2026-09-30T14:44:50.86Z" },
|
|
73
|
+
{ url = "https://files.pythonhosted.org/packages/02/a8/8df951850d6b31d2a00218f19e2b3f999523437ed7a819df7fa427942fca/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_28_x86_64.whl", hash = "sha256:58a0c478eeca76fe5e07993c5a0703def34a6dc6a0cda4f5564639b33112ffe7", size = 5001199, upload-time = "2026-09-30T14:44:53.379Z" },
|
|
74
|
+
{ url = "https://files.pythonhosted.org/packages/8b/f9/36b3022218ce75b7cdf068fb95f809f9bd0d820e4955ef43b90c255cc7ac/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_31_armv7l.whl", hash = "sha256:d38cdff612d06fa6a32840d5e1b1f7a27cee4a349aa9085d94a67789d6bfd408", size = 4629333, upload-time = "2026-09-30T14:44:55.635Z" },
|
|
75
|
+
{ url = "https://files.pythonhosted.org/packages/8c/72/20f99a219f6af47cdd1cbd978c243b92d71496e168a746138af44ded4f29/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_aarch64.whl", hash = "sha256:fdd28f912fccfec1846a94e2e1e8f9b0012f557f0c46fe4f3eb0d7a87afcf90b", size = 4958822, upload-time = "2026-09-30T14:44:59.639Z" },
|
|
76
|
+
{ url = "https://files.pythonhosted.org/packages/f2/20/196f112617fb08eb4d608a2a6c422373d46f9cc2857f38fc0667033c0899/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_ppc64le.whl", hash = "sha256:cbc8738fd8526d80f35cb3a40d41f41a2e7030bb3b18b09a6778ef63d291c2fd", size = 5506351, upload-time = "2026-09-30T14:45:02.267Z" },
|
|
77
|
+
{ url = "https://files.pythonhosted.org/packages/24/95/83378121ef3eaaaf71d4b781577ff794acb39b9e1b87a3f156898c8497ed/cryptography-50.0.2-cp315-abi3.abi3t-manylinux_2_34_x86_64.whl", hash = "sha256:e105ab60406787da31fccc883fc0f733af1efd78f0136a4599692c4083a73d0c", size = 5000859, upload-time = "2026-09-30T14:45:05.009Z" },
|
|
78
|
+
{ url = "https://files.pythonhosted.org/packages/22/f7/70fd7ae4d1dbfa7ba29b02e1b9068771519a86027756510b700ce81086a8/cryptography-50.0.2-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6f8700550aa1474a91e5dc07049c46f98b423b5b1ddd0483e0b51362eeeaf5be", size = 5092151, upload-time = "2026-09-30T15:29:15.932Z" },
|
|
79
|
+
{ url = "https://files.pythonhosted.org/packages/d4/be/688367b74de86984bd58d8efacfc7c9e68b89a6a22ced0fb4f38db50254a/cryptography-50.0.2-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:c71be1cbfa5cd9a41ee452acf1eccd82b2c05950358b106ec8ceb83411d1a020", size = 5286120, upload-time = "2026-09-30T15:29:18.309Z" },
|
|
80
|
+
{ url = "https://files.pythonhosted.org/packages/39/d1/55f8a3f2ef5d1529e16835ef10cf0fe3d559ce237b46dddc440c0bba3649/cryptography-50.0.2-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:c423ab384a46c4dff7217b2ea5ba2e11cffdeab6441acd04cf65a369caf0366c", size = 4111557, upload-time = "2026-09-30T15:29:20.155Z" },
|
|
81
|
+
{ url = "https://files.pythonhosted.org/packages/23/ad/ac987755d00e1e64273760228d2635ae38dae2be83e3c6e0d3289d91dec3/cryptography-50.0.2-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:0ec5f09541743261e66e291b4a0cbf0fb2997aeaab6d9e9c740b9dba1b58d1c2", size = 3943588, upload-time = "2026-09-30T15:29:22.265Z" },
|
|
82
|
+
{ url = "https://files.pythonhosted.org/packages/d5/8d/6d585339bedf85d45044c85d8412dac53f2bb6f918e8b7777efba1787844/cryptography-50.0.2-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c5e67125c7dca78d199ec4e116aa93dbb83494808ecbb8211a2cb09b1bf41dbd", size = 4756166, upload-time = "2026-09-30T15:29:24.58Z" },
|
|
83
|
+
{ url = "https://files.pythonhosted.org/packages/bf/f1/1c1f6874e8550cfddd4b688ceb38cefb6ed15ceed224d56f133f3d88c214/cryptography-50.0.2-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee247f5c245c9a2fe7c8e2214e295918838e44e00a45a6718451e4004219e767", size = 4749145, upload-time = "2026-09-30T15:29:26.807Z" },
|
|
84
|
+
{ url = "https://files.pythonhosted.org/packages/c1/63/61b15dc1a8de03fe0adbe3fd7608b3ad5c73bf50993bbcb1faaa930afe33/cryptography-50.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dfe9763530994147d9af1def057a5b9658b00e8f8fe8743d144d1e0911c2e454", size = 4763638, upload-time = "2026-09-30T15:29:28.588Z" },
|
|
85
|
+
{ url = "https://files.pythonhosted.org/packages/fc/35/b345bdfa40c9126df1a9d33236aa98418367931b8725f84fc3ae2b98dc59/cryptography-50.0.2-cp39-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:58ddb5a8e3179d12f19e4ea34d2d32e9d63a4baa142c875c1eb59f41b7243acd", size = 5382217, upload-time = "2026-09-30T15:29:30.589Z" },
|
|
86
|
+
{ url = "https://files.pythonhosted.org/packages/4f/87/ef344a9e616871f2519c22d6afcda79ddd5d35e9592d95eb6e677608d055/cryptography-50.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f21e8a22c8605750c7af886bab299a363721264061b4ac0a30efb73cfd58efc5", size = 4781387, upload-time = "2026-09-30T15:29:32.605Z" },
|
|
87
|
+
{ url = "https://files.pythonhosted.org/packages/90/5b/f2fdb13cd0b96f6f932c8627bb292a45f11c64d21620a8e120aee9a3b848/cryptography-50.0.2-cp39-abi3-manylinux_2_31_armv7l.whl", hash = "sha256:9c8402a82ea0dc4ceeab793db05f0fafa8ca139ca34fcde5df0f596103c74107", size = 4403790, upload-time = "2026-09-30T15:29:34.374Z" },
|
|
88
|
+
{ url = "https://files.pythonhosted.org/packages/bc/ce/7e4f662b1e3c393513569e402cfc85ac7da0bd3d5435e122a3140219eb2d/cryptography-50.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:0ddc924c04591c2811ca024d62ecad4f7f6f08af8939c211438f48a16bd23602", size = 4764319, upload-time = "2026-09-30T15:29:36.149Z" },
|
|
89
|
+
{ url = "https://files.pythonhosted.org/packages/3c/3f/86ff33ce34cc0de6847fb96e035a1a760d81652e38643f617c02ad32ef7a/cryptography-50.0.2-cp39-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:a6557e5f38e065ca9fbdaf7cfc7435ecb1d113aa81a022d1b51921ee7432e227", size = 5338560, upload-time = "2026-09-30T15:29:39.053Z" },
|
|
90
|
+
{ url = "https://files.pythonhosted.org/packages/40/cf/6b5c8e2fd9202d98988ab7cb5cc5c991704c4ad55f492ff408e4969f83f1/cryptography-50.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:1981f1db4630889b9ef7803fadef12b056f428cb6b85c27ba57b774793b6093c", size = 4780973, upload-time = "2026-09-30T15:29:41.251Z" },
|
|
91
|
+
{ url = "https://files.pythonhosted.org/packages/10/bf/8d6ebc7dded797bd0f0160d52188021211f011a2b164ef0ae1dac4587465/cryptography-50.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:7a8701d6b584d76e909e3d305b7d126b41439876a5aaf76cddc67fc230eafa2e", size = 4897738, upload-time = "2026-09-30T15:29:43.106Z" },
|
|
92
|
+
{ url = "https://files.pythonhosted.org/packages/d4/aa/f3f6e0de7e6253b8baa8b2d8fb9d50924fa75cee3d4624bd4bc1208ee923/cryptography-50.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:ce47f66801c20ec6c6632453bb5960fe38939e9306970b48b3a5a26de7745d94", size = 5058280, upload-time = "2026-09-30T15:29:44.827Z" },
|
|
93
|
+
{ url = "https://files.pythonhosted.org/packages/f6/b6/a1faf3a27ae9405fb34b1713cc73b2d8a26b04d5c561578fa2e6ef3e5bb9/cryptography-50.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:4e81d95e5bafc2d6e34e4bed780e53e4d5b9a2f928573428aa4d35fbec1eb0de", size = 3854095, upload-time = "2026-09-30T15:29:46.782Z" },
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[[package]]
|
|
97
|
+
name = "dev-fleet-ansible"
|
|
98
|
+
version = "0"
|
|
99
|
+
source = { virtual = "." }
|
|
100
|
+
dependencies = [
|
|
101
|
+
{ name = "ansible-core" },
|
|
102
|
+
]
|
|
103
|
+
|
|
104
|
+
[package.metadata]
|
|
105
|
+
requires-dist = [{ name = "ansible-core", specifier = "==2.19.9" }]
|
|
106
|
+
|
|
107
|
+
[[package]]
|
|
108
|
+
name = "jinja2"
|
|
109
|
+
version = "3.1.6"
|
|
110
|
+
source = { registry = "https://pypi.org/simple" }
|
|
111
|
+
dependencies = [
|
|
112
|
+
{ name = "markupsafe" },
|
|
113
|
+
]
|
|
114
|
+
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
|
115
|
+
wheels = [
|
|
116
|
+
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
[[package]]
|
|
120
|
+
name = "markupsafe"
|
|
121
|
+
version = "3.0.4"
|
|
122
|
+
source = { registry = "https://pypi.org/simple" }
|
|
123
|
+
sdist = { url = "https://files.pythonhosted.org/packages/38/9b/e422a865e1d5d57d0e509b4e0bf1c1a70a7f6382c29a5aa428df994c8bc8/markupsafe-3.0.4.tar.gz", hash = "sha256:2e9ad7dd851bf45fab9f75cbff4cb493fee9979e8d8c7c9c3ee119022518edd6", size = 153777, upload-time = "2026-10-02T23:07:22.29Z" }
|
|
124
|
+
wheels = [
|
|
125
|
+
{ url = "https://files.pythonhosted.org/packages/6d/18/4bc5ba32499e87bb2b0ef5b3a9bb9c00a131fa961ddf0be548cb550f548b/markupsafe-3.0.4-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:de8b364c423ef0a4bad9069657d617f9a5d2b2062457a89b1fa16ee199c399c1", size = 12786, upload-time = "2026-10-02T23:05:08.709Z" },
|
|
126
|
+
{ url = "https://files.pythonhosted.org/packages/4e/6f/17f0c099bf25f3e31e63cc19244d9f6af861a9a4ab778c203997903cfdd0/markupsafe-3.0.4-cp313-cp313-android_24_x86_64.whl", hash = "sha256:34bdde374c5932765d7dc685c4a1d191a3207852d67e8e0a9eb6ea85156181f1", size = 12510, upload-time = "2026-10-02T23:05:09.93Z" },
|
|
127
|
+
{ url = "https://files.pythonhosted.org/packages/11/af/1a141081b905036ee904ec4bd945e1f70b4e1b32d33c4e59e8cf1d58b247/markupsafe-3.0.4-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:6bd9e1788e15bfcf6a9082de42e30387e7b85d211ab21e57a939bb8cfaaf8d96", size = 11583, upload-time = "2026-10-02T23:05:10.884Z" },
|
|
128
|
+
{ url = "https://files.pythonhosted.org/packages/e7/0a/a89385ae590232622a03e091805cff12f24fabe6c11e0e8bae096cece81c/markupsafe-3.0.4-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:5066b244f576f91afc8ee3ba029a89f99d39c79b1853fe9d39bea9f0afbec148", size = 11801, upload-time = "2026-10-02T23:05:11.913Z" },
|
|
129
|
+
{ url = "https://files.pythonhosted.org/packages/ed/85/ea548dc013962eb73653124bc595635fbf9e0fa41d1f181a967ccb784dfb/markupsafe-3.0.4-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:7a83aa6e4805df46fed18e989d3d16f86ef60cb50bbc8d9ce3a6be89165fbf6e", size = 11443, upload-time = "2026-10-02T23:05:12.887Z" },
|
|
130
|
+
{ url = "https://files.pythonhosted.org/packages/cc/72/15f2e5ec9cf2eb00d5cdfe968d94e4156a7bd7303832c3f3b2c403a36839/markupsafe-3.0.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:2d1b7d9308288661f56672b1b157d75fc536714d3638487bbea17b6318a78248", size = 11665, upload-time = "2026-10-02T23:05:13.829Z" },
|
|
131
|
+
{ url = "https://files.pythonhosted.org/packages/ca/e0/4030bea613677e333c8a2c901fd405055f657f9d06acba5b7357984b6ef7/markupsafe-3.0.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:73e77980c7207854f00fc4e71fb1626868d5740ab4012623d55c7a99ad122a72", size = 12061, upload-time = "2026-10-02T23:05:14.807Z" },
|
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/f3/a5/28b76a7449eb702966b88bef599e2360b411fbb3afeee8fe560939be06ec/markupsafe-3.0.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7018d4af1cd272e847aa5917983ab5e83e4f6579f9dbfecd4a79c0ca80b144c2", size = 24395, upload-time = "2026-10-02T23:05:15.909Z" },
|
|
133
|
+
{ url = "https://files.pythonhosted.org/packages/07/6c/21232811afc3a063b5e934b1ae2efda52f46154ec382f585149c020e61fe/markupsafe-3.0.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c90d5b3d4e944e065a301d741b3c1d784f6bd1f503aa68b4967e32b2ba313d85", size = 27183, upload-time = "2026-10-02T23:05:16.976Z" },
|
|
134
|
+
{ url = "https://files.pythonhosted.org/packages/14/38/6ccdfa5b59049cb36fb80cbc80aee9cf1fc9bb77d1335ad435f2070b08cf/markupsafe-3.0.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:18a801868a884f216e784d7d14db2a4077143ce7610440aee2ce8f734e7cfcde", size = 24772, upload-time = "2026-10-02T23:05:18.209Z" },
|
|
135
|
+
{ url = "https://files.pythonhosted.org/packages/63/e0/cec6865dfe88cb48fedd4b20aed6af5158e41092adcbf3e028bcc6ec2108/markupsafe-3.0.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:434139499bb20b502ed3baa1f169e618f924a97e7a777fea1a49446d80106cf6", size = 23017, upload-time = "2026-10-02T23:05:19.286Z" },
|
|
136
|
+
{ url = "https://files.pythonhosted.org/packages/ee/76/6ed4940bb7648a9aac457c14f870cfdd5105f139a0fb1f29cd61fafa47d1/markupsafe-3.0.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:9e227f3dbe6bde7491cf0a9965d00b88c6b1a4a95d11480ddf88bb96d397c19f", size = 22036, upload-time = "2026-10-02T23:05:20.352Z" },
|
|
137
|
+
{ url = "https://files.pythonhosted.org/packages/a1/4f/ed476226d4fe46a09090a36025bf319296810028df55eb12f1253b540f3a/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b8cd1f918b26fd7b1832ece557cc18f2d8747309ff8b3f0ef9d4250c5ad67a39", size = 23786, upload-time = "2026-10-02T23:05:21.576Z" },
|
|
138
|
+
{ url = "https://files.pythonhosted.org/packages/9a/35/66ff30450e35ef5fba9ebc930c9411747e537fd9447b65e44f5007e2b84d/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:a5fcffb37e602b0b3c1638a97746b9b96125caa9bcf6fa41d337a9261de231ee", size = 22672, upload-time = "2026-10-02T23:05:22.922Z" },
|
|
139
|
+
{ url = "https://files.pythonhosted.org/packages/32/0b/72f45ce4b4efcbca4b80cf1b06703eff0be8d37e82abb78f66c85a7ead1e/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:5989cb26b2e1efc6a42216a9f6b5ee495ce5ace2e5b352a9af489976b32d1ee2", size = 24107, upload-time = "2026-10-02T23:05:24.175Z" },
|
|
140
|
+
{ url = "https://files.pythonhosted.org/packages/d2/03/71776e5fdcba04614b384cc102e8a4198208579d896fd1394cb7cb9aa900/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:add96447a86d205ab616665d53b2950ee81083757f56e6ea833c8b2917646b46", size = 21615, upload-time = "2026-10-02T23:05:25.215Z" },
|
|
141
|
+
{ url = "https://files.pythonhosted.org/packages/ab/5f/801ce02a02e7aee0f784b1ec7843026178f6adeb9c93ac67eb1992a9a84d/markupsafe-3.0.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2628d3a8cb648ecebb3c5d6b0a1052d400e4d8b7ac0fb786be8d285b50040d17", size = 23076, upload-time = "2026-10-02T23:05:26.423Z" },
|
|
142
|
+
{ url = "https://files.pythonhosted.org/packages/4a/85/c43776625428f3bb4a61e8633940400e3efe6409e3c6f5bff26de5e45618/markupsafe-3.0.4-cp313-cp313-win32.whl", hash = "sha256:672d207103e6b16ca098611b0f9efad6bc00afd47c03d6ef62186495ca677dc0", size = 14118, upload-time = "2026-10-02T23:05:27.716Z" },
|
|
143
|
+
{ url = "https://files.pythonhosted.org/packages/6f/36/163da64de88a13db79214ef75fa041be7fa13bdb42261cf5b7484de14bfb/markupsafe-3.0.4-cp313-cp313-win_amd64.whl", hash = "sha256:1f1f9477e174582b0a1b583d60b66e1f2cf5d3fe12cee985e4aedf44766600e5", size = 14313, upload-time = "2026-10-02T23:05:28.749Z" },
|
|
144
|
+
{ url = "https://files.pythonhosted.org/packages/9f/a8/9b662783ffaa1149221432a923cee562f78b9cbbb8baa3df9b3753e63e1e/markupsafe-3.0.4-cp313-cp313-win_arm64.whl", hash = "sha256:06de8ef6331f6e822c28d577dc8bf43fe398800477c49498f38fc38b67ff33fc", size = 14189, upload-time = "2026-10-02T23:05:29.917Z" },
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
[[package]]
|
|
148
|
+
name = "packaging"
|
|
149
|
+
version = "26.3"
|
|
150
|
+
source = { registry = "https://pypi.org/simple" }
|
|
151
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" }
|
|
152
|
+
wheels = [
|
|
153
|
+
{ url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
[[package]]
|
|
157
|
+
name = "pycparser"
|
|
158
|
+
version = "3.12"
|
|
159
|
+
source = { registry = "https://pypi.org/simple" }
|
|
160
|
+
sdist = { url = "https://files.pythonhosted.org/packages/cb/27/eeb9f307bf07060f3d9f9aa0fb8c15b01bdfded0a941e4b2719c7f94cacd/pycparser-3.12.tar.gz", hash = "sha256:f03387877eab82ce01bbdfd0ba7252ee55a90b1c708d5129e2ce915475cf1db6", size = 158785, upload-time = "2026-10-22T13:40:03.56Z" }
|
|
161
|
+
wheels = [
|
|
162
|
+
{ url = "https://files.pythonhosted.org/packages/b6/ae/315bbeee126a769cbde43cf4908acb4b40408d8bf8bbf334dd7368d8dadf/pycparser-3.12-py3-none-any.whl", hash = "sha256:a076f3f489b39b43ed13563a1dafe42447445bec2e294154ec5c57fcdda4c85e", size = 62600, upload-time = "2026-10-22T13:40:02.021Z" },
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
[[package]]
|
|
166
|
+
name = "pyyaml"
|
|
167
|
+
version = "6.0.3"
|
|
168
|
+
source = { registry = "https://pypi.org/simple" }
|
|
169
|
+
sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" }
|
|
170
|
+
wheels = [
|
|
171
|
+
{ url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" },
|
|
172
|
+
{ url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" },
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" },
|
|
174
|
+
{ url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" },
|
|
175
|
+
{ url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" },
|
|
176
|
+
{ url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" },
|
|
177
|
+
{ url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" },
|
|
178
|
+
{ url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" },
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" },
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" },
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
[[package]]
|
|
184
|
+
name = "resolvelib"
|
|
185
|
+
version = "1.2.1"
|
|
186
|
+
source = { registry = "https://pypi.org/simple" }
|
|
187
|
+
sdist = { url = "https://files.pythonhosted.org/packages/1d/14/4669927e06631070edb968c78fdb6ce8992e27c9ab2cde4b3993e22ac7af/resolvelib-1.2.1.tar.gz", hash = "sha256:7d08a2022f6e16ce405d60b68c390f054efcfd0477d4b9bd019cc941c28fad1c", size = 24575, upload-time = "2025-10-11T01:07:44.582Z" }
|
|
188
|
+
wheels = [
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/e2/23/c941a0d0353681ca138489983c4309e0f5095dfd902e1357004f2357ddf2/resolvelib-1.2.1-py3-none-any.whl", hash = "sha256:fb06b66c8da04172d9e72a21d7d06186d8919e32ae5ab5cdf5b9d920be805ac2", size = 18737, upload-time = "2025-10-11T01:07:43.081Z" },
|
|
190
|
+
]
|
package/bootstrap/bootstrap.sh
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
2
|
+
# Installs the pinned toolchain for the checkout this script is in. fleet-sync
|
|
3
|
+
# runs it on every machine from the checkout of the revision it applies;
|
|
4
|
+
# nobody clones dev-fleet to use it (see README.md).
|
|
3
5
|
set -euo pipefail
|
|
4
|
-
MISE_VERSION=2026.10.24
|
|
5
|
-
repo=https://github.com/crvouga/dev-fleet.git
|
|
6
6
|
os=$(uname -s)
|
|
7
7
|
case "$os" in
|
|
8
8
|
Darwin) platform=macos ;;
|
|
@@ -37,16 +37,20 @@ for tool in curl tar unzip; do
|
|
|
37
37
|
command -v "$tool" >/dev/null || { echo "Install $tool, then rerun." >&2; exit 1; }
|
|
38
38
|
done
|
|
39
39
|
script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
40
|
-
|
|
41
|
-
checkout
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if [[ ! -d "$checkout/.git" ]]; then git clone "$repo" "$checkout"; fi
|
|
45
|
-
[[ "$(git -C "$checkout" remote get-url origin)" == "$repo" ]] || {
|
|
46
|
-
echo "Unexpected checkout at $checkout; choose an empty WORKSPACE_DIR." >&2; exit 1;
|
|
47
|
-
}
|
|
48
|
-
fi
|
|
40
|
+
[[ -f "$script_dir/../mise.toml" ]] || {
|
|
41
|
+
echo 'Run this from a dev-fleet checkout. To use dev-fleet, run its CLI instead: fleet-sync installs the toolchain.' >&2; exit 1;
|
|
42
|
+
}
|
|
43
|
+
checkout=$(cd "$script_dir/.." && pwd)
|
|
49
44
|
cd "$checkout"
|
|
45
|
+
# mise is pinned where every other tool is: `min_version` in mise.toml is the
|
|
46
|
+
# version installed, and [vars] holds the digest of its release archive for
|
|
47
|
+
# each platform. mise cannot read them for us before it exists.
|
|
48
|
+
pin() { sed -n "s/^$1 = \"\\(.*\\)\"\$/\\1/p" "$checkout/mise.toml" | head -n 1; }
|
|
49
|
+
MISE_VERSION=$(pin min_version)
|
|
50
|
+
mise_sha256=$(pin "mise_${platform}_${arch}_sha256")
|
|
51
|
+
[[ -n "$MISE_VERSION" && -n "$mise_sha256" ]] || {
|
|
52
|
+
echo 'mise.toml does not pin mise for this platform.' >&2; exit 1;
|
|
53
|
+
}
|
|
50
54
|
# Reuse an observed matching managed executable. Repeated reconciliation must
|
|
51
55
|
# not download/reinstall mise solely because a previous run finished.
|
|
52
56
|
installed_mise=$("$HOME/.local/bin/mise" --version 2>/dev/null | awk '{print $1}') || installed_mise=''
|
|
@@ -55,12 +59,15 @@ temp=$(mktemp -d)
|
|
|
55
59
|
trap 'rm -rf "$temp"' EXIT
|
|
56
60
|
asset="mise-v${MISE_VERSION}-${platform}-${arch}.tar.gz"
|
|
57
61
|
# Alpine/musl is not part of the supported workstation baseline.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
curl -fsSL "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/$asset" -o "$temp/$asset"
|
|
63
|
+
if command -v sha256sum >/dev/null; then
|
|
64
|
+
actual=$(sha256sum "$temp/$asset" | cut -d' ' -f1)
|
|
65
|
+
else
|
|
66
|
+
actual=$(shasum -a 256 "$temp/$asset" | cut -d' ' -f1)
|
|
67
|
+
fi
|
|
68
|
+
[[ "$actual" == "$mise_sha256" ]] || {
|
|
69
|
+
echo 'The mise archive does not match the digest pinned in mise.toml.' >&2; exit 1;
|
|
70
|
+
}
|
|
64
71
|
tar -xzf "$temp/$asset" -C "$temp"
|
|
65
72
|
mkdir -p "$HOME/.local/bin"
|
|
66
73
|
install -m 0755 "$temp/mise/bin/mise" "$HOME/.local/bin/mise"
|
package/bootstrap/doctor.ts
CHANGED
|
@@ -4,7 +4,13 @@ import { spawnSync } from 'node:child_process';
|
|
|
4
4
|
import { readFileSync } from 'node:fs';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { homedir, tmpdir } from 'node:os';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
AGENT_WORKTREE_ROOTS,
|
|
9
|
+
globalConfigDir,
|
|
10
|
+
globalConfigStanding,
|
|
11
|
+
workspaceRoot,
|
|
12
|
+
type GlobalConfigStanding,
|
|
13
|
+
} from './global-config';
|
|
8
14
|
|
|
9
15
|
type Tool = string | { version: string; lazy?: boolean; os?: string[] };
|
|
10
16
|
type Config = {
|
|
@@ -151,6 +157,44 @@ export function worktreeTrustCheck(
|
|
|
151
157
|
};
|
|
152
158
|
}
|
|
153
159
|
|
|
160
|
+
const STANDING: Record<GlobalConfigStanding, string> = {
|
|
161
|
+
published: 'Published by dev-fleet from this revision.',
|
|
162
|
+
missing: 'There is no global mise configuration.',
|
|
163
|
+
replaced:
|
|
164
|
+
'Another project or tool replaced the global mise configuration dev-fleet publishes.',
|
|
165
|
+
changed:
|
|
166
|
+
'The global mise configuration is not the one this revision publishes.',
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/** On a fleet machine the global mise configuration belongs to dev-fleet.
|
|
170
|
+
* When anything else replaced it, its pins and the trusted agent worktree
|
|
171
|
+
* roots are gone until the next fleet-sync.
|
|
172
|
+
*/
|
|
173
|
+
export function globalConfigCheck(
|
|
174
|
+
dir?: string,
|
|
175
|
+
root: string = workspaceRoot
|
|
176
|
+
): Check {
|
|
177
|
+
let standing: GlobalConfigStanding;
|
|
178
|
+
try {
|
|
179
|
+
standing = globalConfigStanding(dir ?? globalConfigDir(), root);
|
|
180
|
+
} catch {
|
|
181
|
+
return {
|
|
182
|
+
id: 'global-mise-config',
|
|
183
|
+
status: 'fail',
|
|
184
|
+
detail:
|
|
185
|
+
'MISE_GLOBAL_CONFIG_FILE moves the global mise configuration away from the one dev-fleet publishes; unset it.',
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
id: 'global-mise-config',
|
|
190
|
+
status: standing === 'published' ? 'pass' : 'fail',
|
|
191
|
+
detail:
|
|
192
|
+
standing === 'published'
|
|
193
|
+
? STANDING[standing]
|
|
194
|
+
: `${STANDING[standing]} Run fleet-sync; projects pin their own tools in a project mise.toml and never publish a global one.`,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
154
198
|
export function checkMachine(requireDocker = false, worker = false): Check[] {
|
|
155
199
|
const config = Bun.TOML.parse(
|
|
156
200
|
readFileSync(join(workspaceRoot, 'mise.toml'), 'utf8')
|
|
@@ -164,6 +208,7 @@ export function checkMachine(requireDocker = false, worker = false): Check[] {
|
|
|
164
208
|
),
|
|
165
209
|
...dockerChecks(requireDocker),
|
|
166
210
|
worktreeTrustCheck(),
|
|
211
|
+
globalConfigCheck(),
|
|
167
212
|
{
|
|
168
213
|
id: 'github-auth',
|
|
169
214
|
status: auth.ok ? 'pass' : 'warn',
|
|
@@ -12,15 +12,29 @@ shift
|
|
|
12
12
|
case "$revision" in *[!a-f0-9]*|'') exit 2;; esac
|
|
13
13
|
[ "${#revision}" = 40 ] || exit 2
|
|
14
14
|
say() { printf 'fleet-sync (manager): %s\n' "$1" >&2; }
|
|
15
|
-
#
|
|
16
|
-
#
|
|
15
|
+
# A preview (--dry-run) changes nothing outside dev-fleet's own disposable
|
|
16
|
+
# caches: it never publishes the global mise configuration, never edits shell
|
|
17
|
+
# profiles and never prunes run checkouts. Only an apply does.
|
|
18
|
+
preview=false
|
|
19
|
+
for arg in "$@"; do [ "$arg" != --dry-run ] || preview=true; done
|
|
20
|
+
# mise is installed here by the toolchain step below; a login shell is not
|
|
21
|
+
# required to find it.
|
|
22
|
+
export PATH="$HOME/.local/bin:$PATH"
|
|
23
|
+
fleet="$HOME/.local/share/personal/fleet"
|
|
24
|
+
# The repository to take the revision from. Nobody keeps a clone of dev-fleet:
|
|
25
|
+
# fleet-sync names the one it prepared, and a hand-off (which names none) uses
|
|
26
|
+
# the manager's own copy of the source repository, or the checkout the devfleet
|
|
27
|
+
# launcher is linked into.
|
|
17
28
|
repo=${DEVFLEET_REPO:-}
|
|
29
|
+
if [ -z "$repo" ] && git -C "$fleet/manager/source" rev-parse --git-dir >/dev/null 2>&1; then
|
|
30
|
+
repo="$fleet/manager/source"
|
|
31
|
+
fi
|
|
18
32
|
if [ -z "$repo" ]; then
|
|
19
|
-
launcher=$(command -v devfleet) || { say '
|
|
33
|
+
launcher=$(command -v devfleet) || { say 'this manager has no copy of the source yet; run fleet-sync once on the manager itself, from the project that holds your fleet.json.'; exit 3; }
|
|
20
34
|
repo=$(dirname "$(readlink -f "$launcher")")
|
|
21
35
|
fi
|
|
22
|
-
repo=$(git -C "$repo" rev-parse --show-toplevel) || { say 'cannot
|
|
23
|
-
runs="$
|
|
36
|
+
repo=$(git -C "$repo" rev-parse --show-toplevel) || { say 'cannot read the source repository on the manager; run fleet-sync once on the manager itself to fetch it again.'; exit 3; }
|
|
37
|
+
runs="$fleet/manager-runs"
|
|
24
38
|
dir="$runs/$revision"
|
|
25
39
|
ready() {
|
|
26
40
|
[ "$(git -C "$dir" rev-parse HEAD 2>/dev/null)" = "$revision" ] &&
|
|
@@ -28,6 +42,7 @@ ready() {
|
|
|
28
42
|
}
|
|
29
43
|
if ! ready; then
|
|
30
44
|
git -C "$repo" cat-file -e "$revision^{commit}" 2>/dev/null || git -C "$repo" fetch --quiet origin || true
|
|
45
|
+
git -C "$repo" cat-file -e "$revision^{commit}" 2>/dev/null || git -C "$repo" fetch --quiet --no-tags origin "$revision" || true
|
|
31
46
|
git -C "$repo" cat-file -e "$revision^{commit}" 2>/dev/null || { say "revision $revision is neither on the manager nor on origin; push it first."; exit 4; }
|
|
32
47
|
mkdir -p "$runs"
|
|
33
48
|
chmod 700 "$runs"
|
|
@@ -54,9 +69,16 @@ failed() {
|
|
|
54
69
|
say "toolchain or dependency install failed in the run checkout; full log: $log"
|
|
55
70
|
exit 5
|
|
56
71
|
}
|
|
57
|
-
if [ "$
|
|
72
|
+
if [ "$preview" = true ]; then
|
|
73
|
+
# The revision's own locked Bun is enough to preview; mise keeps it beside
|
|
74
|
+
# its other versions without making it the global one.
|
|
75
|
+
command -v mise >/dev/null 2>&1 || { say 'this manager has no toolchain yet, so a preview cannot run; fleet-sync without --dry-run installs it.'; exit 6; }
|
|
76
|
+
mise install --locked bun >"$log" 2>&1 || failed
|
|
77
|
+
elif [ "$(cat "$stamp" 2>/dev/null)" != "$key" ] || [ -z "$(find "$stamp" -mmin -1440 2>/dev/null)" ]; then
|
|
58
78
|
rm -f -- "$stamp"
|
|
59
|
-
|
|
79
|
+
# The toolchain bootstrap installs the pinned mise first when the manager
|
|
80
|
+
# has none (or another version), so Git is all a new manager needs.
|
|
81
|
+
bash bootstrap/bootstrap.sh --tools-only >"$log" 2>&1 || failed
|
|
60
82
|
printf '%s' "$key" >"$stamp"
|
|
61
83
|
fi
|
|
62
84
|
if [ ! -d node_modules ]; then
|
|
@@ -64,13 +86,18 @@ if [ ! -d node_modules ]; then
|
|
|
64
86
|
fi
|
|
65
87
|
# Keep the three most recent run checkouts (names are commit SHAs) and the
|
|
66
88
|
# applied one: fleet/current points at it and T3's providers launch from there.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
89
|
+
# A preview leaves them for the next apply to prune.
|
|
90
|
+
if [ "$preview" = false ]; then
|
|
91
|
+
applied=$(basename "$(readlink "$(dirname "$runs")/current" 2>/dev/null || true)")
|
|
92
|
+
# shellcheck disable=SC2012
|
|
93
|
+
for old in $(ls -1td "$runs"/*/ | tail -n +4); do
|
|
94
|
+
[ "$(basename "$old")" != "$applied" ] || continue
|
|
95
|
+
# A checkout made from another repository (an earlier clone) is not this
|
|
96
|
+
# repository's worktree: remove the directory itself.
|
|
97
|
+
git -C "$repo" worktree remove --force "$old" 2>/dev/null || rm -rf -- "$old"
|
|
98
|
+
rm -f -- "${old%/}.setup.log"
|
|
99
|
+
done
|
|
100
|
+
git -C "$repo" worktree prune
|
|
101
|
+
fi
|
|
75
102
|
export PERSONAL_WORKSPACE="$dir" PERSONAL_FLEET_RUN_CHECKOUT="$revision"
|
|
76
103
|
exec mise exec --locked bun -- bun src/cli/cli.ts fleet-sync --revision "$revision" "$@"
|