Commit Graph
55 Commits
Author SHA1 Message Date
JMR-devandCopilot 76a44c0999 Add --gui flag to integration tests to exercise GUI package install
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 13:48:42 -05:00
JMR-devandCopilot 3e27e54318 Run full bootstrap in integration tests; fix pnpm setup shell detection
- Integration tests now run the full bootstrap (system + flatpak + custom +
  AI + VM packages) instead of '--only custom --no-vm --no-ai', so that
  custom-package prerequisites (zsh, gh, etc.) installed via SystemPackages
  are actually available.
- Fix 'pnpm setup' failing with ERR_PNPM_UNKNOWN_SHELL in CI containers
  by exporting SHELL=/bin/bash before invoking it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 13:47:32 -05:00
JMR-dev ad2976842f Fix integration tests 2026-05-26 13:38:52 -05:00
JMR-devandCopilot c3ddcb336a Forward GITHUB_TOKEN into Linux Dagger containers for API auth
Add env: GITHUB_TOKEN to the Linux workflow step, then read it in
ci/main.go and inject it into each test container via WithSecretVariable
(for both GITHUB_TOKEN and GH_TOKEN). This prevents 403 rate-limit
errors on GitHub API calls (neovim/nvm releases) and authenticates
gh CLI for gh extension install inside the containers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 13:37:48 -05:00
JMR-devandCopilot a2f36665a3 Pass GITHUB_TOKEN to macOS CI step to fix 403 rate-limit errors
Unauthenticated GitHub API calls share the runner IP (60 req/hour limit).
net.go already uses GITHUB_TOKEN as a Bearer token when present.
gh CLI also needs GH_TOKEN to authenticate for gh extension install.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 13:36:22 -05:00
JMR-devandCopilot 9093aedb66 Exit non-zero when any errors are logged during bootstrap run
Track error count in issues.go alongside the existing issues slice.
Add hasErrors() helper. In main.go, call osExit(1) after writeRunLog()
if any [ERROR] entries were recorded, so CI steps correctly fail when
errors occur (e.g. GitHub API 403 rate-limit hits in the macOS job).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-26 13:35:05 -05:00
JMR-dev 4d99bba06f added repo bootstrap tool 2026-05-26 13:21:31 -05:00
Jason Ross ee95457e7d Merge pull request #18 from JMR-dev/fix-add-unit-testing
added unit testing
2026-05-26 09:36:50 -05:00
JMR-dev 669565bb87 added unit testing 2026-05-26 09:36:05 -05:00
Jason Ross 39c23595ce Merge pull request #17 from JMR-dev/feat-add-AI-cli-packages
updates to add AI packages and an opt out of AI flag
2026-05-25 12:11:32 -05:00
JMR-dev 8f11c8d68b updates to add AI packages and an opt out of AI flag 2026-05-25 12:07:14 -05:00
Jason Ross d9e905ac20 Merge pull request #16 from JMR-dev/fix-gha-workflow
Workflow fix to git sha
v0.1.0
2026-05-23 17:58:43 -05:00
JMR-dev 14bf9f3e56 Workflow fix to git sha 2026-05-23 17:57:50 -05:00
Jason Ross f6fdb3f6ae Merge pull request #15 from JMR-dev/claude/github-workflow-permissions-token-pNozt
ci: pass GITHUB_TOKEN explicitly to checkout and release steps
2026-05-22 17:55:29 -05:00
Claude d7d87acb7e ci: pass GITHUB_TOKEN explicitly to checkout and release steps
Add explicit token inputs to the checkout and softprops/action-gh-release
steps so the GitHub token is wired through instead of relying on implicit
defaults. The workflow-level contents: write permission already scopes
the token correctly for tag/release creation.
2026-05-22 22:07:50 +00:00
Jason Ross 817a0ad8a4 Merge pull request #14 from JMR-dev/claude/port-tool-golang-ziaMN
port: rewrite bootstrap tool in Go
2026-05-22 17:00:30 -05:00
Claude 03a90fffe6 ci: add release workflow that builds binaries and publishes SHA256SUMS
Pushing a tag matching v* (or running the workflow manually with an
existing tag) cross-compiles the four supported targets via
`make build-all`, generates a SHA256SUMS file, and publishes a GitHub
release with all binaries attached.
2026-05-22 21:55:15 +00:00
Claude 658460fe4c port: rewrite bootstrap tool in Go
Replace the Python bootstrap script with a Go implementation that
cross-compiles to native binaries for Linux and macOS on x86_64 and
aarch64. The Go port preserves all sections of the original (system
packages, optional Flatpak GUI apps, custom downloads, and the macOS
firecracker VM bridge) and adds first-class pacman support so the tool
works on Arch-family distros alongside Debian, RHEL, and macOS.

A Makefile produces a host binary via `make build` and the full
four-target matrix under dist/ via `make build-all`.
2026-05-22 21:48:57 +00:00
Jason Ross c2ca21b444 Merge pull request #13 from JMR-dev/claude/pip-decimal-import-error-eVPBv
fix: detect and repair broken _decimal C extension before pip install
2026-05-22 14:21:35 -05:00
Claude 26bd80c97d fix: detect and repair broken _decimal C extension before pip install
When python3-full is not installed on Debian/Ubuntu (common with Python
3.13), the _decimal C extension fails to import, crashing any pip
invocation with RuntimeError.  Add _python3_decimal_ok() to probe for
this, and _fix_python3_decimal() to install python3-full (apt) or
python3-libs (dnf).  _install_pip() now calls these before attempting
any ensurepip/pip operations so the error is fixed automatically rather
than producing an unrecoverable crash.

https://claude.ai/code/session_01Lrg3UV7AJN9KRXyTTWGgZi
2026-05-22 19:20:51 +00:00
Jason Ross b3ad702da0 Merge pull request #12 from JMR-dev/claude/bootstrap-infinite-loop-arm64-VU64t
fix: cap pip detection subprocess with a 10s timeout
2026-05-22 14:14:53 -05:00
Claude 8a0e3ee9e4 fix: add timeouts to every subprocess invocation
`run()` and `shell()` now default to a 30-minute cap (generous enough for
heavy apt/brew installs and large downloads, bounded enough to catch a
true hang). Callers can override per-call.

All remaining direct subprocess.run sites have explicit timeouts sized to
the work they do: short caps for read-only probes (rpm, dpkg, brew list,
flatpak info, gh auth status, xcode-select -p, sysctl, VBoxManage), a
60-minute cap for the pyenv Python compile, a 15-minute cap for the
interactive `gh auth login` browser flow, and ConnectTimeout+30s for the
VM SSH helper. A small `_probe()` wrapper centralizes the probe pattern.

On timeout the bootstrap now warns and either fails the check gracefully
or returns rc=124, rather than blocking indefinitely.

https://claude.ai/code/session_01447pnRM4ogyxs5tVCUNDZW
2026-05-22 19:11:04 +00:00
Claude 4525cbc219 fix: cap pip detection subprocess with a 10s timeout
A hung `python3 -m pip --version` inside `_pip_installed()` could block
the bootstrap indefinitely, since `subprocess.run` was called without a
timeout. Treat a timeout (or a missing python3) as "pip not installed"
so the bootstrap proceeds to install it rather than hanging.

https://claude.ai/code/session_01447pnRM4ogyxs5tVCUNDZW
2026-05-22 19:05:28 +00:00
Jason Ross 1c011f4a7d Merge pull request #11 from JMR-dev/claude/script-idempotency-review-CBYwG
Make _clone_nvim_config idempotent
2026-05-22 13:58:29 -05:00
Claude a4b855b796 Rename existing nvim config to nvim-N instead of skipping
On re-runs, ~/.config/nvim is moved aside to ~/.config/nvim-1
(or nvim-2, nvim-3, ... — first free number) and a fresh clone is
created. End-of-run notices report the backup path so it's visible
after the rest of the bootstrap output scrolls by.
2026-05-22 18:55:44 +00:00
Claude cedaf4ce04 Make _clone_nvim_config idempotent
Previously rmtree'd ~/.config/nvim on every full bootstrap run, destroying
any user edits, plugin state, and undo history. Now skips when the
directory is already a clone of the expected repo, and refuses to touch
unfamiliar contents (different remote, or non-git directory).
2026-05-22 18:51:30 +00:00
Jason Ross 92a582efa7 Merge pull request #10 from JMR-dev/claude/neovim-detection-debian-arm64-FqnpH
Fix Neovim not found after install by symlinking /usr/local/bin/nvim
2026-05-22 13:47:09 -05:00
Claude 10963c848b Fix Neovim not found after install by symlinking /usr/local/bin/nvim
The PATH line written to /etc/profile.d/neovim.sh was only sourced by
login shells via /etc/profile. zsh — set as the default shell by this
script — uses /etc/zsh/zprofile which sources /etc/profile only for
login shells, and terminal emulators typically launch non-login
interactive shells. The result on Debian 13 ARM64 (and other distros):
nvim installed correctly to /opt/nvim-linux-arm64 but was not on PATH
in a normal terminal session.

Symlink the binary into /usr/local/bin/nvim instead — that directory
is always on the default PATH on Linux and macOS (Apple Silicon and
Intel) regardless of shell type. The Zig install already follows this
pattern. Also switch the install-detection probe to the symlink so it
verifies an actually-callable nvim, not just the extracted directory.

https://claude.ai/code/session_01VP9hCLH1c5F5iv468jSkqs
2026-05-22 18:27:10 +00:00
Jason Ross e5448b71ba Merge pull request #9 from JMR-dev/claude/pulumi-repo-setup-failure-KEncj
Fix Pulumi repo setup failure by installing from official tarball
2026-05-22 13:14:27 -05:00
Claude 6661aba3d6 Fix Pulumi repo setup failure by installing from official tarball
Pulumi does not publish apt or yum repositories — the URLs the setup
function referenced (api.pulumi.com/releases/sdk/{apt,rpm}-keyring.gpg
and {apt,yum}.releases.pulumi.com) return 404 / do not resolve, which
broke `bootstrap_environment.py` on every fresh Linux run.

Replace `setup_pulumi_repo` with a special-package installer that
downloads the official GitHub release tarball, verifies the SHA256
against the published checksums file, extracts to /opt/pulumi, and
exposes the binaries via PATH — the same pattern used for Neovim.
macOS continues to install Pulumi via brew.

https://claude.ai/code/session_018L1gFoc8L3CYqLE2wNjpy6
2026-05-22 18:13:43 +00:00
Jason Ross 16f058f83c Merge pull request #8 from JMR-dev/claude/debian-arm64-install-errors-ekxEt
Fix five Debian arm64 install failures
2026-05-22 13:05:53 -05:00
Claude da80fe81bc Fix five Debian arm64 install failures
- dotnet-sdk-10.0: add setup_dotnet_repo() to register the Microsoft apt
  feed (packages.microsoft.com) before attempting the install
- lua: map to lua5.4 in apt-get overrides (Debian has no unversioned lua pkg)
- pulumi: add setup_pulumi_repo() to register apt.releases.pulumi.com before
  attempting the install; add dnf/yum variant too
- qemu: map to qemu-system in apt-get overrides (Debian meta-package name)
- python3 -m ensurepip: Debian intentionally strips ensurepip from the system
  Python package; fall back to apt-get install python3-pip automatically

Also add libnsl2 → libnsl-dev mapping for Debian (bonus pyenv build fix).

https://claude.ai/code/session_017KuwqSq7nCp2iWiTeaNivn
2026-05-22 18:05:05 +00:00
Jason Ross 2e9cbb0cab Merge pull request #7 from JMR-dev/claude/headless-default-gui-flag-KCpH8
Default to headless install; add --gui flag; add lazygit and pulumi
2026-05-22 12:57:26 -05:00
Claude 18182aee58 Default to headless install; add --gui flag; add lazygit and pulumi
- Inverts the GUI opt-out model: GUI packages and Flatpak are now skipped
  by default (headless-friendly), and --gui opts in to installing them.
  Removes --no-gui entirely.
- Adds lazygit and pulumi to the default system package list.

https://claude.ai/code/session_01CsTAu2SNhE5ZAQm3RnVwp3
2026-05-22 17:56:27 +00:00
Jason Ross 5b184d81ff Merge pull request #6 from JMR-dev/claude/custom-packages-checksum-yf1cS
Fix custom package checksum verification for Mac and Linux arm64
2026-05-22 12:52:08 -05:00
Claude 8668c12f7d Fix custom package checksum verification for Mac and Linux arm64
Three root causes were causing failures on non-x86_64-Linux platforms:

1. Single SHA256 per package: the pinned fallback checksum in
   formatted_packages.py was a single value computed for linux-x86_64 only.
   Downloads on linux-aarch64, macos-x86_64, and macos-aarch64 produced
   different binaries with different digests, so verification always failed
   on those platforms when the fetch_latest resolver was unavailable.

   Fix: replace the single `sha256` field with a `sha256_map` dict keyed by
   "{os}-{arch}" (e.g. "linux-aarch64", "macos-arm64"). Added the correct
   pinned digests for all four supported platforms for both Go 1.26.3 and
   Firecracker 1.15.1, fetched from official sources.

2. Case-sensitive SHA256 comparison: _sha256_of() always returns lowercase
   hex, but checksums returned by external APIs could be uppercase.
   _verify() compared them without normalising case, causing false mismatches.

   Fix: new resolved_sha256 property always returns a lowercased digest;
   _resolve_latest() also lowercases the dynamically-fetched sha before
   storing it.

3. Firecracker not skipped on macOS: _resolve_latest_firecracker() returns
   None on macOS (firecracker is Linux-only), causing a fallback to the
   pinned linux binary URL with a linux-only checksum map entry. The download
   and verification would both fail misleadingly.

   Fix: explicit early-continue guard in install_custom_packages() when
   name == "firecracker" and IS_MACOS.
2026-05-22 17:49:58 +00:00
Jason Ross 539833344b Merge pull request #5 from JMR-dev/claude/add-python-build-deps-u1Gg5
Add missing Python build deps and fix apt-get name overrides
2026-05-18 16:44:49 -05:00
Claude 01bb797433 Add missing Python build deps and fix apt-get name overrides
Adds curl, ncurses-devel, xz (tool), libxml2-devel, and xmlsec1-devel to
SYSTEM_PACKAGES to cover the full pyenv/CPython build dependency set.

Also adds apt-get overrides for all Fedora-named Python build packages
(bzip2-devel → libbz2-dev, openssl-devel → libssl-dev, etc.) so they
resolve to the correct Debian/Ubuntu package names at install time.
Adds corresponding brew overrides for the new packages.

https://claude.ai/code/session_01P3CkL5oXzkTvayityg3uaH
2026-05-18 21:32:30 +00:00
Jason Ross caa010091f Merge pull request #4 from JMR-dev/claude/fix-package-install-errors-A2rBu
Handle OSError from subprocess when filesystem I/O fails
2026-05-18 12:28:39 -05:00
Claude 112b0005e4 Handle OSError from subprocess when filesystem I/O fails
When the system has disk I/O errors (errno 5), subprocess.run raises
OSError before a process can even start. The run() and shell() helpers
now catch OSError: if check=False the error is logged as a warning and
a returncode=1 CompletedProcess is returned so callers like
install_system_packages can continue; if check=True the error is
re-raised as before.

https://claude.ai/code/session_01Gsfw2QLhQiFVEvZQC5nVcU
2026-05-18 17:26:52 +00:00
Jason Ross 21a635de8e Merge pull request #3 from JMR-dev/claude/fix-debian-arm64-install-Mmx95
Fix Docker repo setup for Debian ARM64
2026-05-18 12:06:17 -05:00
Claude aa39c2f493 Fix README usage command
- curl and unzip were pipe-chained, but -o writes to a file so the pipe
  produced nothing; split into separate steps with &&
- Extracted directory is bootstrap_dev_env-main, not bootstrap
- Script is bootstrap_environment.py, not bootstrap_dev_env

https://claude.ai/code/session_01CkJR1eHoBVMyNNeGdbRBYK
2026-05-18 17:05:35 +00:00
Claude e230da3d28 Fix Docker repo setup for Debian ARM64
Two issues caused failures on Debian 13 (Trixie) ARM64:

1. apt-get update was never called before installing gnupg, leaving the
   package cache stale. The cached version (gnupg2 2.4.7-21+b3) was no
   longer available on the ARM64 mirror, producing 404 errors. Adding
   apt-get update before the install fixes this.

2. The Docker GPG key and apt repo URL were hardcoded to the Ubuntu
   endpoint. Debian has its own Docker repo at
   https://download.docker.com/linux/debian. The distro ID is now read
   from /etc/os-release and used to select the correct URL.

https://claude.ai/code/session_01CkJR1eHoBVMyNNeGdbRBYK
2026-05-18 16:50:10 +00:00
Jason Ross b463636192 Create README.md
Usage instructions
2026-05-18 11:29:20 -05:00
Jason Ross 6bec83b5e9 Merge pull request #2 from JMR-dev/claude/add-macos-support-s0p5z
Add macOS support with Homebrew + Xcode CLT bootstrap
2026-05-18 10:56:33 -05:00
Claude b4b4fde78d macOS firecracker VM: backend per host (nested-virt aware)
Pick a hypervisor based on the host's actual nested-virt capability
instead of always using QEMU/HVF (which doesn't expose nested KVM):

  * Apple Silicon M3+ on macOS 15 Sequoia+: QEMU/HVF with
    -cpu host,el2=on so the Linux guest's KVM (and therefore
    firecracker microVMs) actually works.
  * Intel Mac: VirtualBox with --nested-hw-virt on. Cask is
    installed on demand; the seed ISO and SSH key flow are shared
    with the QEMU path.
  * Apple Silicon M1/M2 (any macOS), or M3+ pre-Sequoia: skip the
    whole VM step and print a notice pointing at a Linux cloud VM
    as the only path to firecracker on that hardware.

Backend selection is centralized in _select_vm_backend(); the rest
of setup_firecracker_vm (image download/verify, cloud-init seed,
SSH wait, in-VM firecracker probe, zsh wrapper) is shared.

https://claude.ai/code/session_01R2CnCeEBYT5QoHiwxczDNq
2026-05-18 15:25:42 +00:00
Claude 1ffece623e macOS: provision Fedora-on-QEMU VM and firecracker() zsh bridge
After the normal package install on macOS, fetch the latest Fedora
cloud qcow2 (auto-discovered from dl.fedoraproject.org), verify its
SHA256, build a cloud-init seed ISO with hdiutil, boot it under
QEMU/HVF (UEFI on aarch64, q35 on x86_64), and wait for cloud-init
to install firecracker inside the guest.

Then write a `firecracker()` function block into ~/.zshrc that
starts the backing VM on demand and proxies invocations via SSH.
The host's own firecracker custom-package install is dropped on
macOS since it's Linux-only. Suppress the whole flow with --no-vm.

https://claude.ai/code/session_01R2CnCeEBYT5QoHiwxczDNq
2026-05-18 14:40:49 +00:00
Claude 5560d6b793 Add macOS support with Homebrew + Xcode CLT bootstrap
Detect Darwin automatically and, on macOS, install the Xcode Command
Line Tools and Homebrew as the first actions before any package work.
Route system packages through brew (formulae and casks), skip the
Flatpak section entirely, refuse to run as root (brew won't), and
adjust custom-package URL/install-path templates with new {os}, {os_go},
{os_zig}, {os_nvim} substitutions. Architecture detection remains
dynamic on both Apple Silicon and Intel.

https://claude.ai/code/session_01R2CnCeEBYT5QoHiwxczDNq
2026-05-18 14:27:01 +00:00
Jason Ross 4cf2645aaf Merge pull request #1 from JMR-dev/claude/refactor-packages-python-20kcR
Refactor package list to Python module with dynamic versions
2026-05-18 09:10:35 -05:00
Claude 8acdb30e83 Add zsh + oh-my-zsh, set default shell per distro family
- Add zsh to SYSTEM_PACKAGES
- Detect RHEL-family vs Debian-family from /etc/os-release ID/ID_LIKE
  (falls back to PKG_MGR if os-release is unreadable)
- ensure_zsh_default sets zsh as the invoking user's login shell after
  system install: usermod -s on RHEL-family (chsh under default
  authselect refuses other-user changes), chsh -s elsewhere; SUDO_USER
  is preferred so sudo invocations target the real user
- Add oh-my-zsh to CUSTOM_PACKAGES; the installer runs the official
  unattended script (requires zsh + git, which are already installed by
  this point) and rewrites ZSH_THEME to "gnzh" in ~/.zshrc
- As a final step, run 'zsh -c "source ~/.zshrc"' to validate the rc
  file (the user's interactive shell is unaffected — they need a new
  terminal to pick up the new default shell)
2026-05-18 14:05:09 +00:00