diff --git a/.github/release-notes/v0.1.0.md b/.github/release-notes/v0.1.0.md new file mode 100644 index 0000000..7552f79 --- /dev/null +++ b/.github/release-notes/v0.1.0.md @@ -0,0 +1,70 @@ +# Vectis 0.1.0 + +**The first release of Vectis: disposable GitHub Actions runners on your own Apple Silicon Mac. Each job runs in a fresh ARM64 virtual machine, with a just-in-time runner that Vectis removes together with the VM when the work is done. You control it from a native Mac app, a CLI or an MCP server, and you can control other Macs remotely.** + +## Highlights + +### One job, one disposable VM + +- Every job starts in a fresh VM cloned from a prepared environment. The runner accepts one job, then Vectis removes the VM and runner registration so later jobs start clean. +- Automatic runners are opt-in for each repository connection. Vectis watches for matching queued jobs and checks that work is still queued before allocating a VM. The default concurrency limit is five runners and can be configured from one to sixteen. Actual capacity depends on the CPU and memory assigned to environments; at most two macOS VMs run at once. +- You can also start a runner manually. Vectis reports runner operation status separately from the GitHub job result, so completed cleanup is not mistaken for a passing workflow. + +### Ubuntu, macOS and Windows environments + +- **Ubuntu 24.04 ARM64:** downloads and verifies a pinned Ubuntu image, then prepares Git, Docker, SSH and the official runner's required dependencies. +- **macOS 26 ARM64:** downloads and verifies Apple's restore image, installs it into a local guest bundle and guides you through guest setup and SSH verification. +- **Windows 11 ARM64:** installation is available as an experimental path using media you provide. + +Choose CPU, memory, virtual disk size, image directory and VM storage location for each environment. Setup operations are durable and can resume after interruptions. + +### Connect GitHub and schedule work + +Pair a Mac with your Vectis account through browser approval. Link and verify a GitHub account, install the Vectis GitHub App for the repository owner, then connect a repository to an environment. Each connection provides a `runs-on` label such as `vectis-ubuntu`. + +- Automatic scheduling starts disabled and can be enabled per connection. Vectis receives GitHub job events and can scan GitHub for missed queued or running jobs. +- If a successful run leaves its original job queued, Vectis makes a bounded number of additional attempts. Failed, cancelled or interrupted runs are not retried automatically. +- Connect and disconnect repository bindings, inspect recent GitHub job states and refresh missing or stale job records. +- Organization repository administrator access is verified before privileged operations. +- Outside contributors need maintainer approval before public-repository jobs are admitted. Fork approval and workflow review stay with GitHub maintainers. + +### Review ARM workflow migrations + +Preview one workflow file or analyze workflows in a connected repository. Vectis proposes supported ARM64 label changes and reports jobs that need human review. It does not assume x64 jobs will work on ARM64. + +After Vectis observes a successful job on the same repository binding and environment revision, it can open a regular pull request containing only changed workflow files. Review and merge it through GitHub as usual; Vectis never merges it. Dynamic expressions, complex matrices, reusable workflows and privileged event patterns may need manual review. + +### Control Vectis from the app, CLI or MCP + +The native Mac app, `vectis` CLI and `vectis-mcp` server use the same typed command contract. + +- The app manages environments, repositories, runner operations, activities, diagnostics and settings. Its background service continues working when the window closes. +- The CLI returns structured JSON, stable error codes and actionable next steps. +- MCP lets agents inspect capabilities, issue the same commands, read operation state and wait for results. +- The release also includes a Vectis agent skill and Claude Code plugin. + +### Control other Macs remotely + +Connect multiple Macs to one account and use the app, CLI or MCP to control an authorized host. Browser approval verifies each controller; access expires after 90 days and can be revoked. Hosts collect remote commands over an outbound connection, so they do not need an inbound port. Commands for an unavailable remote host do not fall back to running locally. + +### Safe recovery after interruptions + +The local service stores operations in SQLite and uses caller-provided keys to make command retries idempotent. Accepted, running, action-required and completed states remain distinct. Setup downloads can resume. After a service or host interruption, Vectis reconciles VM state only after it has evidence that the process exited. It stops only processes it started and tracks, and cleanup removes the owned VM and runner registration. + +### Security boundaries + +- Build work runs on your Mac. The Vectis cloud coordinates account identity, GitHub access and remote commands; it does not run workflow code. VM disks and build files stay on the host, while GitHub receives logs, artifacts and caches that workflows upload. +- Guest VMs receive no host folders, Docker socket, GitHub App private key or general host credentials. A guest receives only the single-use runner registration needed for its job. +- Each Mac maintains an outbound connection and does not expose an inbound service port. + +## Updating + +This is the first release, so install it: the app comes as a signed and notarized installer, and it includes an option to install matching `vectis` CLI and `vectis-mcp` launchers. Afterwards the app has an update path that waits for active work to finish. Then prepare an environment, pair the Mac with your Vectis account through browser approval, link GitHub and connect a repository. + +## Compatibility + +The app, CLI and service ship together. For macOS guests, complete guest setup locally and install Apple's Command Line Tools or Xcode in the guest; Xcode is not installed automatically. Project-specific runtimes and tools on Ubuntu guests are installed by workflow steps or containers. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later; Intel Macs are not supported. Ubuntu 24.04 ARM64 and macOS 26 ARM64 guests are supported. Windows 11 ARM64 is experimental and needs your own Windows and VirtIO media, a valid Windows license, and a separately installed QEMU build with the Vectis TPM patch, firmware and software TPM. All guests are ARM64, so workflows that require x86-64 binaries or x64 runner labels do not run unchanged. diff --git a/.github/release-notes/v0.1.1.md b/.github/release-notes/v0.1.1.md new file mode 100644 index 0000000..92a31c8 --- /dev/null +++ b/.github/release-notes/v0.1.1.md @@ -0,0 +1,49 @@ +# Vectis 0.1.1 + +**A reliability release. Runners start reliably in parallel, failed runners are retried, and jobs that wait for approval run once approved. An idle Mac also costs the cloud far less.** + +## Highlights + +### Parallel runners start reliably + +With several automatic runners, two jobs could start virtual machines within milliseconds of each other. The second start failed because the first, still booting, was treated as an interrupted VM that needed inspection. The affected GitHub jobs then waited until GitHub cancelled them. + +- A booting VM is now tracked as Starting. Admission counts the CPU and memory of starting VMs, so concurrent starts cannot over-commit the Mac. +- A genuinely interrupted VM still blocks new VMs, and runner capacity now reports no free slots while one exists, so the cloud stops handing out runners that cannot start. +- The app shows these VMs as Starting. + +### Failed runners are retried + +A runner that failed before GitHub gave it a job was never retried, so the job kept waiting. Vectis now retries it after a minute, within the existing limit of three attempts per job. Cancelled, unfinished and action-required attempts are still not retried. + +### Jobs that wait for approval now run + +Jobs gated by an environment approval report the GitHub status `waiting`, and GitHub also uses `requested` and `pending`. Vectis rejected these, so such jobs were never picked up after approval. + +- They are now stored as Waiting and get a runner as soon as GitHub queues them. The app shows them as Waiting. +- A runner that finds its job still waiting ends as cancelled without booting a VM. +- A person's cancellation of an unchanged job stays final. + +### A much quieter idle Mac + +One idle Mac used enough Convex database bandwidth to exhaust a free plan within a week. Heartbeats now write liveness and runner capacity to a separate table instead of rewriting the machine record, job scan times no longer rewrite repository bindings, and the app asks the cloud for a small change marker instead of the full job list, fetching the list only when something reads it. In our measurements an idle machine's database traffic dropped by more than 90 percent. Scheduling behavior is unchanged. + +### Diagnostics when a runner loses its guest + +When the guest connection is lost or the runner process exits unsuccessfully, Vectis now collects evidence before stopping the VM and keeps it on the failed operation: the runner's last output or the SSH error, the host's network view of the VM and, if the guest still answers, uptime, memory, the kernel log tail and the runner log tail. The text is capped at 16 KiB and scrubbed of the runner configuration. The app shows it in the activity details, and the CLI and MCP include it in the operation result. Windows guests report only uptime and the runner log, which is untested. + +### Security + +Dependencies `undici` and `devalue` moved past their patched versions, which closes the open Dependabot alerts. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Updating from 0.1.0 is automatic. Nothing needs to be prepared again. + +## Compatibility + +The cloud backend is already deployed and stays compatible with 0.1.0 apps. A 0.1.0 app cannot decode a job list that contains a Waiting job, so update the app on every Mac to see those jobs. The app, CLI and service ship together. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 ARM64 guests are supported; Windows 11 ARM64 is experimental. All guests are ARM64, so workflows that require x86-64 binaries do not run unchanged. diff --git a/.github/release-notes/v0.2.0.md b/.github/release-notes/v0.2.0.md new file mode 100644 index 0000000..b9ac912 --- /dev/null +++ b/.github/release-notes/v0.2.0.md @@ -0,0 +1,78 @@ +# Vectis 0.2.0 + +**Read job logs, see why a repository is not ready, decide who can start runners on your Mac, and rerun, cancel or dispatch GitHub runs from every surface. Linux guests can run x86_64 tools through Rosetta, Windows guests are kept off your local network, and runners that hang or lose their job clean up after themselves.** + +## Highlights + +### Job logs on every surface + +Read a GitHub job's log from the desktop, `vectis job logs --binding [--follow]`, or the MCP tool `vectis_job_logs`. Logs are fetched on demand with a byte cursor, so following a running job only transfers new output. The desktop opens a log panel under each job with follow, wrap and copy. + +### Readiness checks with the next step + +`vectis repository readiness`, the MCP tool `vectis_readiness` and the desktop's connect dialog check everything a repository needs, one item at a time: cloud connection, linked GitHub account, App installation, administrator access, fork approval policy, environment and connection. Each problem carries a code and the next step, and the desktop jumps to the place where you fix it. `vectis doctor` reports coded checks for the host runtime too. A new onboarding checklist on the Overview walks a fresh Mac from environment to first job. + +### Decide who can start runners on your Mac + +Each repository connection now has an access policy: anyone who can run workflows, or only listed GitHub users, and automatic or manually approved capacity. Jobs from other actors never get a runner, and jobs that need approval wait in **Needs you** until you approve them. Because GitHub can hand a runner a different queued job than the one it was started for, a job-started hook inside the guest checks the assigned job against the policy before any step runs, and stops the runner if it does not match. + +### Rerun, cancel and dispatch + +`vectis run rerun-failed`, `vectis run cancel` and `vectis workflow dispatch`, their MCP commands, and the job menu in the desktop control GitHub runs directly. Every request is idempotent: Vectis records it before contacting GitHub, never resends a request whose outcome is unknown, and reports such outcomes as unconfirmed instead of guessing. + +### x86_64 Linux tools through Rosetta + +Opt in per Linux environment with `vectis environment configure --x64 rosetta`. The guest then runs x86_64 binaries and `docker run --platform linux/amd64` images through Apple's Rosetta, shared read-only into the guest. The runner stays ARM64 and keeps its labels, so workflows choose this explicitly. + +### Network egress for Windows guests + +Windows guests are limited to the internet by default: connections to the Mac, its local network, loopback and link-local addresses are refused, while DNS and internet traffic work. Linux and macOS guests report their egress as not enforced on every surface, because Apple Virtualization's NAT cannot restrict it yet. + +### Runners that clean up after themselves + +- A runner requested for a job that no longer needs it is released after 10 minutes of inactivity, reported as `runner_idle`. +- An automatic runner request that a Mac never picks up expires after 2 minutes if the Mac went offline, or 10 minutes if it stayed online, so another connected Mac can take the job. +- When GitHub still holds a runner on a job that died, cleanup is retried automatically for up to 30 minutes instead of waiting for a manual reconcile. +- A request that lost its cloud lease can now be reconciled after its VM is confirmed stopped. +- A job the access policy refused ends as `runner_assignment_rejected`, not as a plain cancellation. + +### See what is happening + +- Jobs show the runner's stage next to their GitHub status: preparing, registering, waiting for a job, cleaning up, released. +- The desktop sends a macOS notification when Vectis needs you or work fails, even while its window is hidden. Clicking it opens the activity. Turn it off in Settings. +- A failed GitHub job now shows an error toast, even when its runner finished cleanly. + +### Workflow migration + +Migration rewrites only the `runs-on` values it moves, byte for byte, and keeps comments and formatting. The desktop shows which jobs move to Vectis, which stay, and why, instead of two plain file previews. + +### Security + +- Account linking and host isolation were hardened: each Linux instance has its own SSH host key, private fork policies are checked before a runner is registered, and Windows guests run with network isolation. +- Credentials are redacted from logs, operation details and stored diagnostics, including Windows bootstrap diagnostics. +- `@modelcontextprotocol/sdk` and `sharp` were updated. + +### Fixes + +- Exit evidence is kept when VM file cleanup fails, so an instance can still be reconciled. +- Windows bootstrap failures keep their diagnostics. +- Jobs that GitHub reports with runner `0` are recognized as unassigned again. +- Jobs inherit the guest's normal umask, so files they create are no longer private to the runner user. +- A removed environment's ID can be prepared again. +- Requesting a runner for a job GitHub does not know reports `job_not_found`. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Before you rely on it: + +- **Prepare Linux environments again.** Each Linux instance now gets its own SSH host key. Images prepared with 0.1.x report `action_required` until they are prepared again. To keep the environment ID, its `vectis-` runner label and existing repository connections, remove the old environment and prepare the new image under the same ID. Removing an environment keeps its image files on disk. +- **Approve the GitHub App's Actions write permission** to use run control. Until then, rerun, cancel and dispatch report `github_app_permission_required`. Everything else works without it. +- **Windows: rebuild QEMU with both Vectis patches.** Windows guests now start only with a QEMU build that supports network isolation (`native/qemu/patches/0002-isolate-vectis-user-network.patch`). Existing Windows base images do not need reinstalling. + +## Compatibility + +The cloud backend is deployed and stays compatible with 0.1.x apps. Run control, job logs and readiness need 0.2.0 on the Mac. The app, CLI and service ship together. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 ARM64 guests are supported; Windows 11 ARM64 is experimental. Guests are ARM64; Linux guests can run x86_64 tools through Rosetta when you opt in. Network egress is enforced only for Windows guests. diff --git a/.github/release-notes/v0.3.0.md b/.github/release-notes/v0.3.0.md new file mode 100644 index 0000000..60f7310 --- /dev/null +++ b/.github/release-notes/v0.3.0.md @@ -0,0 +1,57 @@ +# Vectis 0.3.0 + +**CI on Vectis is now steady and much faster. Runners recover from restarts and crashes on their own, lost GitHub webhooks are redelivered, the macOS two-VM limit is respected before a VM starts, and Windows jobs run in about a third of the time. New opt-in tools make startup nearly instant: derived environments with the runner preinstalled, a warm pool, per-repository cache volumes and GitHub runner scale sets.** + +## Highlights + +### Runners that heal themselves + +- After a service restart or crash, runners whose VM is confirmed stopped are reconciled and released automatically (`runner_recovery_pending`, then `runner_interrupted`). +- Every runner is released after five idle minutes, and a runner GitHub reports offline is stopped as `runner_offline` instead of holding a VM for hours. +- Transient GitHub errors are retried with backoff, honoring rate-limit headers, and are shown as **GitHub degraded** rather than a local failure. Side-effecting requests are never repeated. +- Only real failures count against a job's three attempts. + +### Scheduling that knows each environment + +Each Mac reports free slots per environment, so the cloud waits for a free macOS slot instead of starting a VM that cannot run. Failed GitHub webhook deliveries are redelivered every two minutes, and webhooks with unexpected fields are accepted instead of rejected. The cloud connection no longer drops every five minutes. + +### A shared memory budget + +VMs share one memory budget instead of reserving CPU one to one: vCPUs are overcommitted, memory uses each VM's measured footprint, and no new VM starts while the Mac is under memory pressure. Set the budget in Settings, with `vectis machine configure`, or through MCP. + +### Derived environments with the runner preinstalled + +`environment.provision` builds a new environment from a ready one, optionally running a setup script, and preinstalls the pinned runner so jobs skip the download. Removing a parent waits until its children are gone. + +On Windows, `vectis environment provision --from --image-directory ` adds Git for Windows (bash, GNU tar), zstd, PowerShell 7, a Defender exclusion and quieter background services, with the runner preinstalled. It takes about a minute and leaves the original image untouched. + +### Warm pool, cache volumes and scale sets + +- **Warm pool (opt-in per environment):** booted, credential-free VMs that a runner takes over in well under a second. +- **Cache volumes (opt-in per repository connection):** a private block device per repository, forked per job. Changes are written back only for push, schedule and dispatch runs on the default branch of the same repository. +- **Scale set capacity mode (preview, per repository connection):** GitHub assigns jobs to this Mac's runner scale set and Vectis starts runners for the assigned level, with no workflow changes. Connections with a restricted access policy stay on demand mode. + +### See where the time goes + +Every runner records phase timings (VM start, guest ready, registration, waiting for a job, job, cleanup), shown as a timeline in the desktop, in `vectis activity get` and through MCP. Status responses are bounded, with new operation and activity endpoints, and MCP status is compact. + +### Measured on a real Mac + +- Windows job with a 679 MB pnpm store: about 3 minutes to 67 seconds; pnpm install 105 s to 28 s. +- Warm pool takeover: 0.0 s instead of a 9.6 s cold start. +- Three parallel macOS jobs ran two at a time with no failed attempt. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Nothing needs to be prepared again, but two steps unlock the speedups: + +- **Windows: provision a derived environment** with `vectis environment provision` as described above to get the preinstalled runner and the tooling. +- **Linux: prepare the environment again** to use provisioning and cache volumes. Images prepared before 0.3.0 have no guest sudo and report `provision_requires_guest_sudo` or `cache_volume_requires_guest_sudo`. Fresh images also preinstall the runner. + +## Compatibility + +The cloud backend is deployed and stays compatible with 0.2.0 apps. Per-environment scheduling, scale sets, cache volumes and the other new features need 0.3.0 on the Mac. The app, CLI and service ship together. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 ARM64 guests are supported; Windows 11 ARM64 is experimental. Guests are ARM64; Linux guests can run x86_64 tools through Rosetta when you opt in. Network egress is enforced only for Windows guests. Scale sets use GitHub's preview API. diff --git a/.github/release-notes/v0.3.1.md b/.github/release-notes/v0.3.1.md new file mode 100644 index 0000000..d7b05a6 --- /dev/null +++ b/.github/release-notes/v0.3.1.md @@ -0,0 +1,25 @@ +# Vectis 0.3.1 + +**Linux environments can be prepared again, and Vectis's own CI is steadier on a busy Mac.** + +## Highlights + +### Linux preparation works again + +0.3.0 could stop with `step=packages exit=100` when first-boot services held the apt lock. Preparation now waits for apt and dpkg locks, runs apt non-interactively, and replays the failing step's last lines on the console instead of losing them behind the login prompt. If a 0.3.0 preparation stopped this way, start a new one after updating. + +### Steadier release checks + +Release package verification checks the compact MCP status, and slow service test suites get enough time when the CI host is running other VMs. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Nothing needs to be prepared again, except a Linux preparation that stopped at the packages step: start it again. + +## Compatibility + +The app, CLI and service ship together. The cloud is unchanged from 0.3.0. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 ARM64 guests are supported; Windows 11 ARM64 is experimental. Guests are ARM64; Linux guests can run x86_64 tools through Rosetta when you opt in. Network egress is enforced only for Windows guests. Scale sets use GitHub's preview API. diff --git a/.github/release-notes/v0.3.2.md b/.github/release-notes/v0.3.2.md new file mode 100644 index 0000000..c3b81f2 --- /dev/null +++ b/.github/release-notes/v0.3.2.md @@ -0,0 +1,32 @@ +# Vectis 0.3.2 + +**A security release. Vectis now rejects the compromised eMudhra certificate chains in its own runtime, the runner and the guests, and new macOS environments default to macOS 27. The cloud also caps connected Macs per account and expires stale job records.** + +## Highlights + +### Security + +- The private keys of eight eMudhra intermediate CAs turned out to be trivially recoverable, and clients that check neither revocation nor certificate transparency still accept chains through them. Vectis now ships Node 24.22.2 and Electron 44.10.1, and updates the Actions runner to 2.338.2, which bundles Node 24.22.1. These include the blocklist that rejects those chains. +- Linux preparation pins a newer Ubuntu image and upgrades `ca-certificates`, failing unless the installed version distrusts the affected root. Windows Git uses the Windows certificate store. On macOS, each runner start gives the job a private CA bundle without the two affected roots. +- The account page no longer allows arbitrary inline scripts, and site and packaging dependencies with security advisories were updated. + +### macOS 27 by default + +New macOS environments default to macOS 27. macOS 26 is still accepted for local restore images and setups already in progress. The `macos-27` workflow migration label is available. + +### Cloud limits and cleanup + +- An account can connect at most 100 Macs. A further enrollment or pairing approval is rejected with `machine_limit` and a next step, and the connect page explains the limit. Existing machines and pairings keep working at the limit. +- Job records that have not been updated for 90 days are removed, so jobs whose end was never seen, for example after a lost webhook, no longer linger or compete for automatic runner demand. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Updating does not rewrite existing prepared VM images: Ubuntu environments pick up the pinned runner at instance start, but prepare them again to get the newer `ca-certificates` and the preinstalled fast path. Provisioning a Windows environment again applies the Git certificate-store setting. Existing full-Xcode macOS environments should be preserved until a replacement is validated. + +## Compatibility + +GitHub JavaScript actions run on GitHub's Node 24 engine. A real Vectis job verified that a legacy `using: node20` action runs on Node 24, while `actions/setup-node` can still select Node 20 for workflow commands. Node 20.20.2 accepted a known-compromised eMudhra certificate chain in our TLS test, so Node 20 workflow compatibility is not a guarantee of TLS protection; use a runtime with verified trust fixes for TLS-sensitive work. The machine cap and job cleanup run in the cloud backend, so they apply to every app version. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 and 27 ARM64 guests are supported; Windows 11 ARM64 is experimental and needs separately installed QEMU, qemu-img, swtpm, ARM64 UEFI firmware, and the required Windows and driver installation media, which the release assets do not bundle. Guests are ARM64; Linux guests can run x86_64 tools through Rosetta when you opt in. Network egress is enforced only for Windows guests. Scale sets use GitHub's preview API. diff --git a/.github/release-notes/v0.4.0.md b/.github/release-notes/v0.4.0.md new file mode 100644 index 0000000..782e7ae --- /dev/null +++ b/.github/release-notes/v0.4.0.md @@ -0,0 +1,49 @@ +# Vectis 0.4.0 + +**Guests survive long, heavy jobs. Vectis no longer starts a VM into a thrashing or nearly full Mac, keeps the Mac awake while VMs run, and keeps the evidence when a guest dies. Jobs lost to infrastructure failures can be rerun automatically, and macOS 27 environments set themselves up without Setup Assistant.** + +## Highlights + +### Guests that survive heavy jobs + +- Linux boot and cache disks now use explicit cached disk modes with full synchronization. Implicit modes are the configuration other Virtualization.framework projects linked to corrupted Linux filesystems and guest `Input/output error` failures. +- VM admission now measures the process that actually holds guest memory: the Virtualization.framework XPC process on Apple hosts, and the QEMU process tree for Windows. Previously every Apple VM was budgeted at the 2 GiB floor. +- New VMs are refused with `memory_pressure` while the memory compressor holds at least 25% of physical memory, even when macOS still reports normal pressure. Status shows swap and compressor usage. +- Instances refuse to start with `storage_headroom` when the VM volume has less than 20 GiB free, instead of failing mid-job with disk errors. +- The service holds an idle-sleep assertion while it owns running VMs or a preparation, so the Mac does not sleep in the middle of a job. Closing the lid or an explicit sleep still sleeps. + +### Evidence when something goes wrong + +- Linux guests write their serial console to `diagnostics/serial/.log` in the Vectis home, and failed runners attach the tail of it. +- A runner that dies from an infrastructure failure now ends `failed` with its original cause, instead of looking like a harmless `runner_interrupted`. +- A runner that GitHub has seen busy is no longer stopped when status lookups fail during a cloud or GitHub outage. + +### Rerun jobs lost to infrastructure + +An opt-in policy per repository connection, off by default, reruns a job once when its runner failed with `guest_unavailable`, `runner_offline` or `storage_io_error`. Turn it on with `vectis repository enable-infra-rerun `, the **Rerun infra failures** switch in the desktop, or MCP. A run with any other failed job is never rerun, and an automatic attempt is never rerun again. + +### macOS 27 guests without Setup Assistant + +When the host and the guest both run macOS 27, `environment install-macos` creates the account, turns on Remote Login, installs the guest key and finishes setup with no one at the screen. The generated password never leaves memory. + +### Closer to GitHub's hosted runners + +- Prepared Ubuntu guests include `gh`, Docker Compose and Buildx from Ubuntu's archive. +- macOS jobs start with `/opt/homebrew/bin`, `/opt/homebrew/sbin` and `/usr/local/bin` on PATH. + +### Scheduling and efficiency + +- Queued jobs that this Mac can never run no longer hide newer eligible jobs from automatic runner demand. +- The service stops polling the guest over SSH once a job has started, which saves about 180 SSH handshakes per VM over a 30-minute job. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Existing environments keep working. Ubuntu environments prepared before 0.4.0 lack `gh`, Docker Compose and Buildx; prepare them again or run `vectis environment provision` to add them. The disk mode and PATH changes apply without preparing again. + +## Compatibility + +The app, CLI and service ship together. The infrastructure rerun policy and the new admission checks need 0.4.0 on the Mac. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 and 27 ARM64 guests are supported; Windows 11 ARM64 is experimental. Unattended macOS setup needs macOS 27 on both the host and the guest. Guests are ARM64; Linux guests can run x86_64 tools through Rosetta when you opt in. Network egress is enforced only for Windows guests. diff --git a/.github/release-notes/v0.5.0.md b/.github/release-notes/v0.5.0.md new file mode 100644 index 0000000..98ac42d --- /dev/null +++ b/.github/release-notes/v0.5.0.md @@ -0,0 +1,38 @@ +# Vectis 0.5.0 + +**Vectis has a new cloud. It runs on Cloudflare and only does work when something changes. An idle Mac now holds one quiet connection instead of polling every 30 seconds. Paired Macs need to pair once more after updating.** + +## Highlights + +### An event-driven cloud + +- Each Mac keeps one WebSocket to the cloud. Keep-alive pings are answered without waking anything, so an idle Mac costs no cloud work. +- The cloud signals the Mac when a remote command, query or job arrives. The Mac then syncs once, plus a safety sync every 15 minutes. +- Runner demand runs only on events: a GitHub webhook, a change in free capacity, or a runner finishing. Retries and failed webhook redeliveries run every two minutes. +- Missed-job scans moved to the Mac: once on connect, then hourly for each automatic repository. + +### Same commands everywhere + +Desktop, CLI, MCP and remote control use the same commands as before. Remote operations still replay on the Mac under the same idempotency keys. + +### More honest account page + +The account page talks to the cloud directly and says so when it cannot load your account, with a way to retry, instead of loading forever. + +## Updating + +Installed apps find this release within four hours, and the update waits for active work to finish. Your environments, prepared images and local history stay as they are. Accounts, machines and repository connections start fresh in the new cloud, so on each Mac: + +1. Pair again from the desktop app, or with `vectis cloud pair` and `vectis cloud finish`, and approve it on [vectis.kerd.dev/connect](https://vectis.kerd.dev/connect). +2. Link your GitHub account again on the GitHub tab of the account page. +3. Connect your repositories again. Settings such as automatic runners, cache volumes and access policies are chosen again per repository. + +Remote control from another machine needs a fresh `vectis login`. + +## Compatibility + +0.4.0 and earlier apps cannot connect to the new cloud. Update every Mac and pair it again. Self-hosted deployments move from Convex to the cloud Worker in `apps/cloud`, which needs the Cloudflare Workers Paid plan; [Run your own cloud](https://vectis.kerd.dev/docs/self-hosting/cloud) has the new setup. + +## Platform requirements and limitations + +Apple Silicon Mac with macOS 15 or later. Ubuntu 24.04 ARM64 and macOS 26 and 27 ARM64 guests are supported; Windows 11 ARM64 is experimental. Guests are ARM64; Linux guests can run x86_64 tools through Rosetta when you opt in. Network egress is enforced only for Windows guests. diff --git a/.github/release.yml b/.github/release.yml index 0f87005..e709c4e 100644 --- a/.github/release.yml +++ b/.github/release.yml @@ -4,19 +4,3 @@ changelog: - internal authors: - dependabot - categories: - - title: Features - labels: - - enhancement - - title: Fixes - labels: - - bug - - title: Security - labels: - - security - - title: Documentation - labels: - - docs - - title: Other changes - labels: - - "*" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4d3d3f9..bd273ce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,6 +25,14 @@ jobs: echo "Tag ${GITHUB_REF_NAME} does not match package.json version ${version}." >&2 exit 1 } + - name: Release notes exist + run: | + version=$(jq -r .version package.json) + notes=".github/release-notes/v${version}.md" + test "$(head -n 1 "$notes" 2>/dev/null)" = "# Vectis ${version}" || { + echo "Add ${notes} starting with '# Vectis ${version}' (see RELEASING.md)." >&2 + exit 1 + } check: needs: preflight @@ -121,12 +129,21 @@ jobs: permissions: contents: write steps: + # Check out before downloading: checkout cleans the workspace. + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + sparse-checkout: .github/release-notes - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2 with: name: release path: release + - id: version + run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + # The written notes come first; GitHub appends the generated pull request list. - uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3 with: + name: Vectis ${{ steps.version.outputs.version }} + body_path: .github/release-notes/${{ github.ref_name }}.md files: release/* generate_release_notes: true prerelease: ${{ contains(github.ref_name, '-') }} diff --git a/RELEASING.md b/RELEASING.md index 38fea46..2641ff0 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -55,9 +55,38 @@ Rulesets need a public repository on the free plan. After the repository is publ ## Cut a release -1. Open a pull request titled `chore(release): vX.Y.Z` that only changes `version` in the root `package.json`. Merge it. +1. Open a pull request titled `chore(release): vX.Y.Z` that changes `version` in the root `package.json` and adds `.github/release-notes/vX.Y.Z.md` (see [Release notes](#release-notes)). Merge it. 2. Tag the merge commit and push the tag: `git tag vX.Y.Z && git push origin vX.Y.Z`. A tag with a hyphen, such as `v0.2.0-rc.1`, becomes a prerelease. -3. Approve the `release` deployment. The workflow checks the tag against the version, runs `check`, applies D1 migrations and deploys the cloud Worker, builds, signs and notarizes the app in the macOS VM, publishes the GitHub release with generated notes, and redeploys the website so the changelog and download pick up the release. +3. Approve the `release` deployment. The workflow checks the tag against the version, runs `check`, applies D1 migrations and deploys the cloud Worker, builds, signs and notarizes the app in the macOS VM, publishes the GitHub release as `Vectis X.Y.Z` with the written notes followed by the generated pull request list, and redeploys the website so the changelog and download pick up the release. 4. Installed apps find the update within four hours. Backend changes must keep working with the previous release, because installed apps update at their own pace. + +## Release notes + +Every release uses the same notes. The written part lives in `.github/release-notes/vX.Y.Z.md`; `preflight` refuses a tag without it, and `publish` appends GitHub's generated `## What's Changed` list (merged pull requests and the full changelog link). The website changelog shows the published notes, so fix a release afterwards by editing that file and the GitHub release together, then redeploying the site. + +The file has exactly these parts, in this order: + +```md +# Vectis X.Y.Z + +**Two or three sentences in bold: what changed for the user.** + +## Highlights + +### A short topic phrased as an outcome + +## Updating + +## Compatibility + +## Platform requirements and limitations +``` + +- **Highlights**: one `###` topic per change a user notices, as a short paragraph or bullets. Security fixes, other fixes and measurements are topics here too (`### Security`, `### Fixes`, `### Measured on a real Mac`), never separate sections. A patch release still has at least one topic. +- **Updating**: start with "Installed apps find this release within four hours, and the update waits for active work to finish." Then say what the user has to do after updating, such as preparing an environment again or pairing again, or "Nothing needs to be prepared again." +- **Compatibility**: which app versions the cloud still serves, what needs the new app, and what existing images miss. When nothing applies: "The app, CLI and service ship together." +- **Platform requirements and limitations**: one paragraph describing the platform as of this release. + +State only verified behavior, in plain English with ASCII hyphens and no emojis. Use no other headings, and do not write the pull request list by hand. `.github/release-notes/v0.5.0.md` is a complete example.