feat: add installation scripts for cross-platform setup

- Add Makefile for make-based workflow
- Add setup.sh / setup.bat for one-command bootstrap
- Add scripts/install-deps.sh for macOS/Linux dependencies
- Add scripts/install-deps.ps1 for Windows (Chocolatey)
- Add scripts/install-core.sh to build/download core CLI
- Add scripts/install-core.ps1 for Windows
- Update README with installation instructions

Developers can now run:
  macOS/Linux: ./setup.sh (or make setup)
  Windows: .\setup.bat (as Admin)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Snider 2026-01-28 14:57:30 +00:00
parent 71e8c1b2ef
commit 64bf2e281e
8 changed files with 660 additions and 5 deletions

50
Makefile Normal file
View file

@ -0,0 +1,50 @@
# Host UK Developer Workspace
# Run `make setup` to bootstrap your environment
CORE_REPO := github.com/Snider/Core
CORE_VERSION := latest
INSTALL_DIR := $(HOME)/.local/bin
.PHONY: all setup install-deps install-go install-core doctor clean help
all: help
help:
@echo "Host UK Developer Workspace"
@echo ""
@echo "Usage:"
@echo " make setup Full setup (deps + core + clone repos)"
@echo " make install-deps Install system dependencies (go, gh, etc)"
@echo " make install-core Build and install core CLI"
@echo " make doctor Check environment health"
@echo " make clone Clone all repos into packages/"
@echo " make clean Remove built artifacts"
@echo ""
@echo "Quick start:"
@echo " make setup"
setup: install-deps install-core doctor clone
@echo ""
@echo "Setup complete! Run 'core health' to verify."
install-deps:
@echo "Installing dependencies..."
@./scripts/install-deps.sh
install-go:
@echo "Installing Go..."
@./scripts/install-go.sh
install-core:
@echo "Installing core CLI..."
@./scripts/install-core.sh
doctor:
@core doctor || echo "Run 'make install-core' first if core is not found"
clone:
@core setup || echo "Run 'make install-core' first if core is not found"
clean:
@rm -rf ./build
@echo "Cleaned build artifacts"

View file

@ -4,22 +4,38 @@ This repository bootstraps a complete Host UK development environment.
## Quick Start ## Quick Start
### One-liner (macOS/Linux)
```bash
git clone git@github.com:host-uk/core-devops.git && cd core-devops && make setup
```
### Step by step
```bash ```bash
# 1. Clone this repo # 1. Clone this repo
git clone git@github.com:host-uk/core-devops.git git clone git@github.com:host-uk/core-devops.git
cd core-devops cd core-devops
# 2. Check your environment # 2. Install dependencies and core CLI
core doctor make setup
# 3. Clone all packages # Or manually:
core setup ./scripts/install-deps.sh # Install go, gh, php, node, etc.
./scripts/install-core.sh # Build and install core CLI
# 4. Start developing # 3. Start developing
cd packages/core-php cd packages/core-php
composer install composer install
``` ```
### Windows (PowerShell as Admin)
```powershell
git clone git@github.com:host-uk/core-devops.git
cd core-devops
.\scripts\install-deps.ps1 # Install via Chocolatey
.\scripts\install-core.ps1 # Build and install core CLI
core setup # Clone all repos
```
## Prerequisites ## Prerequisites
Run `core doctor` to check your environment. You'll need: Run `core doctor` to check your environment. You'll need:

98
scripts/install-core.ps1 Normal file
View file

@ -0,0 +1,98 @@
# Install the Core CLI (Windows)
# Run: .\scripts\install-core.ps1
$ErrorActionPreference = "Stop"
$Repo = "Snider/Core"
$InstallDir = "$env:LOCALAPPDATA\Programs\core"
function Write-Info { Write-Host "[INFO] $args" -ForegroundColor Green }
function Write-Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow }
function Write-Err { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 }
function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
# Download pre-built binary
function Download-Binary {
$arch = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" }
$url = "https://github.com/$Repo/releases/latest/download/core-windows-$arch.exe"
Write-Info "Attempting to download pre-built binary..."
Write-Info "URL: $url"
try {
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
Invoke-WebRequest -Uri $url -OutFile "$InstallDir\core.exe" -UseBasicParsing
Write-Info "Downloaded to $InstallDir\core.exe"
return $true
} catch {
Write-Warn "No pre-built binary available, will build from source"
return $false
}
}
# Build from source
function Build-FromSource {
if (-not (Test-Command go)) {
Write-Err "Go is required to build from source. Run '.\scripts\install-deps.ps1' first"
}
$tmpdir = New-TemporaryFile | ForEach-Object { Remove-Item $_; New-Item -ItemType Directory -Path $_ }
Write-Info "Cloning $Repo..."
git clone --depth 1 "https://github.com/$Repo.git" "$tmpdir\Core"
Write-Info "Building core CLI..."
Push-Location "$tmpdir\Core"
go build -o core.exe ./cmd/core
Pop-Location
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
Move-Item "$tmpdir\Core\core.exe" "$InstallDir\core.exe" -Force
Remove-Item -Recurse -Force $tmpdir
Write-Info "Built and installed to $InstallDir\core.exe"
}
# Add to PATH
function Setup-Path {
$userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
if ($userPath -notlike "*$InstallDir*") {
Write-Info "Adding $InstallDir to PATH..."
[Environment]::SetEnvironmentVariable("PATH", "$userPath;$InstallDir", "User")
$env:PATH = "$env:PATH;$InstallDir"
}
}
# Verify installation
function Verify {
Setup-Path
if (Test-Command core) {
Write-Info "Verifying installation..."
& core --help | Select-Object -First 5
Write-Host ""
Write-Info "core CLI installed successfully!"
} elseif (Test-Path "$InstallDir\core.exe") {
Write-Info "core CLI installed to $InstallDir\core.exe"
Write-Info "Restart your terminal to use 'core' command"
} else {
Write-Err "Installation failed"
}
}
# Main
function Main {
Write-Info "Installing Core CLI..."
# Try download first, fallback to build
if (-not (Download-Binary)) {
Build-FromSource
}
Verify
}
Main

139
scripts/install-core.sh Executable file
View file

@ -0,0 +1,139 @@
#!/usr/bin/env bash
set -e
# Install the Core CLI
# Either downloads a pre-built binary or builds from source
REPO="Snider/Core"
INSTALL_DIR="${INSTALL_DIR:-$HOME/.local/bin}"
BUILD_FROM_SOURCE="${BUILD_FROM_SOURCE:-auto}"
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
has() {
command -v "$1" &> /dev/null
}
detect_arch() {
case "$(uname -m)" in
x86_64|amd64) echo "amd64" ;;
arm64|aarch64) echo "arm64" ;;
*) echo "unknown" ;;
esac
}
detect_os() {
case "$(uname -s)" in
Darwin*) echo "darwin" ;;
Linux*) echo "linux" ;;
MINGW*|MSYS*|CYGWIN*) echo "windows" ;;
*) echo "unknown" ;;
esac
}
# Try to download pre-built binary
download_binary() {
local os=$(detect_os)
local arch=$(detect_arch)
local url="https://github.com/$REPO/releases/latest/download/core-${os}-${arch}"
if [[ "$os" == "windows" ]]; then
url="${url}.exe"
fi
info "Attempting to download pre-built binary..."
info "URL: $url"
if curl -fsSL -o /tmp/core "$url" 2>/dev/null; then
chmod +x /tmp/core
mkdir -p "$INSTALL_DIR"
mv /tmp/core "$INSTALL_DIR/core"
info "Downloaded to $INSTALL_DIR/core"
return 0
else
warn "No pre-built binary available, will build from source"
return 1
fi
}
# Build from source
build_from_source() {
if ! has go; then
error "Go is required to build from source. Run './scripts/install-deps.sh' first"
fi
local tmpdir=$(mktemp -d)
info "Cloning $REPO..."
git clone --depth 1 "https://github.com/$REPO.git" "$tmpdir/Core"
info "Building core CLI..."
cd "$tmpdir/Core"
go build -o core ./cmd/core
mkdir -p "$INSTALL_DIR"
mv core "$INSTALL_DIR/core"
rm -rf "$tmpdir"
info "Built and installed to $INSTALL_DIR/core"
}
# Add to PATH if needed
setup_path() {
if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
warn "$INSTALL_DIR is not in your PATH"
echo ""
echo "Add this to your shell profile (~/.bashrc, ~/.zshrc, etc.):"
echo ""
echo " export PATH=\"\$PATH:$INSTALL_DIR\""
echo ""
# Try to add to current session
export PATH="$PATH:$INSTALL_DIR"
fi
}
# Verify installation
verify() {
if has core; then
info "Verifying installation..."
core --help | head -5
echo ""
info "core CLI installed successfully!"
else
setup_path
if [[ -f "$INSTALL_DIR/core" ]]; then
info "core CLI installed to $INSTALL_DIR/core"
info "Restart your shell or run: export PATH=\"\$PATH:$INSTALL_DIR\""
else
error "Installation failed"
fi
fi
}
main() {
info "Installing Core CLI..."
mkdir -p "$INSTALL_DIR"
# Try download first, fallback to build
if [[ "$BUILD_FROM_SOURCE" == "true" ]]; then
build_from_source
elif [[ "$BUILD_FROM_SOURCE" == "false" ]]; then
download_binary || error "Download failed and BUILD_FROM_SOURCE=false"
else
# auto: try download, fallback to build
download_binary || build_from_source
fi
setup_path
verify
}
main "$@"

82
scripts/install-deps.ps1 Normal file
View file

@ -0,0 +1,82 @@
# Install system dependencies for Host UK development (Windows)
# Run: .\scripts\install-deps.ps1
$ErrorActionPreference = "Stop"
function Write-Info { Write-Host "[INFO] $args" -ForegroundColor Green }
function Write-Warn { Write-Host "[WARN] $args" -ForegroundColor Yellow }
function Write-Err { Write-Host "[ERROR] $args" -ForegroundColor Red; exit 1 }
function Test-Command($cmd) {
return [bool](Get-Command $cmd -ErrorAction SilentlyContinue)
}
# Install Chocolatey if not present
function Install-Chocolatey {
if (Test-Command choco) {
Write-Info "Chocolatey already installed"
return
}
Write-Info "Installing Chocolatey..."
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
# Refresh PATH
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")
}
# Install a package via Chocolatey
function Install-ChocoPackage($pkg, $cmd = $pkg) {
if (Test-Command $cmd) {
Write-Info "$pkg already installed"
} else {
Write-Info "Installing $pkg..."
choco install $pkg -y
# Refresh PATH
$env:PATH = [System.Environment]::GetEnvironmentVariable("PATH", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("PATH", "User")
}
}
# Main setup
function Main {
Write-Info "Setting up Windows development environment..."
# Check if running as admin
$isAdmin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Err "Please run this script as Administrator"
}
Install-Chocolatey
# Core tools
Install-ChocoPackage "git"
Install-ChocoPackage "gh"
Install-ChocoPackage "golang" "go"
# PHP development
Install-ChocoPackage "php"
Install-ChocoPackage "composer"
# Node development
Install-ChocoPackage "nodejs" "node"
# pnpm via npm
if (-not (Test-Command pnpm)) {
Write-Info "Installing pnpm..."
npm install -g pnpm
}
# Optional: Docker Desktop
if (-not (Test-Command docker)) {
Write-Warn "Docker not installed. Install Docker Desktop manually if needed."
}
Write-Info "Dependencies installed!"
Write-Host ""
Write-Host "Next: Run '.\scripts\install-core.ps1' to install the core CLI"
}
Main

191
scripts/install-deps.sh Executable file
View file

@ -0,0 +1,191 @@
#!/usr/bin/env bash
set -e
# Install system dependencies for Host UK development
# Supports: macOS (brew), Linux (apt/dnf), Windows (choco via WSL)
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
info() { echo -e "${GREEN}[INFO]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
# Detect OS
detect_os() {
case "$(uname -s)" in
Darwin*) echo "macos" ;;
Linux*) echo "linux" ;;
MINGW*|MSYS*|CYGWIN*) echo "windows" ;;
*) echo "unknown" ;;
esac
}
# Check if command exists
has() {
command -v "$1" &> /dev/null
}
# Install Homebrew (macOS/Linux)
install_brew() {
if has brew; then
info "Homebrew already installed"
return
fi
info "Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add to PATH for this session
if [[ -f /opt/homebrew/bin/brew ]]; then
eval "$(/opt/homebrew/bin/brew shellenv)"
elif [[ -f /home/linuxbrew/.linuxbrew/bin/brew ]]; then
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
fi
}
# Install packages via brew
brew_install() {
local pkg=$1
if has "$pkg"; then
info "$pkg already installed"
else
info "Installing $pkg..."
brew install "$pkg"
fi
}
# Install packages via apt
apt_install() {
local pkg=$1
if has "$pkg"; then
info "$pkg already installed"
else
info "Installing $pkg..."
sudo apt-get update -qq
sudo apt-get install -y "$pkg"
fi
}
# macOS setup
setup_macos() {
info "Setting up macOS environment..."
install_brew
brew_install git
brew_install gh
brew_install go
brew_install php
brew_install composer
brew_install node
brew_install pnpm
# Optional
if ! has docker; then
warn "Docker not installed. Install Docker Desktop manually if needed."
fi
}
# Linux setup
setup_linux() {
info "Setting up Linux environment..."
# Detect package manager
if has apt-get; then
setup_linux_apt
elif has dnf; then
setup_linux_dnf
elif has brew; then
setup_linux_brew
else
warn "Unknown package manager. Installing Homebrew..."
install_brew
setup_linux_brew
fi
}
setup_linux_apt() {
apt_install git
apt_install gh || warn "GitHub CLI may need manual install: https://cli.github.com"
# Go
if ! has go; then
info "Installing Go..."
sudo apt-get install -y golang-go || {
# Fallback to manual install for newer version
curl -LO https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz
rm go1.22.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
}
fi
# PHP
apt_install php
# Composer
if ! has composer; then
info "Installing Composer..."
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
fi
# Node
if ! has node; then
info "Installing Node.js..."
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
fi
# pnpm
if ! has pnpm; then
info "Installing pnpm..."
npm install -g pnpm
fi
}
setup_linux_dnf() {
sudo dnf install -y git gh golang php composer nodejs
npm install -g pnpm
}
setup_linux_brew() {
install_brew
brew_install git
brew_install gh
brew_install go
brew_install php
brew_install composer
brew_install node
brew_install pnpm
}
# Windows setup (via chocolatey in PowerShell or WSL)
setup_windows() {
warn "Windows detected. Please run scripts/install-deps.ps1 in PowerShell"
warn "Or use WSL with: wsl ./scripts/install-deps.sh"
exit 1
}
# Main
main() {
local os=$(detect_os)
info "Detected OS: $os"
case "$os" in
macos) setup_macos ;;
linux) setup_linux ;;
windows) setup_windows ;;
*) error "Unsupported OS: $os" ;;
esac
info "Dependencies installed!"
echo ""
echo "Next: Run './scripts/install-core.sh' to install the core CLI"
}
main "$@"

51
setup.bat Normal file
View file

@ -0,0 +1,51 @@
@echo off
REM Quick setup script for Windows
REM Run as Administrator: .\setup.bat
echo === Host UK Developer Workspace Setup ===
echo.
REM Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo ERROR: Please run this script as Administrator
echo Right-click and select "Run as administrator"
pause
exit /b 1
)
REM Install dependencies
echo Installing dependencies...
powershell -ExecutionPolicy Bypass -File "%~dp0scripts\install-deps.ps1"
if %errorlevel% neq 0 goto :error
REM Install core CLI
echo.
echo Installing core CLI...
powershell -ExecutionPolicy Bypass -File "%~dp0scripts\install-core.ps1"
if %errorlevel% neq 0 goto :error
REM Refresh PATH
set "PATH=%PATH%;%LOCALAPPDATA%\Programs\core"
REM Run doctor
echo.
echo === Verifying environment ===
core doctor
REM Clone repos
echo.
echo === Cloning repositories ===
core setup
echo.
echo === Setup complete! ===
echo Run 'core health' to check status
pause
exit /b 0
:error
echo.
echo Setup failed! Check the error above.
pause
exit /b 1

28
setup.sh Executable file
View file

@ -0,0 +1,28 @@
#!/usr/bin/env bash
# Quick setup script - just run: ./setup.sh
set -e
cd "$(dirname "$0")"
echo "=== Host UK Developer Workspace Setup ==="
echo ""
# Install dependencies
./scripts/install-deps.sh
# Install core CLI
./scripts/install-core.sh
# Run doctor to verify
echo ""
echo "=== Verifying environment ==="
core doctor || true
# Clone repos
echo ""
echo "=== Cloning repositories ==="
core setup
echo ""
echo "=== Setup complete! ==="
echo "Run 'core health' to check status"