Skip to content

feat: full cloud-init tool parity with Python provisioning#909

Merged
rysweet merged 4 commits intomainfrom
fix/cloud-init-full-tool-parity
Apr 2, 2026
Merged

feat: full cloud-init tool parity with Python provisioning#909
rysweet merged 4 commits intomainfrom
fix/cloud-init-full-tool-parity

Conversation

@rysweet
Copy link
Copy Markdown
Owner

@rysweet rysweet commented Mar 27, 2026

Summary

Adds all development tools from the Python vm_provisioning.py that were missing from the Rust cloud-init implementation. The Simard VM showed that only Rust and .NET were installed — gh, az CLI, Node.js, Claude, Go, and other tools were never provisioned.

Changes

Updates both cloud-init code paths (YAML in cloud_init.rs and shell-script in vm.rs):

  • GitHub CLI (gh) via official apt repo
  • Azure CLI via InstallAzureCLIDeb script
  • Node.js 22.x via NodeSource
  • Claude Code AI assistant
  • Go 1.21.5
  • Python 3.13 + python-is-python3
  • uv package manager
  • tmux configuration (status bar, socket permissions with dynamic UID)
  • Docker post-install (add user to docker group)
  • npm global prefix configuration
  • .bashrc PATH additions (Go, Cargo, npm)
  • Removes broken amplihack make install (target does not exist)

Merge-Ready Evidence

QA-team

  • Scenario: tests/agentic-scenarios/cloud-init-tool-parity.yaml
  • gadugi-test validate: ✅ 3/3 valid, 0 invalid
  • gadugi-test run: ✅ 3/3 passed (cloud-init-tool-parity + 2 existing scenarios)
  • Environment: local (Rust unit tests via cargo test)

Docs

Changed surfaces reviewed: cloud_init.rs, vm.rs — both are internal provisioning code with no CLI/API/config impact. No user-facing documentation changes needed.

Quality Audit (4 cycles, final clean)

  • Cycle 1 (3 findings, 3 fixed):
    • HIGH: Hardcoded "azureuser" in YAML path → parameterized default_dev_setup_commands(username)
    • MEDIUM: Hardcoded UID 1000 for tmux socket → dynamic $(id -u username)
    • LOW: Missing version verification in shell path → added
  • Cycle 2 (2 findings, 2 fixed):
    • HIGH: rustc --version ran as root but Rust installed in user homedir → su - user -c ...
    • MEDIUM: Inconsistent upgrade commands (full-upgrade vs apt-get upgrade) → standardized on apt-get upgrade
  • Cycle 3 (1 finding, 1 fixed):
    • HIGH: GPG key downloaded to predictable /tmp path → download directly to /etc/apt/keyrings/
  • Cycle 4: CLEAN — zero critical, high, or medium findings

CI

  • 10 checks passed, 0 failures
  • 1 skipped: OSSF Scorecard (conditional workflow, only runs on main)
  • Rust CI build-and-test: ✅ (both PR and push triggers)
  • Security: Bandit ✅, CodeQL ✅, GitGuardian ✅, Safety ✅

Scope

3 files changed, all directly related:

  • rust/crates/azlin-azure/src/cloud_init.rs — YAML cloud-init generator
  • rust/crates/azlin-azure/src/vm.rs — shell-script cloud-init generator
  • tests/agentic-scenarios/cloud-init-tool-parity.yaml — QA scenario

Add all development tools that were in the Python vm_provisioning.py but
missing from the Rust cloud_init implementation:

- GitHub CLI (gh) via official apt repo
- Azure CLI via InstallAzureCLIDeb script
- Node.js 22.x via NodeSource
- Claude Code AI assistant
- Go 1.24.1
- Python 3.13 + python-is-python3
- uv package manager
- tmux configuration (status bar, socket permissions)
- Docker post-install (add user to docker group)
- npm global prefix configuration
- .bashrc PATH additions (Go, Cargo, npm)

Updates both cloud-init code paths:
- cloud_init.rs: YAML-based cloud-init config (packages + runcmd)
- vm.rs: shell-script based cloud-init provisioning

Removes broken amplihack make install (target doesn't exist).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet rysweet force-pushed the fix/cloud-init-full-tool-parity branch from 5f3728b to ca546ad Compare March 27, 2026 20:19
Ryan Sweet and others added 3 commits March 27, 2026 13:24
Quality audit findings:
- default_dev_setup_commands() now takes username parameter instead of
  hardcoding 'azureuser' (HIGH: would fail for non-default usernames)
- tmux socket dir uses dynamic UID via id -u instead of hardcoded 1000
  (MEDIUM: would fail if user UID != 1000)
- Added version verification step to shell-script cloud-init path
  (matches YAML path's existing verification)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Quality audit cycle 2 findings:
- rustc --version ran as root but Rust is installed in user homedir
  (HIGH: verification always failed even when install succeeded)
- Standardize on apt-get upgrade instead of full-upgrade to match
  shell-script path and avoid unexpected package removal (MEDIUM)
- Remove unnecessary ripgrep reinstall (only needed with full-upgrade)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Quality audit cycle 3: eliminate predictable /tmp path for GitHub CLI
GPG keyring download. Download directly to /etc/apt/keyrings/ in both
cloud-init code paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rysweet rysweet merged commit 67843ae into main Apr 2, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant