Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run ShellCheck
run: find . -name '*.sh' -not -path './zsh/*' -print0 | xargs -0 shellcheck

test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Install bats-core
run: brew install bats-core
- name: Run tests
run: bats test_install.bats
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__pycache__/
*.pyc
.DS_Store
30 changes: 28 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
set -euo pipefail

REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DRY_RUN=false

# ---------------------------------------------------------------------------
# Helpers
Expand All @@ -11,6 +12,11 @@ REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
_symlink() {
local source="$1" destination="$2"

if $DRY_RUN; then
echo "DRY-RUN: Would link $source -> $destination"
return
fi

# Already linked correctly — nothing to do
if [ -L "$destination" ] && [ "$(readlink "$destination")" = "$source" ]; then
echo "INFO: Nothing to do here: $destination LGTM."
Expand All @@ -19,8 +25,10 @@ _symlink() {

# Back up existing file/symlink
if [ -e "$destination" ] || [ -L "$destination" ]; then
mv "$destination" "${destination}.orig"
echo "INFO: Created backup ${destination}.orig"
local backup
backup="${destination}.orig.$(date +%Y%m%d%H%M%S)"
mv "$destination" "$backup"
echo "INFO: Created backup $backup"
fi

ln -s "$source" "$destination"
Expand All @@ -38,6 +46,7 @@ Options:
--osx Run macOS system tweaks (osx/osx.sh)
--oh-my-zsh Install Oh-my-zsh
--claude Link Claude Code skills to ~/.claude/skills/
--dry-run Preview what would be done without making changes
--help Show this help message
EOF
}
Expand Down Expand Up @@ -67,6 +76,10 @@ do_ghostty() {

do_brew() {
echo "Working on Brew and programs.."
if $DRY_RUN; then
echo "DRY-RUN: Would install Xcode CLI tools, Homebrew, and packages from Brewfile"
return
fi
if ! xcode-select -p &>/dev/null; then
xcode-select --install
fi
Expand All @@ -78,11 +91,23 @@ do_brew() {

do_osx() {
echo "Working on osx customisations.."
if $DRY_RUN; then
echo "DRY-RUN: Would run macOS system tweaks from osx/osx.sh"
return
fi
bash "$REPO_DIR/osx/osx.sh"
}

do_oh_my_zsh() {
echo "Working on Oh-my-zsh.."
if [ -d "$HOME/.oh-my-zsh" ]; then
echo "INFO: Oh-my-zsh is already installed, skipping."
return
fi
if $DRY_RUN; then
echo "DRY-RUN: Would install Oh-my-zsh"
return
fi
curl -L https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh | sh
}

Expand All @@ -108,6 +133,7 @@ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then

for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=true ;;
--dotfiles) do_dotfiles ;;
--ghostty) do_ghostty ;;
--brew) do_brew ;;
Expand Down
23 changes: 1 addition & 22 deletions osx/osx.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env bash

set -x

#From https://mths.be/osx

# Ask for the administrator password upfront
Expand Down Expand Up @@ -420,31 +418,12 @@ defaults write com.google.Chrome.canary AppleEnableMouseSwipeNavigateWithScrolls
defaults write com.google.Chrome DisablePrintPreview -bool true
defaults write com.google.Chrome.canary DisablePrintPreview -bool true

###############################################################################
# Transmission.app #
###############################################################################

# Use `~/Documents/Torrents` to store incomplete downloads
defaults write org.m0k.transmission UseIncompleteDownloadFolder -bool true
defaults write org.m0k.transmission IncompleteDownloadFolder -string "${HOME}/Documents/Torrents"

# Don’t prompt for confirmation before downloading
defaults write org.m0k.transmission DownloadAsk -bool false

# Trash original torrent files
defaults write org.m0k.transmission DeleteOriginalTorrent -bool true

# Hide the donate message
defaults write org.m0k.transmission WarningDonate -bool false
# Hide the legal disclaimer
defaults write org.m0k.transmission WarningLegal -bool false

###############################################################################
# Kill affected applications #
###############################################################################

for app in "Activity Monitor" "cfprefsd" "Dock" "Finder" "Messages" \
"SystemUIServer" "Terminal" "Transmission" "Calendar"; do
"SystemUIServer" "Terminal" "Calendar"; do
killall "${app}" > /dev/null 2>&1
done
echo "Done. Note that some of these changes require a logout/restart to take effect."
125 changes: 118 additions & 7 deletions test_install.bats
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ setup() {

[ -L "$dest" ]
[ "$(readlink "$dest")" = "$src" ]
[ -f "${dest}.orig" ]
[ "$(cat "${dest}.orig")" = "old" ]
local backup
backup=$(ls "${dest}".orig.* 2>/dev/null)
[ -f "$backup" ]
[ "$(cat "$backup")" = "old" ]
}

@test "_symlink backs up existing wrong symlink and creates correct one" {
Expand All @@ -58,8 +60,10 @@ setup() {

[ -L "$dest" ]
[ "$(readlink "$dest")" = "$src" ]
[ -L "${dest}.orig" ]
[ "$(readlink "${dest}.orig")" = "$wrong" ]
local backup
backup=$(ls "${dest}".orig.* 2>/dev/null)
[ -L "$backup" ]
[ "$(readlink "$backup")" = "$wrong" ]
}

# --- do_dotfiles test (ported from TestProccessDotfiles) ---
Expand All @@ -86,7 +90,7 @@ setup() {

# --- backup test (ported from TestBackup) ---

@test "backup via _symlink renames file with .orig suffix" {
@test "backup via _symlink renames file with .orig timestamp suffix" {
local dest="$TEST_DIR/myfile"
local src="$TEST_DIR/newsrc"
echo "content" > "$dest"
Expand All @@ -95,6 +99,113 @@ setup() {
_symlink "$src" "$dest"

[ -L "$dest" ]
[ -f "${dest}.orig" ]
[ "$(cat "${dest}.orig")" = "content" ]
local backup
backup=$(ls "${dest}".orig.* 2>/dev/null)
[ -f "$backup" ]
[ "$(cat "$backup")" = "content" ]
}

# --- do_ghostty tests ---

@test "do_ghostty creates config directory and symlinks config" {
local fake_home="$TEST_DIR/home"
mkdir -p "$fake_home"

HOME="$fake_home"

do_ghostty

[ -d "$fake_home/.config/ghostty" ]
[ -L "$fake_home/.config/ghostty/config" ]
}

@test "do_ghostty is idempotent" {
local fake_home="$TEST_DIR/home"
mkdir -p "$fake_home"

HOME="$fake_home"

do_ghostty
run do_ghostty

[ "$status" -eq 0 ]
[[ "$output" == *"LGTM"* ]]
}

# --- do_claude tests ---

@test "do_claude symlinks skill directories" {
local fake_home="$TEST_DIR/home"
local repo="$TEST_DIR/repo"
mkdir -p "$fake_home" "$repo/claude/skills/my-skill"
echo "skill" > "$repo/claude/skills/my-skill/SKILL.md"

HOME="$fake_home"
REPO_DIR="$repo"

do_claude

[ -d "$fake_home/.claude/skills" ]
[ -L "$fake_home/.claude/skills/my-skill" ]
}

@test "do_claude is idempotent" {
local fake_home="$TEST_DIR/home"
local repo="$TEST_DIR/repo"
mkdir -p "$fake_home" "$repo/claude/skills/my-skill"
echo "skill" > "$repo/claude/skills/my-skill/SKILL.md"

HOME="$fake_home"
REPO_DIR="$repo"

do_claude
run do_claude

[ "$status" -eq 0 ]
[[ "$output" == *"LGTM"* ]]
}

# --- do_oh_my_zsh tests ---

@test "do_oh_my_zsh skips when already installed" {
local fake_home="$TEST_DIR/home"
mkdir -p "$fake_home/.oh-my-zsh"

HOME="$fake_home"

run do_oh_my_zsh

[ "$status" -eq 0 ]
[[ "$output" == *"already installed"* ]]
}

# --- dry-run tests ---

@test "dry-run mode prevents _symlink from creating links" {
local src="$TEST_DIR/source"
local dest="$TEST_DIR/dest"
echo "data" > "$src"

DRY_RUN=true
run _symlink "$src" "$dest"

[ "$status" -eq 0 ]
[[ "$output" == *"DRY-RUN"* ]]
[ ! -e "$dest" ]
}

@test "dry-run mode prevents _symlink from backing up files" {
local src="$TEST_DIR/source"
local dest="$TEST_DIR/dest"
echo "new" > "$src"
echo "old" > "$dest"

DRY_RUN=true
run _symlink "$src" "$dest"

[ "$status" -eq 0 ]
[[ "$output" == *"DRY-RUN"* ]]
# Original file should be untouched
[ -f "$dest" ]
[ "$(cat "$dest")" = "old" ]
}