boxd 0.1.0 → 0.1.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f49524201855c87e4519d024cb44bea9aa8e1025e447063abb6bc54d051ed45d
4
- data.tar.gz: 1477bd7f3e17f61fc33774ba39ee6556b410a6d1b61fcf93cd6f97caf50374e4
3
+ metadata.gz: c522b2f321d84049fd8dd3d60cb82367edc2e4e587833020df8959ba6a13573b
4
+ data.tar.gz: 76708e00dcac901bcb25f3201e70d130a527d29176c1711145ebd5e4f9538063
5
5
  SHA512:
6
- metadata.gz: 726612934833830a0280c892c10edc75a0dc3ce7d9cfc88f3d83dc4177bd32335e6558c25336b35bef226c783eca578c92e17665b476ae3d194d22b9d5949fb0
7
- data.tar.gz: 9650055697701481d8e7cea406db62c7cd37604b0a8c1e45ef8b1a5b9f95a3ebc494ab504edee7df24e384008cad5a4b144f9ccbe4e483ed1760f062c60b74a9
6
+ metadata.gz: b47103a2b153dd685cbbe2bd80d001693c5db6a8636e0e513e8f53e0fd30b628a8624493f8cbdd21505813235601b7992b158a15554ac6fe70add2215329d1b5
7
+ data.tar.gz: f0da1fb7199421a2ddc9e940d827e264535dcc08690678dca4e07421a35a92c133c46d8f0a96471b232b2b2b476166ecfe2dc55ec80ecf065b0f06a0912816f3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.1 — 2026-06-04
4
+
5
+ First-run UX fixes for `boxd-dev`:
6
+
7
+ - Top-level rescue prints a clear "Run `boxd login`" message instead of a
8
+ stack trace when the user isn't authenticated.
9
+ - Auto-creates the golden VM if it doesn't exist yet, so `boxd-dev owner/repo`
10
+ works on a fresh boxd account with no prior setup.
11
+ - Bundles the per-repo bootstrap script inside the gem (`lib/boxd/dev_bootstrap.sh`)
12
+ and uploads it to each fork at runtime — no dependency on a pre-baked golden.
13
+ - Better handling of missing/unauthenticated `gh` CLI: skip the preflight
14
+ check instead of failing, and tell the user how to get the better errors back.
15
+
3
16
  ## 0.1.0 — 2026-06-04
4
17
 
5
18
  Initial release. CLI-backed v0.
data/boxd.gemspec CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.files = Dir[
34
34
  "lib/**/*.rb",
35
+ "lib/boxd/dev_bootstrap.sh",
35
36
  "bin/boxd-dev",
36
37
  "README.md",
37
38
  "LICENSE",
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env bash
2
+ # Per-fork bootstrap. Uploaded by the boxd-dev binary every time it runs,
3
+ # so the script always tracks the gem's version. Reads REPO_URL and
4
+ # REPO_NAME from the environment.
5
+
6
+ set -e
7
+ echo "[bootstrap] $(date +%T) starting"
8
+ cd ~
9
+
10
+ if [ -n "${REPO_URL:-}" ] && [ -n "${REPO_NAME:-}" ] && [ ! -d "$REPO_NAME" ]; then
11
+ echo "[bootstrap] cloning $REPO_URL"
12
+ git clone "$REPO_URL"
13
+ fi
14
+ [ -n "${REPO_NAME:-}" ] && cd "$REPO_NAME" || exit 0
15
+
16
+ # Prefer the project's own setup script if it ships one.
17
+ for s in script/bootstrap script/setup bin/setup; do
18
+ if [ -x "$s" ]; then
19
+ echo "[bootstrap] running $s"
20
+ "$s"
21
+ echo "[bootstrap] done."
22
+ exit 0
23
+ fi
24
+ done
25
+
26
+ # Ecosystem-default install per detected manifest.
27
+ if [ -f package.json ]; then
28
+ if [ -f pnpm-lock.yaml ]; then
29
+ command -v pnpm >/dev/null || sudo npm i -g pnpm
30
+ pnpm install
31
+ elif [ -f yarn.lock ]; then
32
+ command -v yarn >/dev/null || sudo npm i -g yarn
33
+ yarn install
34
+ else
35
+ npm install
36
+ fi
37
+ fi
38
+ if [ -f Cargo.toml ]; then
39
+ if ! command -v cargo >/dev/null; then
40
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
41
+ | sh -s -- -y --default-toolchain stable --profile minimal
42
+ fi
43
+ . "$HOME/.cargo/env" 2>/dev/null || true
44
+ cargo fetch
45
+ fi
46
+ if [ -f mix.exs ]; then
47
+ if ! command -v mix >/dev/null; then
48
+ sudo apt-get update -qq && sudo apt-get install -y elixir
49
+ fi
50
+ mix local.hex --force && mix local.rebar --force
51
+ mix deps.get
52
+ fi
53
+ if [ -f Gemfile ]; then
54
+ if ! command -v bundle >/dev/null; then
55
+ sudo apt-get update -qq && sudo apt-get install -y ruby ruby-bundler
56
+ fi
57
+ bundle install
58
+ fi
59
+ if [ -f go.mod ] && command -v go >/dev/null; then
60
+ go mod download
61
+ fi
62
+ if [ -f pyproject.toml ] || [ -f requirements.txt ]; then
63
+ if ! command -v uv >/dev/null; then
64
+ curl -LsSf https://astral.sh/uv/install.sh | sh
65
+ fi
66
+ export PATH="$HOME/.local/bin:$PATH"
67
+ if [ -f pyproject.toml ]; then
68
+ uv sync || true
69
+ else
70
+ uv pip install -r requirements.txt || pip install -r requirements.txt
71
+ fi
72
+ fi
73
+ echo "[bootstrap] done."
@@ -20,15 +20,36 @@ module Boxd
20
20
  # <bare VM name> # connect to existing
21
21
  class DevCommand
22
22
  GOLDEN_DEFAULT = "dev-golden"
23
- BOOTSTRAP_PATH = "/usr/local/bin/dev-bootstrap"
23
+ BOOTSTRAP_LOCAL = File.expand_path("dev_bootstrap.sh", __dir__)
24
+ BOOTSTRAP_REMOTE = "/tmp/dev-bootstrap"
24
25
 
25
26
  def initialize(argv)
26
27
  @argv = argv
27
28
  end
28
29
 
29
30
  def run
30
- arg = @argv.first || ENV["BOXD_DEV_VM"] || "dev-chad"
31
+ do_run
32
+ rescue Boxd::CLIMissingError => e
33
+ warn e.message
34
+ exit 1
35
+ rescue Boxd::AuthenticationError
36
+ warn <<~MSG
37
+ boxd-dev: you're not logged in to boxd yet.
38
+
39
+ Run: boxd login
40
+
41
+ (or set BOXD_TOKEN to a long-lived API key from `boxd keys create`)
42
+ MSG
43
+ exit 1
44
+ rescue Boxd::Error => e
45
+ warn "boxd-dev: #{e.message}"
46
+ exit 1
47
+ end
48
+
49
+ private
31
50
 
51
+ def do_run
52
+ arg = @argv.first || ENV["BOXD_DEV_VM"] || "dev-chad"
32
53
  repo = parse_repo(arg)
33
54
  vm = repo ? "dev-#{repo[:slug]}" : arg
34
55
  golden = ENV.fetch("BOXD_GOLDEN", GOLDEN_DEFAULT)
@@ -41,8 +62,6 @@ module Boxd
41
62
  exec_attach(box)
42
63
  end
43
64
 
44
- private
45
-
46
65
  # ---- repo reference parsing ------------------------------------------
47
66
 
48
67
  def parse_repo(arg)
@@ -76,7 +95,14 @@ module Boxd
76
95
  return unless repo[:host] == "github.com"
77
96
 
78
97
  unless system("command -v gh > /dev/null 2>&1")
79
- warn "boxd-dev: gh CLI not found; skipping repo existence check"
98
+ warn "boxd-dev: gh CLI not installed; skipping repo preflight check."
99
+ warn " install for better errors: brew install gh && gh auth login"
100
+ return
101
+ end
102
+
103
+ unless system("gh auth status > /dev/null 2>&1")
104
+ warn "boxd-dev: gh not authenticated; skipping repo preflight check."
105
+ warn " authenticate for better errors: gh auth login"
80
106
  return
81
107
  end
82
108
 
@@ -101,8 +127,9 @@ module Boxd
101
127
  end
102
128
 
103
129
  unless compute.boxes.find(golden)
104
- warn "boxd-dev: golden VM '#{golden}' is missing (set BOXD_GOLDEN to override)"
105
- exit 1
130
+ warn "boxd-dev: golden VM '#{golden}' doesn't exist yet creating it..."
131
+ compute.boxes.create(name: golden, auto_suspend_timeout: 0)
132
+ warn "boxd-dev: created #{golden} (vanilla VM; bake setup into it later if you want)."
106
133
  end
107
134
 
108
135
  warn "boxd-dev: forking #{golden} → #{vm} (#{repo[:display]})..."
@@ -112,9 +139,15 @@ module Boxd
112
139
  # ---- tmux + bootstrap ------------------------------------------------
113
140
 
114
141
  # Ensure the persistent tmux session "dev" exists on the box. If a
115
- # repo arg was given and the clone isn't there yet, kick off the
116
- # bootstrap script in pane 0 so the attaching shell sees the build live.
142
+ # repo arg was given and the clone isn't there yet, upload the bundled
143
+ # bootstrap script and kick it off inside pane 0 the attaching shell
144
+ # shows the build live and lands at a shell in the repo dir.
117
145
  def prep_tmux(box, repo)
146
+ # Upload the gem's bootstrap script on every run so it always tracks the
147
+ # gem version (cheap idempotent write).
148
+ box.write_file(BOOTSTRAP_REMOTE, File.read(BOOTSTRAP_LOCAL))
149
+ box.exec(["chmod", "+x", BOOTSTRAP_REMOTE])
150
+
118
151
  script = +<<~SH
119
152
  set -e
120
153
  if ! tmux has-session -t dev 2>/dev/null; then
@@ -124,7 +157,7 @@ module Boxd
124
157
  if repo
125
158
  script << <<~SH
126
159
  if [ ! -d "$HOME/#{repo[:repo]}" ]; then
127
- tmux send-keys -t dev "REPO_URL='#{repo[:clone_url]}' REPO_NAME='#{repo[:repo]}' #{BOOTSTRAP_PATH} && cd ~/#{repo[:repo]}" Enter
160
+ tmux send-keys -t dev "REPO_URL='#{repo[:clone_url]}' REPO_NAME='#{repo[:repo]}' #{BOOTSTRAP_REMOTE} && cd ~/#{repo[:repo]}" Enter
128
161
  else
129
162
  tmux send-keys -t dev "cd ~/#{repo[:repo]}" Enter
130
163
  fi
data/lib/boxd/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Boxd
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boxd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - boxd contributors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-04 00:00:00.000000000 Z
11
+ date: 2026-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -62,6 +62,7 @@ files:
62
62
  - lib/boxd/box_service.rb
63
63
  - lib/boxd/cli_backend.rb
64
64
  - lib/boxd/compute.rb
65
+ - lib/boxd/dev_bootstrap.sh
65
66
  - lib/boxd/dev_command.rb
66
67
  - lib/boxd/errors.rb
67
68
  - lib/boxd/version.rb