diff --git a/.agents/skills/add-package/SKILL.md b/.agents/skills/add-package/SKILL.md index 8eb2217..a2daa33 100644 --- a/.agents/skills/add-package/SKILL.md +++ b/.agents/skills/add-package/SKILL.md @@ -87,14 +87,21 @@ Apply these rules in order: `.agents/skills/add-package/pkg-lookup flatpak` result's `name` field). - If only an AppImage exists from a GitHub release: set `appimage: /` and verify with `.agents/skills/add-package/pkg-lookup appimage`. -6. **Requires a Homebrew tap**: set `brew_tap: ""` (e.g., `BarutSRB/tap`). +6. **CLI tool for mise profiles (devpod-slim)**: if the tool publishes prebuilt + Linux release binaries, set `mise: "aqua:/"` (check with + `mise registry `; fall back to `github:/`), then run + `scripts/mise-lock` and commit the updated `home/.chezmoitemplates/mise-packages.lock`. + Devpods have glibc 2.36: if the release has a musl build, add + `mise_opts: { matching: "musl" }`; otherwise hold a working version with + `mise_version`. +7. **Requires a Homebrew tap**: set `brew_tap: ""` (e.g., `BarutSRB/tap`). See `omniwm` in the repo for the pattern. -7. **AUR-only Arch package**: set `pacman: ` if the AUR name differs +8. **AUR-only Arch package**: set `pacman: ` if the AUR name differs from the YAML key. Paru handles both repos. After applying these rules, you should have a minimal entry — only fields that differ from defaults. Read the schema comments at -`home/.chezmoidata/packages.yaml:9-39` if uncertain about defaults. +`home/.chezmoidata/packages.yaml:9-42` if uncertain about defaults. ### 4. Confirm tags and description @@ -145,14 +152,14 @@ Default to **No** — let them apply on their schedule. ## Schema cheatsheet -Authoritative source: `home/.chezmoidata/packages.yaml:9-39` (header comment). +Authoritative source: `home/.chezmoidata/packages.yaml:9-42` (header comment). -- Cascade order: `brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`. +- Cascade order: `mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`. - Tri-state fields (`brew`, `pacman`, `apt`, `dnf`): **absent** = use YAML key, **string** = override, **false** = exclude from this manager. - Modifiers: `brew_cask: true` flips to cask on macOS; `brew_tap: ""` preinstalls a tap. -- Opt-in: `rpm_ostree`, `flatpak`, `mas`, `appimage` are only used when the +- Opt-in: `mise`, `rpm_ostree`, `flatpak`, `mas`, `appimage` are only used when the field is present AND truthy. - Required fields: `tags`, `desc`. diff --git a/.github/workflows/devpod-linuxbrew-cache.yml b/.github/workflows/devpod-linuxbrew-cache.yml index bd3c6aa..212f9d5 100644 --- a/.github/workflows/devpod-linuxbrew-cache.yml +++ b/.github/workflows/devpod-linuxbrew-cache.yml @@ -7,6 +7,8 @@ name: Build devpod linuxbrew cache # # The build runs the full `chezmoi apply` for profile=devpod, so any chezmoi # template, package, or run_* script regression also fails this workflow. +# Pull requests build and verify the PR branch (devpod and devpod-slim) but +# never publish; only main publishes the release asset. on: schedule: @@ -20,6 +22,13 @@ on: - 'install.sh' - 'scripts/**' - '.github/workflows/devpod-linuxbrew-cache.yml' + pull_request: + paths: + - '.chezmoiroot' + - 'home/**' + - 'install.sh' + - 'scripts/**' + - '.github/workflows/devpod-linuxbrew-cache.yml' permissions: contents: write @@ -28,10 +37,14 @@ env: PLATFORM: debian12-x86_64 RELEASE_TAG: linuxbrew-cache-debian12-x86_64 ARCHIVE: linuxbrew-debian12-x86_64.tar.zst + # Branch under test: the PR head for pull requests, else the pushed/dispatched ref. + DOTFILES_REF: ${{ github.head_ref || github.ref_name }} jobs: build: name: Build linuxbrew tarball (debian:12) + # Fork PRs: their branch lives in the fork, which install.sh can't clone. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest container: image: debian:12 @@ -68,7 +81,8 @@ jobs: set -eux sudo -u builder -H \ SKIP_LINUXBREW_FETCH=1 \ - bash -lc 'cd ~ && curl -fsSL https://raw.githubusercontent.com/tyvsmith/dotfiles/main/install.sh | bash -s -- --profile devpod' + DOTFILES_REF="$DOTFILES_REF" \ + bash -lc 'cd ~ && curl -fsSL "https://raw.githubusercontent.com/tyvsmith/dotfiles/$DOTFILES_REF/install.sh" | bash -s -- --profile devpod --branch "$DOTFILES_REF"' - name: Verify brew is usable run: | @@ -85,10 +99,24 @@ jobs: set -eux sudo -u builder -H bash -lc " cd \$HOME + # Runtime-only tree: drop translations, headers, static libs, and + # doc/info pages (keep man pages, which fish also uses for + # completions), plus the prefix symlinks that point at them. tar --use-compress-program='zstd -T0 -10' \ --exclude='.linuxbrew/Caskroom' \ --exclude='.linuxbrew/var/homebrew/locks' \ --exclude='.linuxbrew/Library/Logs' \ + --exclude='.linuxbrew/Cellar/*/*/share/locale' \ + --exclude='.linuxbrew/Cellar/*/*/share/doc' \ + --exclude='.linuxbrew/Cellar/*/*/share/info' \ + --exclude='.linuxbrew/Cellar/*/*/share/gtk-doc' \ + --exclude='.linuxbrew/Cellar/*/*/include' \ + --exclude='.linuxbrew/share/locale' \ + --exclude='.linuxbrew/share/doc' \ + --exclude='.linuxbrew/share/info' \ + --exclude='.linuxbrew/share/gtk-doc' \ + --exclude='.linuxbrew/include' \ + --exclude='.linuxbrew/*.a' \ -cf /tmp/${ARCHIVE} \ .linuxbrew ls -lh /tmp/${ARCHIVE} @@ -130,10 +158,55 @@ jobs: retention-days: 7 if-no-files-found: error + devpod-slim: + name: Verify devpod-slim apply (debian:12) + # Fork PRs: their branch lives in the fork, which install.sh can't clone. + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + container: + image: debian:12 + options: --user root + steps: + - name: Install container prerequisites + run: | + set -eux + export DEBIAN_FRONTEND=noninteractive + apt-get update -qq + apt-get install -y --no-install-recommends curl ca-certificates git sudo procps file locales + locale-gen en_US.UTF-8 || true + useradd -m -s /bin/bash builder + echo 'builder ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/builder + chmod 0440 /etc/sudoers.d/builder + + - name: Apply dotfiles via install.sh (profile=devpod-slim) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eux + sudo -u builder -H DOTFILES_REF="$DOTFILES_REF" MISE_GITHUB_TOKEN="$GITHUB_TOKEN" \ + bash -lc 'cd ~ && curl -fsSL "https://raw.githubusercontent.com/tyvsmith/dotfiles/$DOTFILES_REF/install.sh" | bash -s -- --profile devpod-slim --branch "$DOTFILES_REF"' + + - name: Verify managed tools run + run: | + set -eux + sudo -u builder -H bash -lc ' + cd ~ + tools=$(sed -n "s/^\"\([^\"]*\)\" = .*/\1/p" ~/.config/mise/conf.d/20-packages.toml) + broken=0 + for d in $(~/.local/bin/mise bin-paths $tools); do + for f in "$d"/*; do + [ -f "$f" ] && [ -x "$f" ] || continue + if ldd "$f" 2>&1 | grep -q "not found"; then echo "BROKEN: $f"; broken=1; fi + done + done + ~/.local/bin/fish -c "rg --version; atuin --version; tmux -V; nvim --version | head -1" + exit $broken + ' + publish: name: Publish to GitHub Release - needs: build - if: github.event_name != 'pull_request' + needs: [build, devpod-slim] + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: write diff --git a/AGENTS.md b/AGENTS.md index 9e63558..b2609db 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,7 +50,8 @@ DOTFILES_PROFILE=arch-desktop chezmoi init Each profile (defined in `home/.chezmoidata/profiles.yaml`) fully specifies: - **`tags`**: comma-delimited category tags (`core`, `core-extra`, `container`, `dev`, `dev-extra`, `dev-toolchains`, `ai`, `experiment`, `hardware`, `ui`, `ui-extra`, `gaming`) -- **Package managers**: `brew`, `pacman`, `apt`, `dnf`, `rpm_ostree`, `flatpak` +- **Package managers**: `mise`, `brew`, `pacman`, `apt`, `dnf`, `rpm_ostree`, `flatpak` +- **`devpod`**: Uber devpod — runs the devpod bootstrap and login-shell scripts - **`work`**: work machine (system SSH agent, corporate configs) - **`decrypt`**: enable age decryption of private configs - **`backup`**: personal machine — install the restic stack and schedule backups (default off; servers/containers/Macs stay off, Macs use Time Machine) @@ -65,6 +66,7 @@ If no profile is specified, auto-detects from distro (macOS → `macos-work`, Ar | `arch-desktop` | core, core-extra, container, dev, dev-extra, dev-toolchains, experiment, ai, hardware, ui, ui-extra, gaming | pacman, flatpak, appimage | | yes | yes | Arch Linux desktop | | `debian-server` | core | apt | | | | Debian/Ubuntu server — CLI only | | `devpod` | core, dev, ai | brew | yes | no | | Work devpod — lean; toolchains from image/repo | +| `devpod-slim` | core, dev, ai | mise | yes | no | | Work devpod — same tools as pinned mise binaries, no Linuxbrew | | `silverblue` | core, core-extra, container, dev, dev-extra, dev-toolchains, experiment, ai, hardware, ui, ui-extra, gaming | brew, rpm_ostree, flatpak, appimage | | yes | | Silverblue/Bazzite immutable | **Package categories:** @@ -103,11 +105,21 @@ Brew modifier fields: - `brew_tap:` — Homebrew tap required before install Opt-in manager fields are present when available: +- `mise:` — mise backend spec (`aqua:owner/repo` preferred, `github:owner/repo` when aqua lacks it); installs a prebuilt release binary - `rpm_ostree:` — rpm-ostree package (`true` = use YAML key, string = override name; for immutable Fedora) - `flatpak:` — Flatpak app ID - `appimage:` — GitHub repo (`owner/name`) for AppImage download -Cascade order: `brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`. Each package goes to the first enabled manager that can handle it, determined at template time by `home/.chezmoitemplates/cascade-filter`. Each manager has its own `run_onchange_*` script with a profile guard that renders to `exit 0` when the manager is not enabled. +Cascade order: `mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage`. Each package goes to the first enabled manager that can handle it, determined at template time by `home/.chezmoitemplates/cascade-filter`. Each manager has its own `run_onchange_*` script with a profile guard that renders to `exit 0` when the manager is not enabled. + +**mise packages (`devpod-slim`):** +Profiles with `mise: true` install every package that declares a `mise:` backend as a prebuilt release binary, with no Linuxbrew. `home/dot_config/mise/conf.d/20-packages.toml.tmpl` renders them at `"latest"`; `home/.chezmoitemplates/mise-packages.lock` (committed, generated) pins each to an exact version, URL, and sha256 per platform. chezmoi merges those pins into the machine's own `~/.config/mise/mise.lock` (`home/dot_config/mise/modify_mise.lock`): it adds missing tools and takes newer repo pins, keeps versions upgraded locally, and never touches or removes entries it does not manage (toolchains, `mise use -g`). The install script runs `mise install --locked` on the managed tools. Packages without a `mise:` field (git, wget, tree, socat) come from the devpod image. + +- Add or remove a package: edit `packages.yaml`, run `scripts/mise-lock`, commit both files. +- Upgrade: `scripts/mise-lock --bump`, review the lockfile diff, commit. Machines update on the next apply. +- Local mise use is safe: `mise use -g`, toolchains, and `mise upgrade` write the same lockfile, and the merge keeps their entries. +- Devpods run Debian 12 (glibc 2.36). Some upstream gnu builds need newer glibc: pick a static build with `mise_opts: { matching: "musl" }` or hold a version line with `mise_version`. The install script warns about any managed binary `ldd` cannot resolve. +- Reset a machine's lockfile to exactly the repo's (drops stale entries, including local-only pins): `scripts/mise-lock --force-overwrite` on that machine. **Debian/Ubuntu apt availability:** The apt install script uses runtime `apt-cache` checks to determine package availability, so it works correctly across different Debian/Ubuntu versions without static exclusion lists. Packages available in Ubuntu 24.04 but missing in Debian Bookworm (e.g., eza, sd, git-delta, gping, yq, hyperfine) will be installed where available and skipped with warnings where not. @@ -145,6 +157,7 @@ Scripts use category-based numeric prefixes with gaps for future expansion: | `run_onchange_13-install-packages-apt.sh.tmpl` | Debian/Ubuntu packages via apt | | `run_onchange_14-install-packages-dnf.sh.tmpl` | Fedora packages via dnf | | `run_onchange_15-install-packages-rpm-ostree.sh.tmpl` | Immutable Fedora packages via rpm-ostree | +| `run_onchange_16-install-packages-mise.sh.tmpl` | mise packages at lockfile-pinned versions; installs a pinned mise via mise.run; links `~/.local/bin/fish` | | `run_onchange_20-configure-pacman-repos.sh.tmpl` | Splices `~/.config/pacman/custom-repos-{head,tail}.conf` into `/etc/pacman.conf` via the omarchy `pre-refresh-pacman` hook (one sudo); omarchy-only | | `run_onchange_30-install-packages-flatpak.sh.tmpl` | Flatpak GUI apps (Linux, tier 4+) | | `run_onchange_31-install-packages-appimage.sh.tmpl` | AppImage downloads (Linux, last resort) | diff --git a/home/.chezmoidata/packages.yaml b/home/.chezmoidata/packages.yaml index 3391cdd..3e6008b 100644 --- a/home/.chezmoidata/packages.yaml +++ b/home/.chezmoidata/packages.yaml @@ -2,7 +2,7 @@ # Package definitions — single source of truth for all platforms # ============================================================================= # -# Cascade order: brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage +# Cascade order: mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage # Each package goes to the first enabled manager that can handle it. # Cascade logic lives in .chezmoitemplates/cascade-filter. # @@ -31,6 +31,11 @@ # brew_tap: null # Homebrew tap required before install # # Opt-in manager fields (present = available, absent = N/A): +# mise: null # mise backend spec (e.g. aqua:sharkdp/bat, github:owner/repo); +# # installs a prebuilt release binary at the version pinned in +# # .chezmoitemplates/mise-packages.lock (regenerate with scripts/mise-lock) +# mise_version: "latest" # version spec for mise (e.g. "0.25" to hold a major line) +# mise_opts: null # backend options, e.g. { matching: "musl" } to pick a static build # rpm_ostree: false # true (use YAML key) or package name; immutable Fedora only # flatpak: null # Flatpak app ID (Linux GUI), or false # mas: null # Mac App Store ID @@ -45,22 +50,28 @@ packages: fish: tags: [core] desc: "Modern shell" + mise: "github:fish-shell/fish-shell" atuin: tags: [core] desc: "Magical shell history" + mise: "github:atuinsh/atuin" + mise_opts: { matching: "musl" } # gnu build needs glibc 2.38+; Debian 12 has 2.36 zoxide: tags: [core] desc: "Smarter cd command" + mise: "aqua:ajeetdsouza/zoxide" starship: tags: [core] desc: "Cross-shell prompt" + mise: "aqua:starship/starship" direnv: tags: [core] desc: "Per-directory env vars" + mise: "aqua:direnv/direnv" fastfetch: tags: [core-extra] @@ -72,6 +83,7 @@ packages: neovim: tags: [core] desc: "Hyperextensible text editor" + mise: "aqua:neovim/neovim" # =========================================================================== # Modern CLI Replacements @@ -79,52 +91,64 @@ packages: eza: tags: [core] desc: "ls replacement" + mise: "aqua:eza-community/eza" bat: tags: [core] desc: "cat replacement" + mise: "aqua:sharkdp/bat" fd: tags: [core] desc: "find replacement" + mise: "aqua:sharkdp/fd" apt: fd-find dnf: fd-find ripgrep: tags: [core] desc: "grep replacement" + mise: "aqua:BurntSushi/ripgrep" sd: tags: [core] desc: "sed replacement" + mise: "aqua:chmln/sd" dust: tags: [core] desc: "du replacement" + mise: "aqua:bootandy/dust" duf: tags: [core] desc: "df replacement" + mise: "aqua:muesli/duf" procs: tags: [core] desc: "ps replacement" + mise: "github:dalance/procs" btop: tags: [core] desc: "System resource monitor TUI" + mise: "aqua:aristocratos/btop" difftastic: tags: [dev] desc: "Structural diff tool" + mise: "aqua:Wilfred/difftastic" git-delta: tags: [core] desc: "Git pager with syntax highlighting" + mise: "aqua:dandavison/delta" gtrash: tags: [core] desc: "Trash CLI (rm replacement, XDG trash spec)" + mise: "github:umlx5h/gtrash" apt: false dnf: false @@ -140,6 +164,7 @@ packages: xh: tags: [core] desc: "curl replacement" + mise: "aqua:ducaale/xh" doggo: tags: [dev-extra] @@ -152,10 +177,13 @@ packages: tealdeer: tags: [core] desc: "tldr pages client" + mise: "aqua:tealdeer-rs/tealdeer" yazi: tags: [core] desc: "Terminal file manager" + mise: "github:sxyazi/yazi" + mise_opts: { matching: "musl" } # gnu build needs glibc 2.39+ superfile: tags: [experiment] @@ -175,15 +203,18 @@ packages: git-lfs: tags: [core] desc: "Git Large File Storage" + mise: "aqua:git-lfs/git-lfs" gh: tags: [core] desc: "GitHub CLI" + mise: "aqua:cli/cli" pacman: false # omarchy 4 provides gh as a lazy mise wrapper lazygit: tags: [core] desc: "Terminal UI for git" + mise: "aqua:jesseduffield/lazygit" # =========================================================================== # Essential Utilities @@ -191,23 +222,28 @@ packages: chezmoi: tags: [core] desc: "Dotfile manager" + mise: "aqua:twpayne/chezmoi" fzf: tags: [core] desc: "Fuzzy finder" + mise: "aqua:junegunn/fzf" jq: tags: [core] desc: "JSON processor" + mise: "aqua:jqlang/jq" yq: tags: [core] desc: "YAML processor" + mise: "aqua:mikefarah/yq" pacman: go-yq tmux: tags: [core] desc: "Terminal multiplexer" + mise: "aqua:tmux/tmux-builds" zellij: tags: [experiment] @@ -310,6 +346,7 @@ packages: uv: tags: [dev] desc: "Python package manager" + mise: "aqua:astral-sh/uv" # =========================================================================== # Build & Image Tools @@ -330,6 +367,7 @@ packages: shellcheck: tags: [dev] desc: "Shell script linter" + mise: "aqua:koalaman/shellcheck" dnf: ShellCheck tokei: @@ -351,10 +389,13 @@ packages: tree-sitter-cli: tags: [dev] desc: "Parser generator for editors" + mise: "aqua:tree-sitter/tree-sitter" + mise_version: "0.25" # 0.26+ ships only glibc 2.39+ builds, no musl usage: tags: [dev] desc: "CLI spec and completions tool" + mise: "aqua:jdx/usage" # =========================================================================== # AI Tools @@ -364,6 +405,7 @@ packages: herdr: tags: [ai] desc: "Terminal multiplexer for AI coding agents" + mise: "aqua:herdrdev/herdr" apt: false dnf: false diff --git a/home/.chezmoidata/profiles.yaml b/home/.chezmoidata/profiles.yaml index 1d32268..6ecff83 100644 --- a/home/.chezmoidata/profiles.yaml +++ b/home/.chezmoidata/profiles.yaml @@ -6,7 +6,9 @@ # desc: human-readable description (shown during profile selection) # tags: comma-delimited category tags (core, core-extra, container, dev, dev-extra, dev-toolchains, ai, experiment, hardware, ui, ui-extra, gaming) # *-extra = nice-to-have on machines you sit at; dev-toolchains = global mise runtimes (latest) -# brew/pacman/apt/dnf/rpm_ostree/flatpak/appimage: which package managers to enable +# mise/brew/pacman/apt/dnf/rpm_ostree/flatpak/appimage: which package managers to enable +# (mise installs packages that declare a `mise:` backend as pinned release binaries) +# devpod: Uber devpod — runs the devpod bootstrap and login-shell scripts # work: work machine (system SSH agent, corporate configs) # decrypt: enable age decryption of private configs # backup: personal machine — install+schedule restic backups (default false; servers/containers stay off) @@ -53,10 +55,19 @@ profiles: devpod: desc: "Work devpod (Debian) — lean CLI + dev tools via Linuxbrew; toolchains come from the image/repo" tags: core, dev, ai + devpod: true work: true brew: true decrypt: false + devpod-slim: + desc: "Work devpod (Debian) — same tools as devpod, as mise-pinned release binaries (no Linuxbrew)" + tags: core, dev, ai + devpod: true + work: true + mise: true + decrypt: false + # --- Immutable Fedora --- silverblue: desc: "Fedora Silverblue/Bazzite — immutable desktop" diff --git a/home/.chezmoiignore.tmpl b/home/.chezmoiignore.tmpl index 30b766e..9010e46 100644 --- a/home/.chezmoiignore.tmpl +++ b/home/.chezmoiignore.tmpl @@ -22,6 +22,11 @@ .local/bin/devpod-linuxbrew-fetch {{ end }} +{{ if not (get (index .profiles .profile) "mise") }} +# mise package lockfile — only profiles that install packages via mise +.config/mise/mise.lock +{{ end }} + {{ if ne .chezmoi.os "darwin" }} # macOS-only apps — skip on Linux .config/borders/ diff --git a/home/.chezmoitemplates/cascade-filter b/home/.chezmoitemplates/cascade-filter index c0d2d2f..42594ef 100644 --- a/home/.chezmoitemplates/cascade-filter +++ b/home/.chezmoitemplates/cascade-filter @@ -2,7 +2,7 @@ cascade-filter: Outputs a formatted line if the package belongs to the specified manager, with the manager-specific package name resolved. - Cascade order: brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage + Cascade order: mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage A package goes to the first enabled manager that can handle it. Native manager fields are tri-state: @@ -14,7 +14,7 @@ absent/false = brew formula (or not a brew package) true = brew cask (macOS only); name comes from brew: or YAML key - rpm_ostree/flatpak/appimage are opt-in: require their field to be present. + mise/rpm_ostree/flatpak/appimage are opt-in: require their field to be present. de field is a string match: absent = no restriction (installs on all profiles) @@ -54,6 +54,7 @@ {{- /* Opt-in managers: require their field to exist and be truthy */ -}} {{- $field_ok := true -}} +{{- if eq $mgr "mise" -}}{{- $field_ok = and (hasKey $pkg "mise") $pkg.mise -}}{{- end -}} {{- if eq $mgr "brew_cask" -}}{{- $field_ok = and (hasKey $pkg "brew_cask") $pkg.brew_cask -}}{{- end -}} {{- if eq $mgr "rpm_ostree" -}}{{- $field_ok = and (hasKey $pkg "rpm_ostree") $pkg.rpm_ostree -}}{{- end -}} {{- if eq $mgr "flatpak" -}}{{- $field_ok = and (hasKey $pkg "flatpak") $pkg.flatpak -}}{{- end -}} @@ -61,6 +62,7 @@ {{- /* Tri-state availability: profile enables manager AND field is not false absent = available (default name), string = available (override), false = excluded */ -}} +{{- $avail_mise := and (and (hasKey $p "mise") $p.mise) (and (hasKey $pkg "mise") $pkg.mise) -}} {{- $avail_brew := and (and (hasKey $p "brew") $p.brew) (or (not (hasKey $pkg "brew")) $pkg.brew) (not (and (hasKey $pkg "brew_cask") $pkg.brew_cask)) -}} {{- $avail_brew_cask := and (and (hasKey $p "brew") $p.brew) (eq $os "darwin") (and (hasKey $pkg "brew_cask") $pkg.brew_cask) (or (not (hasKey $pkg "brew")) $pkg.brew) -}} {{- $avail_pacman := and (and (hasKey $p "pacman") $p.pacman) (or (not (hasKey $pkg "pacman")) $pkg.pacman) -}} @@ -72,7 +74,8 @@ {{- /* First enabled manager wins */ -}} {{- $winner := "none" -}} -{{- if $avail_brew -}}{{- $winner = "brew" -}} +{{- if $avail_mise -}}{{- $winner = "mise" -}} +{{- else if $avail_brew -}}{{- $winner = "brew" -}} {{- else if $avail_brew_cask -}}{{- $winner = "brew_cask" -}} {{- else if $avail_pacman -}}{{- $winner = "pacman" -}} {{- else if $avail_apt -}}{{- $winner = "apt" -}} @@ -84,7 +87,9 @@ {{- if and $enabled $tags_ok $os_ok $de_ok $work_ok $decrypt_ok $backup_ok $field_ok (eq $winner $mgr) -}} {{- $resolved := $display -}} -{{- if and (eq $mgr "brew") (hasKey $pkg "brew") -}} +{{- if eq $mgr "mise" -}} +{{- $resolved = index $pkg "mise" -}} +{{- else if and (eq $mgr "brew") (hasKey $pkg "brew") -}} {{- $resolved = index $pkg "brew" -}} {{- else if and (eq $mgr "brew_cask") (hasKey $pkg "brew") -}} {{- $resolved = index $pkg "brew" -}} diff --git a/home/.chezmoitemplates/mise-packages.lock b/home/.chezmoitemplates/mise-packages.lock new file mode 100644 index 0000000..be3e390 --- /dev/null +++ b/home/.chezmoitemplates/mise-packages.lock @@ -0,0 +1,531 @@ +# @generated - this file is auto-generated by `mise lock` https://mise.jdx.dev/dev-tools/mise-lock.html + +lockfile_version = 2 + +[[tools."aqua:BurntSushi/ripgrep"]] +version = "15.2.0" +backend = "aqua:BurntSushi/ripgrep" +specifiers = ["latest"] + +[tools."aqua:BurntSushi/ripgrep"."platforms.linux-arm64"] +checksum = "sha256:a740b91c82eaf9914cfedd353572f2791cbe0162c84101ee0951058f4dcbc90d" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478119579" + +[tools."aqua:BurntSushi/ripgrep"."platforms.linux-x64"] +checksum = "sha256:33e15bcf1624b25cdd2a55813a47a2f95dbe126268203e76aa6a585d1e7b149c" +url = "https://github.com/BurntSushi/ripgrep/releases/download/15.2.0/ripgrep-15.2.0-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/BurntSushi/ripgrep/releases/assets/478120097" + +[[tools."aqua:Wilfred/difftastic"]] +version = "0.71.0" +backend = "aqua:Wilfred/difftastic" +specifiers = ["latest"] + +[tools."aqua:Wilfred/difftastic"."platforms.linux-arm64"] +checksum = "sha256:5f046098b36ff985d0f99fec6f22cf74961db60386ff9d40df39fd99660aae2c" +url = "https://github.com/Wilfred/difftastic/releases/download/0.71.0/difft-0.71.0-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/Wilfred/difftastic/releases/assets/573540796" + +[tools."aqua:Wilfred/difftastic"."platforms.linux-x64"] +checksum = "sha256:61aea5394a53c56f144637cf39b3a0c0dafa27769731745e5851ff276e6478da" +url = "https://github.com/Wilfred/difftastic/releases/download/0.71.0/difft-0.71.0-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/Wilfred/difftastic/releases/assets/573539079" + +[[tools."aqua:ajeetdsouza/zoxide"]] +version = "0.10.0" +backend = "aqua:ajeetdsouza/zoxide" +specifiers = ["latest"] + +[tools."aqua:ajeetdsouza/zoxide"."platforms.linux-arm64"] +checksum = "sha256:f1f16c5d6298d63dee467eedea1cdcd8490e43e493bea43acd416dc9033ef641" +url = "https://github.com/ajeetdsouza/zoxide/releases/download/v0.10.0/zoxide-0.10.0-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/ajeetdsouza/zoxide/releases/assets/466316402" + +[tools."aqua:ajeetdsouza/zoxide"."platforms.linux-x64"] +checksum = "sha256:2d93385b99f3e82cf2701609a1bffcad863fbeb75aa3fe7eb6be4d29be68b1ae" +url = "https://github.com/ajeetdsouza/zoxide/releases/download/v0.10.0/zoxide-0.10.0-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/ajeetdsouza/zoxide/releases/assets/466316293" + +[[tools."aqua:aristocratos/btop"]] +version = "1.4.7" +backend = "aqua:aristocratos/btop" +specifiers = ["latest"] + +[tools."aqua:aristocratos/btop"."platforms.linux-arm64"] +checksum = "sha256:6270de0ef4c84cf0eea61cb148b3ad9ae91a11e9c3309867ffc6b3751024c252" +url = "https://github.com/aristocratos/btop/releases/download/v1.4.7/btop-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/aristocratos/btop/releases/assets/409963650" + +[tools."aqua:aristocratos/btop"."platforms.linux-x64"] +checksum = "sha256:5099054dd6a101bd12eb6ff3702a9a6a3f57aaa27923a0da478ae5b517faf335" +url = "https://github.com/aristocratos/btop/releases/download/v1.4.7/btop-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/aristocratos/btop/releases/assets/409963672" + +[[tools."aqua:astral-sh/uv"]] +version = "0.12.18" +backend = "aqua:astral-sh/uv" +specifiers = ["latest"] + +[tools."aqua:astral-sh/uv"."platforms.linux-arm64"] +checksum = "sha256:afb6291f3f0a6b4521fc67b947822506c41dde5b60d2189dd8f3695b2ac8c9e7" +url = "https://github.com/astral-sh/uv/releases/download/0.12.18/uv-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/582430569" +provenance = "github-attestations" + +[tools."aqua:astral-sh/uv"."platforms.linux-x64"] +checksum = "sha256:89eadd7c76fc063887959510d5ba0ab1264dfd5f1143b925ddb73021a40acf16" +url = "https://github.com/astral-sh/uv/releases/download/0.12.18/uv-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/astral-sh/uv/releases/assets/582430671" +provenance = "github-attestations" + +[[tools."aqua:bootandy/dust"]] +version = "1.2.6" +backend = "aqua:bootandy/dust" +specifiers = ["latest"] + +[tools."aqua:bootandy/dust"."platforms.linux-arm64"] +checksum = "sha256:ec6a63bc275a33000443d444fd5424e56745aa995bc88e1080cd951e5e9e5cbf" +url = "https://github.com/bootandy/dust/releases/download/v1.2.6/dust-v1.2.6-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/bootandy/dust/releases/assets/568852461" + +[tools."aqua:bootandy/dust"."platforms.linux-x64"] +checksum = "sha256:14f788707aad217667f6812cf1a9639bf5c861a2ee815d486cffc36051f5e759" +url = "https://github.com/bootandy/dust/releases/download/v1.2.6/dust-v1.2.6-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/bootandy/dust/releases/assets/568852367" + +[[tools."aqua:chmln/sd"]] +version = "1.1.0" +backend = "aqua:chmln/sd" +specifiers = ["latest"] + +[tools."aqua:chmln/sd"."platforms.linux-arm64"] +checksum = "sha256:ec8c93c0533ff21f4851d11566808d4082544baf063d9b96ea77c27e98b7cd99" +url = "https://github.com/chmln/sd/releases/download/v1.1.0/sd-v1.1.0-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/chmln/sd/releases/assets/362325535" + +[tools."aqua:chmln/sd"."platforms.linux-x64"] +checksum = "sha256:3613eca74cd686739bb5a6d68319aa56c747e7315274d02323a2ca2b1c5d82d2" +url = "https://github.com/chmln/sd/releases/download/v1.1.0/sd-v1.1.0-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/chmln/sd/releases/assets/362325296" + +[[tools."aqua:cli/cli"]] +version = "2.101.0" +backend = "aqua:cli/cli" +specifiers = ["latest"] + +[tools."aqua:cli/cli"."platforms.linux-arm64"] +checksum = "sha256:b57e8063f18862647c9d22727c32e9da1b963f8bf9db648fe123a6975695640f" +url = "https://github.com/cli/cli/releases/download/v2.101.0/gh_2.101.0_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/565857147" +provenance = "github-attestations" + +[tools."aqua:cli/cli"."platforms.linux-x64"] +checksum = "sha256:9bca2d1c16825f109907a23307628a2f0698fbf99662b73a5cf0b020293072b8" +url = "https://github.com/cli/cli/releases/download/v2.101.0/gh_2.101.0_linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/cli/cli/releases/assets/565857134" +provenance = "github-attestations" + +[[tools."aqua:dandavison/delta"]] +version = "0.19.2" +backend = "aqua:dandavison/delta" +specifiers = ["latest"] + +[tools."aqua:dandavison/delta"."platforms.linux-arm64"] +checksum = "sha256:0bfce159a5cddd5feb3d6db4a616d883ff51253ce08ac7ec11cb1d208cfaab9e" +url = "https://github.com/dandavison/delta/releases/download/0.19.2/delta-0.19.2-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/dandavison/delta/releases/assets/383662337" + +[tools."aqua:dandavison/delta"."platforms.linux-x64"] +checksum = "sha256:8e695c5f586a8c53d6c3b01be0b4a422ed218bfed2a56191caebe373a1c18ab2" +url = "https://github.com/dandavison/delta/releases/download/0.19.2/delta-0.19.2-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/dandavison/delta/releases/assets/383662069" + +[[tools."aqua:direnv/direnv"]] +version = "2.37.1" +backend = "aqua:direnv/direnv" +specifiers = ["latest"] + +[tools."aqua:direnv/direnv"."platforms.linux-arm64"] +checksum = "sha256:2a9cef8d73521d6a3ec3f2871c4b747b8c4cc038628c1b57a7efa42b393a2d82" +url = "https://github.com/direnv/direnv/releases/download/v2.37.1/direnv.linux-arm64" +url_api = "https://api.github.com/repos/direnv/direnv/releases/assets/274610549" + +[tools."aqua:direnv/direnv"."platforms.linux-x64"] +checksum = "sha256:1f1b93dd6f38523fde26dfac96151ef9d31a374e3005cd3345fb93555ae0c9b5" +url = "https://github.com/direnv/direnv/releases/download/v2.37.1/direnv.linux-amd64" +url_api = "https://api.github.com/repos/direnv/direnv/releases/assets/274610548" + +[[tools."aqua:ducaale/xh"]] +version = "0.26.2" +backend = "aqua:ducaale/xh" +specifiers = ["latest"] + +[tools."aqua:ducaale/xh"."platforms.linux-arm64"] +checksum = "sha256:3a44900a8ac53f614aa0cd1d2e54ecf4e93584384c1ad091aa18d7992686d7eb" +url = "https://github.com/ducaale/xh/releases/download/v0.26.2/xh-v0.26.2-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/ducaale/xh/releases/assets/490411000" + +[tools."aqua:ducaale/xh"."platforms.linux-x64"] +checksum = "sha256:8c53b6a23435754f9e2ea8ab8c0d0296a1921404b88132cf9b364ff6e8c22a6e" +url = "https://github.com/ducaale/xh/releases/download/v0.26.2/xh-v0.26.2-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/ducaale/xh/releases/assets/490410371" + +[[tools."aqua:eza-community/eza"]] +version = "0.23.5" +backend = "aqua:eza-community/eza" +specifiers = ["latest"] + +[tools."aqua:eza-community/eza"."platforms.linux-arm64"] +checksum = "sha256:40b87ae8628aa2ff0f0d2dc24ab52f689631366385c3da630bae745671fd71ec" +url = "https://github.com/eza-community/eza/releases/download/v0.23.5/eza_aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/eza-community/eza/releases/assets/471228867" + +[tools."aqua:eza-community/eza"."platforms.linux-x64"] +checksum = "sha256:35c70c5c43c29108075e58b893234c67ef585f0b53a7eaf8e9e7d4eec9f339b4" +url = "https://github.com/eza-community/eza/releases/download/v0.23.5/eza_x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/eza-community/eza/releases/assets/471228887" + +[[tools."aqua:git-lfs/git-lfs"]] +version = "3.8.0" +backend = "aqua:git-lfs/git-lfs" +specifiers = ["latest"] + +[tools."aqua:git-lfs/git-lfs"."platforms.linux-arm64"] +checksum = "sha256:ac9c8efac980bb0505ead384d087e2acb6486fd8498691a2165fa174ec6118c2" +url = "https://github.com/git-lfs/git-lfs/releases/download/v3.8.0/git-lfs-linux-arm64-v3.8.0.tar.gz" +url_api = "https://api.github.com/repos/git-lfs/git-lfs/releases/assets/532993825" + +[tools."aqua:git-lfs/git-lfs"."platforms.linux-x64"] +checksum = "sha256:e455e00f15d9b95661b8d53498ffb0c3367962cf1ec73c31ab7369516cd6ab8d" +url = "https://github.com/git-lfs/git-lfs/releases/download/v3.8.0/git-lfs-linux-amd64-v3.8.0.tar.gz" +url_api = "https://api.github.com/repos/git-lfs/git-lfs/releases/assets/532993734" + +[[tools."aqua:herdrdev/herdr"]] +version = "0.9.1" +backend = "aqua:herdrdev/herdr" +specifiers = ["latest"] + +[tools."aqua:herdrdev/herdr"."platforms.linux-arm64"] +checksum = "sha256:f4ccf4de745f2cb9a39a983e9ba3703dad50ec2a58dea83026ceab721bbd8d9e" +url = "https://github.com/herdrdev/herdr/releases/download/v0.9.1/herdr-linux-aarch64" +url_api = "https://api.github.com/repos/herdrdev/herdr/releases/assets/568559680" + +[tools."aqua:herdrdev/herdr"."platforms.linux-x64"] +checksum = "sha256:2a02fed16beb651ef006e1d43f048f652ca4dc58ad053cd2d44450563d5c54b7" +url = "https://github.com/herdrdev/herdr/releases/download/v0.9.1/herdr-linux-x86_64" +url_api = "https://api.github.com/repos/herdrdev/herdr/releases/assets/568559679" + +[[tools."aqua:jdx/usage"]] +version = "6.11.1" +backend = "aqua:jdx/usage" +specifiers = ["latest"] + +[tools."aqua:jdx/usage"."platforms.linux-arm64"] +checksum = "sha256:90622145566409da24d282190ad17cc786c85d498d751543824ab62931705018" +url = "https://github.com/jdx/usage/releases/download/v6.11.1/usage-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/jdx/usage/releases/assets/584024322" + +[tools."aqua:jdx/usage"."platforms.linux-x64"] +checksum = "sha256:afa6cb0e76f88cc6392aeecf21bbcd869747d4eeb60ab84c98d6e6178edc359a" +url = "https://github.com/jdx/usage/releases/download/v6.11.1/usage-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/jdx/usage/releases/assets/584024165" + +[[tools."aqua:jesseduffield/lazygit"]] +version = "0.65.1" +backend = "aqua:jesseduffield/lazygit" +specifiers = ["latest"] + +[tools."aqua:jesseduffield/lazygit"."platforms.linux-arm64"] +checksum = "sha256:49abecdf6adf4f2dfdb11bf7b9bfada267ea523612ed809d1c6d87f6c04000a7" +url = "https://github.com/jesseduffield/lazygit/releases/download/v0.65.1/lazygit_0.65.1_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/jesseduffield/lazygit/releases/assets/560658270" + +[tools."aqua:jesseduffield/lazygit"."platforms.linux-x64"] +checksum = "sha256:02beacbcda0fa342e50ae3480ba8147307353af3fb28e1d5f790e02329c201a6" +url = "https://github.com/jesseduffield/lazygit/releases/download/v0.65.1/lazygit_0.65.1_linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/jesseduffield/lazygit/releases/assets/560658266" + +[[tools."aqua:jqlang/jq"]] +version = "1.8.2" +backend = "aqua:jqlang/jq" +specifiers = ["latest"] + +[tools."aqua:jqlang/jq"."platforms.linux-arm64"] +checksum = "sha256:8b85c817833814ddca00a144c33705546355afccf0cf39b188f3cdb48b852309" +url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-arm64" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012756" +provenance = "github-attestations" + +[tools."aqua:jqlang/jq"."platforms.linux-x64"] +checksum = "sha256:b1c22172dd303f3be49e935aa56aa48a8b7a46e0bc838b4997d3bb451495870f" +url = "https://github.com/jqlang/jq/releases/download/jq-1.8.2/jq-linux-amd64" +url_api = "https://api.github.com/repos/jqlang/jq/releases/assets/453012752" +provenance = "github-attestations" + +[[tools."aqua:junegunn/fzf"]] +version = "0.74.4" +backend = "aqua:junegunn/fzf" +specifiers = ["latest"] + +[tools."aqua:junegunn/fzf"."platforms.linux-arm64"] +checksum = "sha256:5d673b849f494f0d64ec471d8640b153ca8849e3846a31da17abdcfce8df6b46" +url = "https://github.com/junegunn/fzf/releases/download/v0.74.4/fzf-0.74.4-linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/junegunn/fzf/releases/assets/558287789" + +[tools."aqua:junegunn/fzf"."platforms.linux-x64"] +checksum = "sha256:05e6813a337cc722c3ed07e54a764b75cc5d671e2e60459db0ba696ee5fa7504" +url = "https://github.com/junegunn/fzf/releases/download/v0.74.4/fzf-0.74.4-linux_amd64.tar.gz" +url_api = "https://api.github.com/repos/junegunn/fzf/releases/assets/558287768" + +[[tools."aqua:koalaman/shellcheck"]] +version = "0.11.0" +backend = "aqua:koalaman/shellcheck" +specifiers = ["latest"] + +[tools."aqua:koalaman/shellcheck"."platforms.linux-arm64"] +checksum = "sha256:12b331c1d2db6b9eb13cfca64306b1b157a86eb69db83023e261eaa7e7c14588" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.aarch64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056934" + +[tools."aqua:koalaman/shellcheck"."platforms.linux-x64"] +checksum = "sha256:8c3be12b05d5c177a04c29e3c78ce89ac86f1595681cab149b65b97c4e227198" +url = "https://github.com/koalaman/shellcheck/releases/download/v0.11.0/shellcheck-v0.11.0.linux.x86_64.tar.xz" +url_api = "https://api.github.com/repos/koalaman/shellcheck/releases/assets/279056942" + +[[tools."aqua:mikefarah/yq"]] +version = "4.53.6" +backend = "aqua:mikefarah/yq" +specifiers = ["latest"] + +[tools."aqua:mikefarah/yq"."platforms.linux-arm64"] +checksum = "sha256:88a1016bc1d657375a35864e4f44b6f333df8ff97b559f51bba0adcb2169df09" +url = "https://github.com/mikefarah/yq/releases/download/v4.53.6/yq_linux_arm64" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/522028007" +provenance = "cosign" + +[tools."aqua:mikefarah/yq"."platforms.linux-x64"] +checksum = "sha256:c5f056448f973ae7d39b5401949648a78f2dc1947d6a8eb65be60d5c504b9385" +url = "https://github.com/mikefarah/yq/releases/download/v4.53.6/yq_linux_amd64" +url_api = "https://api.github.com/repos/mikefarah/yq/releases/assets/522028022" +provenance = "cosign" + +[[tools."aqua:muesli/duf"]] +version = "0.9.1" +backend = "aqua:muesli/duf" +specifiers = ["latest"] + +[tools."aqua:muesli/duf"."platforms.linux-arm64"] +checksum = "sha256:22ea0ad29f6610bf443aa351e600de97e47a9b380ef58316606a84bb8f595216" +url = "https://github.com/muesli/duf/releases/download/v0.9.1/duf_0.9.1_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/muesli/duf/releases/assets/291083817" + +[tools."aqua:muesli/duf"."platforms.linux-x64"] +checksum = "sha256:5add851e7062c5e56939abb664705e4d14fa2d06289490aff31d51f153832de7" +url = "https://github.com/muesli/duf/releases/download/v0.9.1/duf_0.9.1_linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/muesli/duf/releases/assets/291083805" + +[[tools."aqua:neovim/neovim"]] +version = "0.12.5" +backend = "aqua:neovim/neovim" +specifiers = ["latest"] + +[tools."aqua:neovim/neovim"."platforms.linux-arm64"] +checksum = "sha256:1aa5ca085249580ae0f91eb14f27ec0919773ff2d99a163d03f3d6c21ac29725" +url = "https://github.com/neovim/neovim/releases/download/v0.12.5/nvim-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/neovim/neovim/releases/assets/526503739" + +[tools."aqua:neovim/neovim"."platforms.linux-x64"] +checksum = "sha256:bce0f56eda1f1b1db6eee8f4133d7a38813ea07933837dd1777411ca384c6875" +url = "https://github.com/neovim/neovim/releases/download/v0.12.5/nvim-linux-x86_64.tar.gz" +url_api = "https://api.github.com/repos/neovim/neovim/releases/assets/526503737" + +[[tools."aqua:sharkdp/bat"]] +version = "0.26.1" +backend = "aqua:sharkdp/bat" +specifiers = ["latest"] + +[tools."aqua:sharkdp/bat"."platforms.linux-arm64"] +checksum = "sha256:422eb73e11c854fddd99f5ca8461c2f1d6e6dce0a2a8c3d5daade5ffcb6564aa" +url = "https://github.com/sharkdp/bat/releases/download/v0.26.1/bat-v0.26.1-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/sharkdp/bat/releases/assets/323548647" + +[tools."aqua:sharkdp/bat"."platforms.linux-x64"] +checksum = "sha256:726f04c8f576a7fd18b7634f1bbf2f915c43494c1c0f013baa3287edb0d5a2a3" +url = "https://github.com/sharkdp/bat/releases/download/v0.26.1/bat-v0.26.1-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/sharkdp/bat/releases/assets/323549181" + +[[tools."aqua:sharkdp/fd"]] +version = "10.5.0" +backend = "aqua:sharkdp/fd" +specifiers = ["latest"] + +[tools."aqua:sharkdp/fd"."platforms.linux-arm64"] +checksum = "sha256:c0ee43802e3313a317c5af2f4eabd6ba13eeedd595af9775f05e18a13ac4f52c" +url = "https://github.com/sharkdp/fd/releases/download/v10.5.0/fd-v10.5.0-aarch64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/sharkdp/fd/releases/assets/530482307" + +[tools."aqua:sharkdp/fd"."platforms.linux-x64"] +checksum = "sha256:a1259cd129636efbc3fef123525c1b49e88fe5088c012630983c310e52fdfa95" +url = "https://github.com/sharkdp/fd/releases/download/v10.5.0/fd-v10.5.0-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/sharkdp/fd/releases/assets/530481615" + +[[tools."aqua:starship/starship"]] +version = "1.26.0" +backend = "aqua:starship/starship" +specifiers = ["latest"] + +[tools."aqua:starship/starship"."platforms.linux-arm64"] +checksum = "sha256:dc30189378d2f2e287384e8a692d3f95ad1df64cf0e8c36aa9201516028aed6b" +url = "https://github.com/starship/starship/releases/download/v1.26.0/starship-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/starship/starship/releases/assets/460374586" + +[tools."aqua:starship/starship"."platforms.linux-x64"] +checksum = "sha256:321f0dd7af8340a5f2e6a8fec6538a04f617486f9ec70d878f91c09cd8deef22" +url = "https://github.com/starship/starship/releases/download/v1.26.0/starship-x86_64-unknown-linux-gnu.tar.gz" +url_api = "https://api.github.com/repos/starship/starship/releases/assets/460374620" + +[[tools."aqua:tealdeer-rs/tealdeer"]] +version = "1.9.0" +backend = "aqua:tealdeer-rs/tealdeer" +specifiers = ["latest"] + +[tools."aqua:tealdeer-rs/tealdeer"."platforms.linux-arm64"] +checksum = "sha256:a748f181c00933980cb850f4a24199c45900fc523787f6c524232a6bfc66b895" +url = "https://github.com/tealdeer-rs/tealdeer/releases/download/v1.9.0/tealdeer-linux-aarch64-musl" +url_api = "https://api.github.com/repos/tealdeer-rs/tealdeer/releases/assets/527792762" + +[tools."aqua:tealdeer-rs/tealdeer"."platforms.linux-x64"] +checksum = "sha256:dc7263b550e90c0689ea2cb434e3144469805d5dddecbb1f7fc534e1185b7408" +url = "https://github.com/tealdeer-rs/tealdeer/releases/download/v1.9.0/tealdeer-linux-x86_64-musl" +url_api = "https://api.github.com/repos/tealdeer-rs/tealdeer/releases/assets/527792725" + +[[tools."aqua:tmux/tmux-builds"]] +version = "3.7c" +backend = "aqua:tmux/tmux-builds" +specifiers = ["latest"] + +[tools."aqua:tmux/tmux-builds"."platforms.linux-arm64"] +checksum = "sha256:29dcb978da2a4b0cf6790f9e004865dac239a3ba03bbf776dddacce23d03831b" +url = "https://github.com/tmux/tmux-builds/releases/download/v3.7c/tmux-3.7c-linux-arm64.tar.gz" +url_api = "https://api.github.com/repos/tmux/tmux-builds/releases/assets/528734863" + +[tools."aqua:tmux/tmux-builds"."platforms.linux-x64"] +checksum = "sha256:cc56bd1cc873eb6089c615f0496b072385bda8a6d944069f38564a5d49c128aa" +url = "https://github.com/tmux/tmux-builds/releases/download/v3.7c/tmux-3.7c-linux-x86_64.tar.gz" +url_api = "https://api.github.com/repos/tmux/tmux-builds/releases/assets/528734864" + +[[tools."aqua:tree-sitter/tree-sitter"]] +version = "0.25.10" +backend = "aqua:tree-sitter/tree-sitter" +specifiers = ["0.25"] + +[tools."aqua:tree-sitter/tree-sitter"."platforms.linux-arm64"] +checksum = "sha256:07fbff8ae0eeb0d3e496e14fc1a30dcc730cc2c97d70e601e5357f2e51958af5" +url = "https://github.com/tree-sitter/tree-sitter/releases/download/v0.25.10/tree-sitter-linux-arm64.gz" +url_api = "https://api.github.com/repos/tree-sitter/tree-sitter/releases/assets/296134136" + +[tools."aqua:tree-sitter/tree-sitter"."platforms.linux-x64"] +checksum = "sha256:8283ddba69253c698f6e987ba0e2f9285e079c8db4d36ebe1394b5bb3a0ebdfd" +url = "https://github.com/tree-sitter/tree-sitter/releases/download/v0.25.10/tree-sitter-linux-x64.gz" +url_api = "https://api.github.com/repos/tree-sitter/tree-sitter/releases/assets/296134134" + +[[tools."aqua:twpayne/chezmoi"]] +version = "2.72.2" +backend = "aqua:twpayne/chezmoi" +specifiers = ["latest"] + +[tools."aqua:twpayne/chezmoi"."platforms.linux-arm64"] +checksum = "sha256:499925fd10804b7c1a5dc4b4a275c8935261d02a4be0c18bbd41b7747810de67" +url = "https://github.com/twpayne/chezmoi/releases/download/v2.72.2/chezmoi_2.72.2_linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/twpayne/chezmoi/releases/assets/561706486" +provenance = "cosign" + +[tools."aqua:twpayne/chezmoi"."platforms.linux-x64"] +checksum = "sha256:a2be1b8bcdf06c6f173e070bb3ddbcc52c50478fe9b57f6e6c63d15c7cff4f03" +url = "https://github.com/twpayne/chezmoi/releases/download/v2.72.2/chezmoi_2.72.2_linux-glibc_amd64.tar.gz" +url_api = "https://api.github.com/repos/twpayne/chezmoi/releases/assets/561706563" +provenance = "cosign" + +[[tools."github:atuinsh/atuin"]] +version = "18.23.0" +backend = "github:atuinsh/atuin" +specifiers = ["latest"] + +[tools."github:atuinsh/atuin".options] +matching = "musl" + +[tools."github:atuinsh/atuin"."platforms.linux-arm64"] +checksum = "sha256:faf91adc71e6b661b21ed4f486babbd7af9d17363d4276da4a0251f83c72498d" +url = "https://github.com/atuinsh/atuin/releases/download/v18.23.0/atuin-aarch64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/atuinsh/atuin/releases/assets/580134145" +provenance = "github-attestations" + +[tools."github:atuinsh/atuin"."platforms.linux-x64"] +checksum = "sha256:d1b40dd6e7cd3d823867ffe22b39a025bc420f7875926ae9ca974155378da14d" +url = "https://github.com/atuinsh/atuin/releases/download/v18.23.0/atuin-x86_64-unknown-linux-musl.tar.gz" +url_api = "https://api.github.com/repos/atuinsh/atuin/releases/assets/580134247" +provenance = "github-attestations" + +[[tools."github:dalance/procs"]] +version = "0.14.12" +backend = "github:dalance/procs" +specifiers = ["latest"] + +[tools."github:dalance/procs"."platforms.linux-arm64"] +checksum = "sha256:74b4f82acc6fe553cbd5af20ba0baac420b42bef9bb0cbb38fef14b8317d9f91" +url = "https://github.com/dalance/procs/releases/download/v0.14.12/procs-v0.14.12-aarch64-linux.zip" +url_api = "https://api.github.com/repos/dalance/procs/releases/assets/457524789" + +[tools."github:dalance/procs"."platforms.linux-x64"] +checksum = "sha256:81964faf9d5cd0e9f399d5d0954fb6fe4d4d9f7d3cbec4507633df5a45b11713" +url = "https://github.com/dalance/procs/releases/download/v0.14.12/procs-v0.14.12-x86_64-linux.zip" +url_api = "https://api.github.com/repos/dalance/procs/releases/assets/457525859" + +[[tools."github:fish-shell/fish-shell"]] +version = "4.9.3" +backend = "github:fish-shell/fish-shell" +specifiers = ["latest"] + +[tools."github:fish-shell/fish-shell"."platforms.linux-arm64"] +checksum = "sha256:57349f0111728c64b703a84e611aa97ff4d1fa8466385d64e67bd5bc3ffa49fc" +url = "https://github.com/fish-shell/fish-shell/releases/download/4.9.3/fish-4.9.3-linux-aarch64.tar.xz" +url_api = "https://api.github.com/repos/fish-shell/fish-shell/releases/assets/551107872" + +[tools."github:fish-shell/fish-shell"."platforms.linux-x64"] +checksum = "sha256:8f643d10ad1abb0ef7072764c01ceb5cf61b2d373fda400cf60f0bad69b7e095" +url = "https://github.com/fish-shell/fish-shell/releases/download/4.9.3/fish-4.9.3-linux-x86_64.tar.xz" +url_api = "https://api.github.com/repos/fish-shell/fish-shell/releases/assets/551107873" + +[[tools."github:sxyazi/yazi"]] +version = "26.9.1" +backend = "github:sxyazi/yazi" +specifiers = ["latest"] + +[tools."github:sxyazi/yazi".options] +matching = "musl" + +[tools."github:sxyazi/yazi"."platforms.linux-arm64"] +checksum = "sha256:dd569daecaae914185f295634109295ccd25c1b42b02eb89a74f651970024f2e" +url = "https://github.com/sxyazi/yazi/releases/download/v26.9.1/yazi-aarch64-unknown-linux-musl.zip" +url_api = "https://api.github.com/repos/sxyazi/yazi/releases/assets/539261411" + +[tools."github:sxyazi/yazi"."platforms.linux-x64"] +checksum = "sha256:9b9c39decccf8cb0ff53a7d637d38f8a79d93bbd0099f4ea9c619ef6bb392f5d" +url = "https://github.com/sxyazi/yazi/releases/download/v26.9.1/yazi-x86_64-unknown-linux-musl.zip" +url_api = "https://api.github.com/repos/sxyazi/yazi/releases/assets/539261404" + +[[tools."github:umlx5h/gtrash"]] +version = "0.0.6" +backend = "github:umlx5h/gtrash" +specifiers = ["latest"] + +[tools."github:umlx5h/gtrash"."platforms.linux-arm64"] +checksum = "sha256:6c0c761691227feb2aca7231c92641d7fd9cd93fdd39600be6b446b80b39fc7d" +url = "https://github.com/umlx5h/gtrash/releases/download/v0.0.6/gtrash_Linux_arm64.tar.gz" +url_api = "https://api.github.com/repos/umlx5h/gtrash/releases/assets/176947843" + +[tools."github:umlx5h/gtrash"."platforms.linux-x64"] +checksum = "sha256:40d5560dc3ed34629f198203a6cce39529e413dbcbc48d8ebe1a3b716891d965" +url = "https://github.com/umlx5h/gtrash/releases/download/v0.0.6/gtrash_Linux_x86_64.tar.gz" +url_api = "https://api.github.com/repos/umlx5h/gtrash/releases/assets/176947849" diff --git a/home/dot_config/fish/conf.d/zz_01_paths.fish.tmpl b/home/dot_config/fish/conf.d/zz_01_paths.fish.tmpl index 277f6ff..cf8eba0 100644 --- a/home/dot_config/fish/conf.d/zz_01_paths.fish.tmpl +++ b/home/dot_config/fish/conf.d/zz_01_paths.fish.tmpl @@ -17,15 +17,18 @@ end set -gx OMARCHY_PATH /usr/share/omarchy {{ end -}} +# Custom bins (before mise activation, so a mise installed to ~/.local/bin, +# as on devpod-slim, is found) +fish_add_path -a --path ~/.local/bin + # Mise - polyglot runtime version manager (Java, Python, Node, etc.) # PATH activation (not --shims): a fish_prompt hook runs `mise hook-env`, which # puts the real tool bin dirs (incl. ~/.cargo/bin) on PATH — so binaries added # by `cargo install` / `npm i -g` work without a `mise reshim`. hook-env keeps # entries added after activation (like the overrides move below) in front. -__cached_source mise activate fish - -# Custom bins -fish_add_path -a --path ~/.local/bin +# Not cached: the activate output embeds `set -gx PATH `, so a +# cached copy would replay a stale PATH snapshot into every new shell. +command -q mise; and mise activate fish | source # Override bins (Should come first on path) fish_add_path --move --path ~/.local/share/overrides/bin diff --git a/home/dot_config/mise/conf.d/20-packages.toml.tmpl b/home/dot_config/mise/conf.d/20-packages.toml.tmpl new file mode 100644 index 0000000..4dfa374 --- /dev/null +++ b/home/dot_config/mise/conf.d/20-packages.toml.tmpl @@ -0,0 +1,21 @@ +{{- $p := index .profiles .profile -}} +{{- if and (hasKey $p "mise") $p.mise -}} +# Generated from .chezmoidata/packages.yaml (packages with a `mise:` backend). +# chezmoi owns this file (`mise use -g` writes config.toml instead). Versions +# are pinned by the repo's mise-packages.lock, merged into ~/.config/mise/mise.lock. +[tools] +{{- range $key, $pkg := .packages }} +{{- $spec := includeTemplate "cascade-filter" (dict "root" $ "pkg" $pkg "key" $key "manager" "mise" "fmt" "%s%.0s") | trim }} +{{- if $spec }} +{{- $version := get $pkg "mise_version" | default "latest" }} +{{- $opts := get $pkg "mise_opts" | default dict }} +{{- if $opts }} +{{- $fields := list (printf "version = %q" $version) }} +{{- range $k, $v := $opts }}{{ $fields = append $fields (printf "%s = %q" $k (toString $v)) }}{{ end }} +{{ printf "%q" $spec }} = { {{ join ", " $fields }} } # {{ $key }} +{{- else }} +{{ printf "%q" $spec }} = {{ printf "%q" $version }} # {{ $key }} +{{- end }} +{{- end }} +{{- end }} +{{ end -}} diff --git a/home/dot_config/mise/modify_mise.lock b/home/dot_config/mise/modify_mise.lock new file mode 100644 index 0000000..4b84a79 --- /dev/null +++ b/home/dot_config/mise/modify_mise.lock @@ -0,0 +1,58 @@ +{{- /* chezmoi:modify-template */ -}} +{{- /* + Merge the repo's pinned mise packages (.chezmoitemplates/mise-packages.lock, + regenerated by scripts/mise-lock) into this machine's global mise.lock, + which mise itself also writes (toolchains, `mise use -g`, `mise upgrade`). + + Per managed tool: + - missing locally, or the repo pins a newer version -> take the repo entry + - same version but different entry (e.g. new platform) -> take the repo entry + - version spec changed in the repo (e.g. latest -> 0.25) -> take the repo entry + - local version newer under the same spec (upgraded here) -> keep local; + non-semver versions (tmux 3.7c) compare numeric prefix, then suffix + Tools the repo does not manage are never touched or removed. When nothing + changes the file is emitted byte-for-byte, so mise's formatting survives. +*/ -}} +{{- $repo := include ".chezmoitemplates/mise-packages.lock" | fromToml -}} +{{- $cur := dict -}} +{{- if .chezmoi.stdin }}{{ $cur = .chezmoi.stdin | fromToml }}{{ end -}} +{{- $tools := dict -}} +{{- if hasKey $cur "tools" }}{{ $tools = $cur.tools }}{{ end -}} +{{- $semver := `^v?[0-9]+(\.[0-9]+){0,2}([-+].*)?$` -}} +{{- $changed := false -}} +{{- range $name, $entries := $repo.tools -}} +{{- $take := true -}} +{{- if hasKey $tools $name -}} +{{- $local := index $tools $name -}} +{{- $rv := (index $entries 0).version -}} +{{- $lv := (index $local 0).version -}} +{{- $rs := get (index $entries 0) "specifiers" | toJson -}} +{{- $ls := get (index $local 0) "specifiers" | toJson -}} +{{- if eq $rv $lv -}} +{{- $take = ne (toJson $entries) (toJson $local) -}} +{{- else if ne $rs $ls -}} +{{- $take = true -}} +{{- else if and (regexMatch $semver $rv) (regexMatch $semver $lv) -}} +{{- $take = not (semverCompare (printf "> %s" $rv) $lv) -}} +{{- else -}} +{{- /* Non-semver (e.g. tmux 3.7c): compare the numeric prefix, then the suffix. */ -}} +{{- $rn := regexFind `^v?[0-9]+(\.[0-9]+){0,2}` $rv -}} +{{- $ln := regexFind `^v?[0-9]+(\.[0-9]+){0,2}` $lv -}} +{{- if and $rn $ln -}} +{{- if eq $rn $ln -}} +{{- $take = not (gt (trimPrefix $ln $lv) (trimPrefix $rn $rv)) -}} +{{- else -}} +{{- $take = not (semverCompare (printf "> %s" $rn) $ln) -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- if $take }}{{ $_ := set $tools $name $entries }}{{ $changed = true }}{{ end -}} +{{- end -}} +{{- if $changed -}} +{{- $_ := set $cur "tools" $tools -}} +{{- if not (hasKey $cur "lockfile_version") }}{{ $_ := set $cur "lockfile_version" $repo.lockfile_version }}{{ end -}} +{{- $cur | toToml -}} +{{- else -}} +{{- .chezmoi.stdin -}} +{{- end -}} diff --git a/home/dot_local/bin/executable_devpod-linuxbrew-fetch b/home/dot_local/bin/executable_devpod-linuxbrew-fetch index 2342ea7..1df8920 100644 --- a/home/dot_local/bin/executable_devpod-linuxbrew-fetch +++ b/home/dot_local/bin/executable_devpod-linuxbrew-fetch @@ -106,14 +106,6 @@ main() { ensure_zstd || return 0 - log "downloading $RELEASE_BASE/$r_archive" - local tmp="/tmp/${r_archive}" - if ! curl -fL --retry 3 --max-time 1800 -o "$tmp" "$RELEASE_BASE/$r_archive"; then - warn "download failed; skipping (brew bundle will install from scratch)" - rm -f "$tmp" - return 0 - fi - # Extract into a sibling staging dir, then swap atomically. A simple # wipe-then-extract leaves a ~30-60s window where brew binaries don't # exist; an interactive fish shell (or background atuin/starship hook) @@ -122,18 +114,34 @@ main() { local stage_parent stage_parent=$(mktemp -d -p "$HOME" .linuxbrew-stage.XXXXXX) || { warn "could not create staging dir; skipping" - rm -f "$tmp" return 0 } - log "extracting to $stage_parent" - if ! tar -C "$stage_parent" --use-compress-program="$ZSTD -d -T0" -xf "$tmp"; then - warn "extract failed; leaving existing ~/.linuxbrew in place" + # Stream download into extraction so the two overlap (~30% faster than + # download-then-extract). A mid-stream failure can't be retried by curl, + # so fall back to the download-to-file path below. + log "streaming $RELEASE_BASE/$r_archive into $stage_parent" + if ! curl -fsSL --retry 3 --max-time 1800 "$RELEASE_BASE/$r_archive" \ + | "$ZSTD" -d -T0 | tar -C "$stage_parent" -xf -; then + warn "streamed extract failed; retrying via download" rm -rf "$stage_parent" + stage_parent=$(mktemp -d -p "$HOME" .linuxbrew-stage.XXXXXX) || { + warn "could not create staging dir; skipping" + return 0 + } + local tmp="/tmp/${r_archive}" + if ! curl -fL --retry 3 --max-time 1800 -o "$tmp" "$RELEASE_BASE/$r_archive"; then + warn "download failed; skipping (brew bundle will install from scratch)" + rm -rf "$stage_parent" "$tmp" + return 0 + fi + if ! tar -C "$stage_parent" --use-compress-program="$ZSTD -d -T0" -xf "$tmp"; then + warn "extract failed; leaving existing ~/.linuxbrew in place" + rm -rf "$stage_parent" "$tmp" + return 0 + fi rm -f "$tmp" - return 0 fi - rm -f "$tmp" if [ ! -d "$stage_parent/.linuxbrew" ]; then warn "archive did not contain .linuxbrew/ at root; skipping" diff --git a/home/run_after_90-devpod-shell.sh.tmpl b/home/run_after_90-devpod-shell.sh.tmpl index 37406e2..2fba77f 100644 --- a/home/run_after_90-devpod-shell.sh.tmpl +++ b/home/run_after_90-devpod-shell.sh.tmpl @@ -1,4 +1,4 @@ -{{- if eq .profile "devpod" -}} +{{- if get (index .profiles .profile) "devpod" -}} #!/usr/bin/env bash # Devpods reset /etc/shells on restart, so re-register fish on every apply. @@ -9,7 +9,7 @@ source "${CHEZMOI_SOURCE_DIR:-$(chezmoi source-path)}/../scripts/lib/common.sh" # Find fish binary — check well-known install paths, then fall back to PATH FISH_PATH="" -for p in /home/linuxbrew/.linuxbrew/bin/fish "$HOME/.linuxbrew/bin/fish" \ +for p in /home/linuxbrew/.linuxbrew/bin/fish "$HOME/.linuxbrew/bin/fish" "$HOME/.local/bin/fish" \ /usr/local/bin/fish /usr/bin/fish; do if [[ -x "$p" ]]; then FISH_PATH="$p" diff --git a/home/run_before_00-devpod-bootstrap.sh.tmpl b/home/run_before_00-devpod-bootstrap.sh.tmpl index e616f3d..a1399f7 100644 --- a/home/run_before_00-devpod-bootstrap.sh.tmpl +++ b/home/run_before_00-devpod-bootstrap.sh.tmpl @@ -1,7 +1,9 @@ -{{- if eq .profile "devpod" -}} +{{- $p := index .profiles .profile -}} +{{- if get $p "devpod" -}} #!/usr/bin/env bash # Bootstrap devpod environment before other run_before scripts. -# Sets up Linuxbrew directory structure that brew install scripts expect. +# Brew devpods: sets up the Linuxbrew directory structure the brew install +# scripts expect. mise devpods (devpod-slim) keep everything under $HOME. set -euo pipefail @@ -10,6 +12,7 @@ source "${CHEZMOI_SOURCE_DIR:-$(chezmoi source-path)}/../scripts/lib/common.sh" log "Bootstrapping devpod environment..." +{{ if get $p "brew" -}} # Remove stale brew shims that block real Homebrew install sudo rm -f /usr/local/bin/brew /etc/homebrew/brew.no_install @@ -38,6 +41,7 @@ if [ -f "/etc/gitconfig" ]; then ln -sfn "/etc/gitconfig" /home/linuxbrew/.linuxbrew/etc/gitconfig fi +{{ end -}} # Migrate ~/.devpod directory to ~/.config/devpod so chezmoi can replace it with a symlink if [ -d "$HOME/.devpod" ] && [ ! -L "$HOME/.devpod" ]; then log "Migrating ~/.devpod to ~/.config/devpod..." diff --git a/home/run_onchange_10-install-packages-homebrew.sh.tmpl b/home/run_onchange_10-install-packages-homebrew.sh.tmpl index c43bb91..deee016 100644 --- a/home/run_onchange_10-install-packages-homebrew.sh.tmpl +++ b/home/run_onchange_10-install-packages-homebrew.sh.tmpl @@ -26,7 +26,6 @@ require_cmd brew # ============================================================================= # Install formulas via brew bundle # ============================================================================= -log "Running brew bundle (formulas)..." export HOMEBREW_NO_AUTO_UPDATE=1 BREWFILE_CONTENT=$(cat <<'BREWFILE' @@ -56,6 +55,22 @@ mas "{{ $pkg.desc }}", id: {{ $pkg.mas }} BREWFILE ) +skip_bundle="" +{{- if get $p "devpod" }} + +# The linuxbrew cache tarball is built by running this same script, and the +# Brewfile hash it stamps into the prefix rides along. When the stamp matches, +# the restored tree already equals what bundle + cleanup would produce. +BREWFILE_STAMP="$(brew --prefix)/var/dotfiles/brewfile.sha256" +brewfile_sha=$(printf '%s' "$BREWFILE_CONTENT" | sha256sum | cut -d' ' -f1) +if [[ -f "$BREWFILE_STAMP" && "$(cat "$BREWFILE_STAMP")" == "$brewfile_sha" ]]; then + log "Homebrew already matches this Brewfile; skipping brew bundle" + skip_bundle=1 +fi +{{- end }} + +if [[ -z "$skip_bundle" ]]; then +log "Running brew bundle (formulas)..." # Run brew bundle with retries (fresh Homebrew installs often have linking failures # on first pass that resolve after an explicit relink) MAX_RETRIES=3 @@ -72,14 +87,20 @@ for attempt in $(seq 1 "$MAX_RETRIES"); do done log "Homebrew formula installation complete!" -{{- if eq .profile "devpod" }} +{{- if get $p "devpod" }} # Devpod brew is fully managed by this Brewfile, so uninstall anything it no # longer lists (retagged packages, manual installs). Not safe on a Mac, where # ad-hoc `brew install`s are expected to survive. log "Removing formulas no longer in the Brewfile..." -brew bundle cleanup --force --file=- <<<"$BREWFILE_CONTENT" || log "brew bundle cleanup failed; continuing" +if brew bundle cleanup --force --file=- <<<"$BREWFILE_CONTENT"; then + mkdir -p "$(dirname "$BREWFILE_STAMP")" + printf '%s\n' "$brewfile_sha" > "$BREWFILE_STAMP" +else + log "brew bundle cleanup failed; continuing" +fi {{- end }} +fi # ============================================================================= # Disable vendor fish conf.d files we handle ourselves with caching diff --git a/home/run_onchange_16-install-packages-mise.sh.tmpl b/home/run_onchange_16-install-packages-mise.sh.tmpl new file mode 100644 index 0000000..8e530f4 --- /dev/null +++ b/home/run_onchange_16-install-packages-mise.sh.tmpl @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# Chezmoi run_onchange script: Install mise-managed packages +# +# Cascade order: mise → brew → brew_cask → pacman → apt → dnf → rpm_ostree → flatpak → appimage +# Installs every tool in ~/.config/mise/conf.d/20-packages.toml as a prebuilt +# release binary, at the version and checksum pinned in ~/.config/mise/mise.lock. +# chezmoi merges the repo's pins (.chezmoitemplates/mise-packages.lock, from +# scripts/mise-lock) into that lock without dropping local entries. +# +# packages.yaml hash: {{ include ".chezmoidata/packages.yaml" | sha256sum }} +# profiles.yaml hash: {{ include ".chezmoidata/profiles.yaml" | sha256sum }} +# mise-packages.lock hash: {{ include ".chezmoitemplates/mise-packages.lock" | sha256sum }} + +{{ $p := index .profiles .profile -}} +{{ if not (and (hasKey $p "mise") $p.mise) -}} +# Profile '{{ .profile }}' does not use mise packages — nothing to do. +exit 0 +{{ else -}} +set -euo pipefail + +# shellcheck source=/dev/null +source "${CHEZMOI_SOURCE_DIR:-$(chezmoi source-path)}/../scripts/lib/common.sh" + +log "Using profile '{{ .profile }}' — installing mise packages" + +# ============================================================================= +# Bootstrap mise itself (pinned so every machine can read the committed lock) +# ============================================================================= +MISE_VERSION="2026.9.13" +BIN_DIR="$HOME/.local/bin" +MISE="$BIN_DIR/mise" + +if [[ "$("$MISE" --version 2>/dev/null | awk '{print $1}')" != "$MISE_VERSION" ]]; then + log "Installing mise $MISE_VERSION to $MISE" + # The standard installer verifies the download against the release checksums. + curl -fsSL https://mise.run | MISE_VERSION="v$MISE_VERSION" MISE_INSTALL_PATH="$MISE" sh +fi + +export PATH="$BIN_DIR:$PATH" + +# ============================================================================= +# Install pinned packages +# ============================================================================= +# Install only the tools chezmoi declares. A bare `mise install --locked` +# would also demand lock entries for anything in an unmanaged global config +# (a stray `mise use -g`) and fail before fish is linked. --locked on the +# command, not MISE_LOCKED globally, so project configs (work monorepo) keep +# their own behavior. Run from $HOME so no project config is in scope. +cd "$HOME" +mapfile -t tools < <(sed -n 's/^"\([^"]*\)" = .*/\1/p' "$HOME/.config/mise/conf.d/20-packages.toml") +(( ${#tools[@]} )) || fail "no tools found in ~/.config/mise/conf.d/20-packages.toml" +log "Running mise install --locked (${#tools[@]} tools)..." +mise install --locked --yes "${tools[@]}" + +# Login shell needs a stable path; mise's install dir is versioned. +fish_bin="$(mise which fish 2>/dev/null || true)" +if [[ -n "$fish_bin" ]]; then + ln -sfn "$fish_bin" "$BIN_DIR/fish" + log "Linked $BIN_DIR/fish -> $fish_bin" +fi + +# Upstream gnu builds can require a newer glibc than the image ships (atuin, +# yazi, tree-sitter did); ldd reports any missing symbol version. Warn rather +# than fail so the rest of the apply (login shell, fisher) still runs. +broken=() +while IFS= read -r dir; do + for f in "$dir"/*; do + [[ -f "$f" && -x "$f" ]] || continue + ldd "$f" 2>&1 | grep -q "not found" && broken+=("${f##*/}") + done +done < <(mise bin-paths "${tools[@]}" 2>/dev/null) +if (( ${#broken[@]} )); then + warn "these binaries cannot run on this system's libc: ${broken[*]}" + warn "pick a musl build (mise_opts: { matching: \"musl\" }) or hold the version (mise_version)" +fi + +# Drop superseded versions of our tools only. A bare `mise prune` could also +# remove versions a work repo installed whose config mise isn't tracking. +# Packages removed from packages.yaml stay installed until `mise uninstall`. +mise prune --yes "${tools[@]}" || warn "mise prune failed; continuing" + +log "mise package installation complete!" +{{ end -}} diff --git a/home/run_onchange_59-configure-fish-shell.sh.tmpl b/home/run_onchange_59-configure-fish-shell.sh.tmpl index 4612246..a0a9468 100644 --- a/home/run_onchange_59-configure-fish-shell.sh.tmpl +++ b/home/run_onchange_59-configure-fish-shell.sh.tmpl @@ -11,7 +11,7 @@ source "${CHEZMOI_SOURCE_DIR:-$(chezmoi source-path)}/../scripts/lib/common.sh" FISH_PATH="" for p in /opt/homebrew/bin/fish /usr/local/bin/fish \ /home/linuxbrew/.linuxbrew/bin/fish "$HOME/.linuxbrew/bin/fish" \ - /usr/bin/fish; do + "$HOME/.local/bin/fish" /usr/bin/fish; do if [[ -x "$p" ]]; then FISH_PATH="$p" break diff --git a/home/run_onchange_60-install-fisher.sh.tmpl b/home/run_onchange_60-install-fisher.sh.tmpl index 5a097ea..c706728 100755 --- a/home/run_onchange_60-install-fisher.sh.tmpl +++ b/home/run_onchange_60-install-fisher.sh.tmpl @@ -10,6 +10,9 @@ source "${CHEZMOI_SOURCE_DIR:-$(chezmoi source-path)}/../scripts/lib/common.sh" {{ if and (hasKey $p "brew") $p.brew -}} ensure_brew_in_path {{ end -}} +{{ if and (hasKey $p "mise") $p.mise -}} +export PATH="$HOME/.local/bin:$PATH" # mise and the fish symlink +{{ end -}} require_cmd fish require_file ~/.config/fish/fish_plugins diff --git a/scripts/mise-lock b/scripts/mise-lock new file mode 100755 index 0000000..b909ae4 --- /dev/null +++ b/scripts/mise-lock @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +# mise-lock — regenerate home/.chezmoitemplates/mise-packages.lock from packages.yaml. +# +# Renders the mise package drop-in for a mise-enabled profile into a scratch +# config dir, runs `mise lock --global` there, and copies the lockfile back. +# Existing pins are kept; new packages get the current release. +# +# Usage: +# scripts/mise-lock # lock new/removed packages, keep pins +# scripts/mise-lock --bump # re-resolve every "latest" (upgrade) +# scripts/mise-lock --bump # profile defaults to devpod-slim +# scripts/mise-lock --force-overwrite +# On a mise-profile machine: replace ~/.config/mise/mise.lock with the +# repo lock (dropping stale entries), then reinstall managed packages. +# Local-only entries (toolchains, `mise use -g`) lose their pins; mise +# re-resolves them on the next install. +# +# Uses MISE_GITHUB_TOKEN, GITHUB_TOKEN, or `gh auth token` to avoid the +# 60/hour unauthenticated GitHub API limit. + +set -euo pipefail + +repo="$(cd "$(dirname "$0")/.." && pwd)" +# Fallback for plain shells on devpods, where chezmoi and mise live here. +PATH="$PATH:$HOME/.local/bin" +profile="devpod-slim" +bump=() +overwrite=0 +for arg in "$@"; do + case "$arg" in + --bump) bump=(--bump) ;; + --force-overwrite) overwrite=1 ;; + -h|--help) sed -n '2,/^$/p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;; + -*) echo "Unknown option: $arg" >&2; exit 1 ;; + *) profile="$arg" ;; + esac +done + +lock="$repo/home/.chezmoitemplates/mise-packages.lock" + +if (( overwrite )); then + # Machine-side reset; chezmoi's merge normally never removes entries. + enabled="$(chezmoi execute-template '{{ get (index .profiles .profile) "mise" }}')" + [[ "$enabled" == "true" ]] || { echo "This machine's profile does not use mise packages." >&2; exit 1; } + target="${MISE_CONFIG_DIR:-$HOME/.config/mise}/mise.lock" + cp "$lock" "$target" + echo "Replaced ${target/#$HOME/\~} with the repo lock" + mapfile -t tools < <(sed -n 's/^"\([^"]*\)" = .*/\1/p' "${MISE_CONFIG_DIR:-$HOME/.config/mise}/conf.d/20-packages.toml") + (cd "$HOME" && mise install --locked --yes "${tools[@]}") + exit 0 +fi +platforms="linux-x64,linux-arm64" +cz=(chezmoi --source "$repo") + +# Render as the target profile, not this machine's: override every profile +# property the cascade filter reads. +data="$("${cz[@]}" execute-template "{{ \$p := index .profiles \"$profile\" }}{{ if not (get \$p \"mise\") }}{{ fail \"profile $profile does not enable mise\" }}{{ end }}{{ dict \"profile\" \"$profile\" \"tags\" \$p.tags \"work\" (get \$p \"work\" | default false) \"decrypt\" (get \$p \"decrypt\" | default false) \"backup\" (get \$p \"backup\" | default false) \"de\" (get \$p \"de\" | default \"\") | toJson }}")" + +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT +mkdir -p "$tmp/cfg/conf.d" +"${cz[@]}" execute-template --override-data "$data" \ + < "$repo/home/dot_config/mise/conf.d/20-packages.toml.tmpl" \ + > "$tmp/cfg/conf.d/20-packages.toml" +[[ -f "$lock" ]] && cp "$lock" "$tmp/cfg/mise.lock" + +token="${MISE_GITHUB_TOKEN:-${GITHUB_TOKEN:-$(gh auth token 2>/dev/null || true)}}" +( + cd "$tmp" + env -u MISE_GLOBAL_CONFIG_FILE -u MISE_CONFIG_FILE -u MISE_ENV \ + MISE_CONFIG_DIR="$tmp/cfg" MISE_DATA_DIR="$tmp/data" MISE_CACHE_DIR="$tmp/cache" \ + MISE_GITHUB_TOKEN="$token" MISE_YES=1 \ + mise lock --global --platform "$platforms" ${bump[@]+"${bump[@]}"} +) + +cp "$tmp/cfg/mise.lock" "$lock" +echo "Wrote ${lock#"$repo"/}"