Update scripts to keep SOUL.md idempotent. Add release upgrade framework.
This commit is contained in:
55
bin/mosaic
55
bin/mosaic
@@ -14,6 +14,9 @@ set -euo pipefail
|
||||
# mosaic doctor [args...] Health audit
|
||||
# mosaic sync [args...] Sync skills
|
||||
# mosaic bootstrap <path> Bootstrap a repo
|
||||
# mosaic upgrade release Upgrade installed Mosaic release
|
||||
# mosaic upgrade check Check release upgrade status (no changes)
|
||||
# mosaic upgrade project [args] Upgrade project-local stale files
|
||||
|
||||
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||||
VERSION="0.1.0"
|
||||
@@ -34,7 +37,10 @@ Management:
|
||||
doctor [args...] Audit runtime state and detect drift
|
||||
sync [args...] Sync skills from canonical source
|
||||
bootstrap <path> Bootstrap a repo with Mosaic standards
|
||||
upgrade [path] Clean up stale SOUL.md/CLAUDE.md in a project
|
||||
upgrade [mode] [args] Upgrade release (default) or project files
|
||||
upgrade check Check release upgrade status (no changes)
|
||||
release-upgrade [...] Upgrade installed Mosaic release
|
||||
project-upgrade [...] Clean up stale SOUL.md/CLAUDE.md in a project
|
||||
|
||||
Options:
|
||||
-h, --help Show this help
|
||||
@@ -147,11 +153,54 @@ run_bootstrap() {
|
||||
exec "$MOSAIC_HOME/bin/mosaic-bootstrap-repo" "$@"
|
||||
}
|
||||
|
||||
run_upgrade() {
|
||||
run_release_upgrade() {
|
||||
check_mosaic_home
|
||||
exec "$MOSAIC_HOME/bin/mosaic-release-upgrade" "$@"
|
||||
}
|
||||
|
||||
run_project_upgrade() {
|
||||
check_mosaic_home
|
||||
exec "$MOSAIC_HOME/bin/mosaic-upgrade" "$@"
|
||||
}
|
||||
|
||||
run_upgrade() {
|
||||
check_mosaic_home
|
||||
|
||||
# Default: upgrade installed release
|
||||
if [[ $# -eq 0 ]]; then
|
||||
run_release_upgrade
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
release)
|
||||
shift
|
||||
run_release_upgrade "$@"
|
||||
;;
|
||||
check)
|
||||
shift
|
||||
run_release_upgrade --dry-run "$@"
|
||||
;;
|
||||
project)
|
||||
shift
|
||||
run_project_upgrade "$@"
|
||||
;;
|
||||
|
||||
# Backward compatibility for historical project-upgrade usage.
|
||||
--all|--root)
|
||||
run_project_upgrade "$@"
|
||||
;;
|
||||
--dry-run|--ref|--keep|--overwrite|-y|--yes)
|
||||
run_release_upgrade "$@"
|
||||
;;
|
||||
-*)
|
||||
run_release_upgrade "$@"
|
||||
;;
|
||||
*)
|
||||
run_project_upgrade "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Main router
|
||||
if [[ $# -eq 0 ]]; then
|
||||
usage
|
||||
@@ -170,6 +219,8 @@ case "$command" in
|
||||
sync) run_sync "$@" ;;
|
||||
bootstrap) run_bootstrap "$@" ;;
|
||||
upgrade) run_upgrade "$@" ;;
|
||||
release-upgrade) run_release_upgrade "$@" ;;
|
||||
project-upgrade) run_project_upgrade "$@" ;;
|
||||
help|-h|--help) usage ;;
|
||||
version|-v|--version) echo "mosaic $VERSION" ;;
|
||||
*)
|
||||
|
||||
124
bin/mosaic-release-upgrade
Executable file
124
bin/mosaic-release-upgrade
Executable file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# mosaic-release-upgrade — Upgrade installed Mosaic framework release.
|
||||
#
|
||||
# This re-runs the remote installer with explicit install mode controls.
|
||||
# Default behavior is safe/idempotent (keep SOUL.md + memory).
|
||||
#
|
||||
# Usage:
|
||||
# mosaic-release-upgrade
|
||||
# mosaic-release-upgrade --ref main --keep
|
||||
# mosaic-release-upgrade --ref v0.2.0 --overwrite --yes
|
||||
|
||||
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||||
REMOTE_SCRIPT_URL="${MOSAIC_REMOTE_INSTALL_URL:-https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.sh}"
|
||||
BOOTSTRAP_REF="${MOSAIC_BOOTSTRAP_REF:-main}"
|
||||
INSTALL_MODE="${MOSAIC_INSTALL_MODE:-keep}" # keep|overwrite
|
||||
YES=false
|
||||
DRY_RUN=false
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
Usage: $(basename "$0") [options]
|
||||
|
||||
Upgrade the installed Mosaic framework release.
|
||||
|
||||
Options:
|
||||
--ref <name> Bootstrap archive ref (branch/tag/commit). Default: main
|
||||
--keep Keep local files (SOUL.md, memory/) during upgrade (default)
|
||||
--overwrite Overwrite target install directory contents
|
||||
-y, --yes Skip confirmation prompt
|
||||
--dry-run Show actions without executing
|
||||
-h, --help Show this help
|
||||
USAGE
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--ref)
|
||||
[[ $# -lt 2 ]] && { echo "Missing value for --ref" >&2; exit 1; }
|
||||
BOOTSTRAP_REF="$2"
|
||||
shift 2
|
||||
;;
|
||||
--keep)
|
||||
INSTALL_MODE="keep"
|
||||
shift
|
||||
;;
|
||||
--overwrite)
|
||||
INSTALL_MODE="overwrite"
|
||||
shift
|
||||
;;
|
||||
-y|--yes)
|
||||
YES=true
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=true
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown argument: $1" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$INSTALL_MODE" in
|
||||
keep|overwrite) ;;
|
||||
*)
|
||||
echo "[mosaic-release-upgrade] Invalid install mode: $INSTALL_MODE" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
current_version="unknown"
|
||||
if [[ -x "$MOSAIC_HOME/bin/mosaic" ]]; then
|
||||
current_version="$("$MOSAIC_HOME/bin/mosaic" --version 2>/dev/null | awk '{print $2}' || true)"
|
||||
[[ -n "$current_version" ]] || current_version="unknown"
|
||||
fi
|
||||
|
||||
echo "[mosaic-release-upgrade] Current version: $current_version"
|
||||
echo "[mosaic-release-upgrade] Target ref: $BOOTSTRAP_REF"
|
||||
echo "[mosaic-release-upgrade] Install mode: $INSTALL_MODE"
|
||||
echo "[mosaic-release-upgrade] Installer URL: $REMOTE_SCRIPT_URL"
|
||||
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "[mosaic-release-upgrade] Dry run: no changes applied."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$YES" != "true" && -t 0 ]]; then
|
||||
printf "Proceed with Mosaic release upgrade? [y/N]: "
|
||||
read -r confirm
|
||||
case "${confirm:-n}" in
|
||||
y|Y|yes|YES) ;;
|
||||
*)
|
||||
echo "[mosaic-release-upgrade] Aborted."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
curl -sL "$REMOTE_SCRIPT_URL" | \
|
||||
MOSAIC_BOOTSTRAP_REF="$BOOTSTRAP_REF" \
|
||||
MOSAIC_INSTALL_MODE="$INSTALL_MODE" \
|
||||
MOSAIC_HOME="$MOSAIC_HOME" \
|
||||
sh
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
wget -qO- "$REMOTE_SCRIPT_URL" | \
|
||||
MOSAIC_BOOTSTRAP_REF="$BOOTSTRAP_REF" \
|
||||
MOSAIC_INSTALL_MODE="$INSTALL_MODE" \
|
||||
MOSAIC_HOME="$MOSAIC_HOME" \
|
||||
sh
|
||||
else
|
||||
echo "[mosaic-release-upgrade] ERROR: curl or wget required." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
65
bin/mosaic-release-upgrade.ps1
Normal file
65
bin/mosaic-release-upgrade.ps1
Normal file
@@ -0,0 +1,65 @@
|
||||
# mosaic-release-upgrade.ps1 — Upgrade installed Mosaic framework release (Windows)
|
||||
#
|
||||
# Usage:
|
||||
# mosaic-release-upgrade.ps1
|
||||
# mosaic-release-upgrade.ps1 -Ref main -Keep
|
||||
# mosaic-release-upgrade.ps1 -Ref v0.2.0 -Overwrite -Yes
|
||||
#
|
||||
param(
|
||||
[string]$Ref = $(if ($env:MOSAIC_BOOTSTRAP_REF) { $env:MOSAIC_BOOTSTRAP_REF } else { "main" }),
|
||||
[switch]$Keep,
|
||||
[switch]$Overwrite,
|
||||
[switch]$Yes,
|
||||
[switch]$DryRun
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$MosaicHome = if ($env:MOSAIC_HOME) { $env:MOSAIC_HOME } else { Join-Path $env:USERPROFILE ".config\mosaic" }
|
||||
$RemoteInstallerUrl = if ($env:MOSAIC_REMOTE_INSTALL_URL) {
|
||||
$env:MOSAIC_REMOTE_INSTALL_URL
|
||||
} else {
|
||||
"https://git.mosaicstack.dev/mosaic/bootstrap/raw/branch/main/remote-install.ps1"
|
||||
}
|
||||
|
||||
$installMode = if ($Overwrite) { "overwrite" } elseif ($Keep) { "keep" } elseif ($env:MOSAIC_INSTALL_MODE) { $env:MOSAIC_INSTALL_MODE } else { "keep" }
|
||||
if ($installMode -notin @("keep", "overwrite")) {
|
||||
Write-Host "[mosaic-release-upgrade] Invalid install mode: $installMode" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$currentVersion = "unknown"
|
||||
$mosaicCmd = Join-Path $MosaicHome "bin\mosaic.ps1"
|
||||
if (Test-Path $mosaicCmd) {
|
||||
try {
|
||||
$currentVersion = (& $mosaicCmd --version) -replace '^mosaic\s+', ''
|
||||
}
|
||||
catch {
|
||||
$currentVersion = "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "[mosaic-release-upgrade] Current version: $currentVersion"
|
||||
Write-Host "[mosaic-release-upgrade] Target ref: $Ref"
|
||||
Write-Host "[mosaic-release-upgrade] Install mode: $installMode"
|
||||
Write-Host "[mosaic-release-upgrade] Installer URL: $RemoteInstallerUrl"
|
||||
|
||||
if ($DryRun) {
|
||||
Write-Host "[mosaic-release-upgrade] Dry run: no changes applied."
|
||||
exit 0
|
||||
}
|
||||
|
||||
if (-not $Yes) {
|
||||
$confirmation = Read-Host "Proceed with Mosaic release upgrade? [y/N]"
|
||||
if ($confirmation -notin @("y", "Y", "yes", "YES")) {
|
||||
Write-Host "[mosaic-release-upgrade] Aborted."
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
$env:MOSAIC_BOOTSTRAP_REF = $Ref
|
||||
$env:MOSAIC_INSTALL_MODE = $installMode
|
||||
$env:MOSAIC_HOME = $MosaicHome
|
||||
|
||||
Invoke-RestMethod -Uri $RemoteInstallerUrl | Invoke-Expression
|
||||
|
||||
@@ -31,7 +31,10 @@ Management:
|
||||
doctor [args...] Audit runtime state and detect drift
|
||||
sync [args...] Sync skills from canonical source
|
||||
bootstrap <path> Bootstrap a repo with Mosaic standards
|
||||
upgrade [path] Clean up stale SOUL.md/CLAUDE.md in a project
|
||||
upgrade [mode] [args] Upgrade release (default) or project files
|
||||
upgrade check Check release upgrade status (no changes)
|
||||
release-upgrade [...] Upgrade installed Mosaic release
|
||||
project-upgrade [...] Clean up stale SOUL.md/CLAUDE.md in a project
|
||||
|
||||
Options:
|
||||
-h, --help Show this help
|
||||
@@ -142,6 +145,48 @@ switch ($command) {
|
||||
& (Join-Path $MosaicHome "bin\mosaic-bootstrap-repo") @remaining
|
||||
}
|
||||
"upgrade" {
|
||||
Assert-MosaicHome
|
||||
if ($remaining.Count -eq 0) {
|
||||
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1")
|
||||
break
|
||||
}
|
||||
|
||||
$mode = $remaining[0]
|
||||
$tail = if ($remaining.Count -gt 1) { $remaining[1..($remaining.Count - 1)] } else { @() }
|
||||
|
||||
switch -Regex ($mode) {
|
||||
"^release$" {
|
||||
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @tail
|
||||
}
|
||||
"^check$" {
|
||||
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") -DryRun @tail
|
||||
}
|
||||
"^project$" {
|
||||
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
||||
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @tail
|
||||
}
|
||||
"^(--all|--root)$" {
|
||||
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
||||
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
|
||||
}
|
||||
"^(--dry-run|--ref|--keep|--overwrite|-y|--yes)$" {
|
||||
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
|
||||
}
|
||||
"^-.*" {
|
||||
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
|
||||
}
|
||||
default {
|
||||
Write-Host "[mosaic] NOTE: treating positional argument as project path." -ForegroundColor Yellow
|
||||
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
||||
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
|
||||
}
|
||||
}
|
||||
}
|
||||
"release-upgrade" {
|
||||
Assert-MosaicHome
|
||||
& (Join-Path $MosaicHome "bin\mosaic-release-upgrade.ps1") @remaining
|
||||
}
|
||||
"project-upgrade" {
|
||||
Assert-MosaicHome
|
||||
Write-Host "[mosaic] NOTE: mosaic-upgrade requires bash. Use Git Bash or WSL." -ForegroundColor Yellow
|
||||
& (Join-Path $MosaicHome "bin\mosaic-upgrade") @remaining
|
||||
|
||||
Reference in New Issue
Block a user