grasys blog

ターミナルがダサいとモテない。topgrade で update 管理編 part2

macOS/Linux の update 管理に何を使っていますか?

Photo by Ryuno on Unsplash

恵比寿で IT 企業をやっているとモテると聞いて創業しましたが早いことありがたいことに 10 年目に突入した長谷川です。

まだモテる成果は出ていません、、、これからです!(もうめんどくさいのでカウントやめましたw)

今回は topgrade です。

GitHub – topgrade-rs/topgrade: Upgrade all the things


macOS や Linux などで update 管理に使えるスグレモノです。

ここを見るとめちゃくちゃ広範囲に対応しているのがわかります。

topgrade/src/steps at main · topgrade-rs/topgrade


grasys の blog には書いてるので Part2 になります。

topgrade で macOS の update 管理


ここでは update もあるので Setup から自分の使い方なども含めて紹介することにします。

Install

homebrew で入ります。

brew install topgrade

Help

Help みるとめちゃくちゃ多機能なのもわかって頂けるかと・・・

Usage: topgrade [OPTIONS]

Options:
--edit-config
Edit the configuration file

--config-reference
Show config reference

-t, --tmux
Run inside tmux

-c, --cleanup
Cleanup temporary or old files

-n, --dry-run
Print what would be done

--no-retry
Do not ask to retry failed steps

--disable <STEP>...
Do not perform upgrades for the given steps

[possible values: am, app_man, asdf, atom, aqua, audit, auto_cpufreq, bin, bob, brew_cask, brew_formula, bun, bun_packages, cargo, certbot, chezmoi, chocolatey, choosenim, clam_av_db, composer, conda, config_update, containers, custom_commands, deb_get, deno, distrobox, dkp_pacman, dotnet, elan, emacs, firmware, flatpak, flutter, fossil, gcloud, gem, ghcup, github_cli_extensions, git_repos, gnome_shell_extensions, go, guix, haxelib, helm, home_manager, jetpack, julia, juliaup, kakoune, helix, krew, lure, lensfun, macports, mamba, miktex, mas, maza, micro, mise, myrepos, nix, node, opam, pacdef, pacstall, pearl, pip3, pip_review, pip_review_local, pipupgrade, pipx, pixi, pkg, pkgin, platformio_core, pnpm, poetry, powershell, protonup, pyenv, raco, rcm, remotes, restarts, rtcl, ruby_gems, rustup, rye, scoop, sdkman, self_update, sheldon, shell, snap, sparkle, spicetify, stack, stew, system, tldr, tlmgr, tmux, toolbx, uv, vagrant, vcpkg, vim, volta_packages, vscode, waydroid, winget, wsl, wsl_update, xcodes, yadm, yarn, zvm]

--only <STEP>...
Perform only the specified steps

[possible values: am, app_man, asdf, atom, aqua, audit, auto_cpufreq, bin, bob, brew_cask, brew_formula, bun, bun_packages, cargo, certbot, chezmoi, chocolatey, choosenim, clam_av_db, composer, conda, config_update, containers, custom_commands, deb_get, deno, distrobox, dkp_pacman, dotnet, elan, emacs, firmware, flatpak, flutter, fossil, gcloud, gem, ghcup, github_cli_extensions, git_repos, gnome_shell_extensions, go, guix, haxelib, helm, home_manager, jetpack, julia, juliaup, kakoune, helix, krew, lure, lensfun, macports, mamba, miktex, mas, maza, micro, mise, myrepos, nix, node, opam, pacdef, pacstall, pearl, pip3, pip_review, pip_review_local, pipupgrade, pipx, pixi, pkg, pkgin, platformio_core, pnpm, poetry, powershell, protonup, pyenv, raco, rcm, remotes, restarts, rtcl, ruby_gems, rustup, rye, scoop, sdkman, self_update, sheldon, shell, snap, sparkle, spicetify, stack, stew, system, tldr, tlmgr, tmux, toolbx, uv, vagrant, vcpkg, vim, volta_packages, vscode, waydroid, winget, wsl, wsl_update, xcodes, yadm, yarn, zvm]

--custom-commands <NAME>...
Run only specific custom commands

--env <NAME=VALUE>...
Set environment variables

-v, --verbose
Output debug logs. Alias for `--log-filter debug`

-k, --keep
Prompt for a key before exiting

--skip-notify
Skip sending a notification at the end of a run

-y, --yes [<STEP>...]
Say yes to package manager's prompt

[possible values: am, app_man, asdf, atom, aqua, audit, auto_cpufreq, bin, bob, brew_cask, brew_formula, bun, bun_packages, cargo, certbot, chezmoi, chocolatey, choosenim, clam_av_db, composer, conda, config_update, containers, custom_commands, deb_get, deno, distrobox, dkp_pacman, dotnet, elan, emacs, firmware, flatpak, flutter, fossil, gcloud, gem, ghcup, github_cli_extensions, git_repos, gnome_shell_extensions, go, guix, haxelib, helm, home_manager, jetpack, julia, juliaup, kakoune, helix, krew, lure, lensfun, macports, mamba, miktex, mas, maza, micro, mise, myrepos, nix, node, opam, pacdef, pacstall, pearl, pip3, pip_review, pip_review_local, pipupgrade, pipx, pixi, pkg, pkgin, platformio_core, pnpm, poetry, powershell, protonup, pyenv, raco, rcm, remotes, restarts, rtcl, ruby_gems, rustup, rye, scoop, sdkman, self_update, sheldon, shell, snap, sparkle, spicetify, stack, stew, system, tldr, tlmgr, tmux, toolbx, uv, vagrant, vcpkg, vim, volta_packages, vscode, waydroid, winget, wsl, wsl_update, xcodes, yadm, yarn, zvm]

--disable-predefined-git-repos
Don't pull the predefined git repos

--config <PATH>
Alternative configuration file

--remote-host-limit <REGEX>
A regular expression for restricting remote host execution

--show-skipped
Show the reason for skipped steps

--log-filter <LOG_FILTER>
Tracing filter directives.

See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/struct.EnvFilter.html

[default: warn]

--no-self-update
Don't update Topgrade

-h, --help
Print help (see a summary with '-h')

-V, --version
Print version

Configuration

ここをみると書いてあります。

GitHub – topgrade-rs/topgrade: Upgrade all the things


macOS の場合 CONFIG_HOMEXDG_CONFIG_HOME なので .config です。
つまり ${HOME}/.config/topgrade.toml が Config Path です。

topgrade には config-reference という option があるのでそちらを利用すると、config sample が出力できます。

# Include any additional configuration file(s)
# [include] sections are processed in the order you write them
# Files in $CONFIG_DIR/topgrade.d/ are automatically included before this file
[include]
# paths = ["/etc/topgrade.toml"]


[misc]
# Run `sudo -v` to cache credentials at the start of the run
# This avoids a blocking password prompt in the middle of an unattended run
# (default: false)
# pre_sudo = false

# Sudo command to be used
# sudo_command = "sudo"

# Disable specific steps - same options as the command line flag
# disable = ["system", "emacs"]

# Ignore failures for these steps
# ignore_failures = ["powershell"]

# List of remote machines with Topgrade installed on them
# remote_topgrades = ["toothless", "pi", "parnas"]

# Path to Topgrade executable on remote machines
# remote_topgrade_path = ".cargo/bin/topgrade"

# Arguments to pass to SSH when upgrading remote systems
# ssh_arguments = "-o ConnectTimeout=2"

# Arguments to pass tmux when pulling Repositories
# tmux_arguments = "-S /var/tmux.sock"

# Do not set the terminal title (default: true)
# set_title = true

# Display the time in step titles (default: true)
# display_time = true

# Don't ask for confirmations (no default value)
# assume_yes = true

# Do not ask to retry failed steps (default: false)
# no_retry = true

# Run inside tmux (default: false)
# run_in_tmux = true

# Changes the way topgrade interacts with
# the tmux session, creating the session
# and only attaching to it if not inside tmux
# (default: "attach_if_not_in_session", allowed values: "attach_if_not_in_session", "attach_always")
# tmux_session_mode = "attach_if_not_in_session"

# Cleanup temporary or old files (default: false)
# cleanup = true

# Send a notification for every step (default: false)
# notify_each_step = false

# Skip sending a notification at the end of a run (default: false)
# skip_notify = true

# The Bash-it branch to update (default: "stable")
# bashit_branch = "stable"

# Run specific steps - same options as the command line flag
# only = ["system", "emacs"]

# Whether to self update
#
# this will be ignored if the binary is built without self update support
#
# available also via setting the environment variable TOPGRADE_NO_SELF_UPGRADE)
# no_self_update = true

# Extra tracing filter directives
# These are prepended to the `--log-filter` argument
# See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives
# log_filters = ["topgrade::command=debug", "warn"]


# Commands to run before anything
[pre_commands]
# "Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak"


# Commands to run after anything
[post_commands]
# "Emacs Snapshot" = "rm -rf ~/.emacs.d/elpa.bak && cp -rl ~/.emacs.d/elpa ~/.emacs.d/elpa.bak"


# Custom commands
[commands]
# "Python Environment" = "~/dev/.env/bin/pip install -i https://pypi.python.org/simple -U --upgrade-strategy eager jupyter"
# "Custom command using interactive shell (unix)" = "-i vim_upgrade"


[python]
# enable_pip_review = true ###disabled by default
# enable_pip_review_local = true ###disabled by default
# enable_pipupgrade = true ###disabled by default
# pipupgrade_arguments = "-y -u --pip-path pip" ###disabled by default


[composer]
# self_update = true


[brew]
# For the BrewCask step
# If `Repo Cask Upgrade` exists, then use the `-a` option.
# Otherwise, use the `--greedy` option.
# greedy_cask = true

# For the BrewCask step
# If `Repo Cask Upgrade` does not exist, then use the `--greedy_latest` option.
# NOTE: the above entry `greedy_cask` contains this entry, though you can enable
# both of them, they won't clash with each other.
# greedy_latest = true

# For the BrewCask step
# If `Repo Cask Upgrade` does not exist, then use the `--greedy_auto_updates` option.
# NOTE: the above entry `greedy_cask` contains this entry, though you can enable
# both of them, they won't clash with each other.
# greedy_auto_updates = true

# For the BrewFormula step
# Execute `brew autoremove` after the step.
# autoremove = true

# For the BrewFormula step
# Upgrade formulae built from the HEAD branch; `brew upgrade --fetch-HEAD`
# fetch_head = true


[linux]
# Arch Package Manager to use.
# Allowed values:
# autodetect, aura, garuda_update, pacman, pamac, paru, pikaur, trizen, yay
# arch_package_manager = "pacman"

# Arguments to pass yay (or paru) when updating packages
# yay_arguments = "--nodevel"

# Arguments to pass dnf when updating packages
# dnf_arguments = "--refresh"

# aura_aur_arguments = "-kx"

# aura_pacman_arguments = ""
# garuda_update_arguments = ""

# show_arch_news = true

# trizen_arguments = "--devel"

# pikaur_arguments = ""

# pamac_arguments = "--no-devel"

# enable_tlmgr = true

# emerge_sync_flags = "-q"

# emerge_update_flags = "-uDNa --with-bdeps=y world"

# redhat_distro_sync = false

# suse_dup = false

# rpm_ostree = false

# nix_arguments = "--flake"

# nix_env_arguments = "--prebuilt-only"

# Extra Home Manager arguments
# home_manager_arguments = ["--flake", "file"]


[git]
# How many repos to pull at max in parallel
# max_concurrency = 5

# Additional git repositories to pull
# repos = [
# "~/src/*/",
# "~/.config/something"
# ]

# Don't pull the predefined git repos
# pull_predefined = false

# Arguments to pass Git when pulling Repositories
# arguments = "--rebase --autostash"


[windows]
# Manually select Windows updates
# accept_all_updates = false

# open_remotes_in_new_terminal = true

# wsl_update_pre_release = true

# wsl_update_use_web_download = true

# Causes Topgrade to rename itself during the run to allow package managers
# to upgrade it. Use this only if you installed Topgrade by using a package
# manager such as Scoop or Cargo
# self_rename = true


[npm]
# Use sudo if the NPM directory isn't owned by the current user
# use_sudo = true


[yarn]
# Run `yarn global upgrade` with `sudo`
# use_sudo = true


[vim]
# For `vim-plug`, execute `PlugUpdate!` instead of `PlugUpdate`
# force_plug_update = true


[firmware]
# Offer to update firmware; if false just check for and display available updates
# upgrade = true


[vagrant]
# Vagrant directories
# directories = []

# power on vagrant boxes if needed
# power_on = true

# Always suspend vagrant boxes instead of powering off
# always_suspend = true


[flatpak]
# Use sudo for updating the system-wide installation
# use_sudo = true


[distrobox]
# use_root = false

# containers = ["archlinux-latest"]
[containers]
# Specify the containers to ignore while updating (Wildcard supported)
# ignored_containers = ["ghcr.io/rancher-sandbox/rancher-desktop/rdx-proxy:latest", "docker.io*"]
# Specify the runtime to use for containers (default: "docker", allowed values: "docker", "podman")
# runtime = "podman"

[lensfun]
# If disabled, Topgrade invokes `lensfun‑update‑data` without root priviledge,
# then the update will be only available to you. Otherwise, `sudo` is required,
# and the update will be installed system-wide, i.e., available to all users.
# (default: false)
# use_sudo = false

因みに config-reference を見るとわかるのですが、

# Include any additional configuration file(s)
# [include] sections are processed in the order you write them
# Files in $CONFIG_DIR/topgrade.d/ are automatically included before this file
[include]
# paths = ["/etc/topgrade.toml"]

このように ${CONFIG_DIR}/topgrade.d/ 配下に toml を配置することで ${CONFIG_DIR}/topgrade.toml の設定を上書きすることができます。

私はこれを利用して管理しています。
つまり ${CONFIG_DIR}/topgrade.toml は何もいじってません。

├──  topgrade.d
│ ├──  brew.toml
│ ├──  commands.toml
│ ├──  git.toml
│ └──  misc.toml
├──  topgrade.toml

${CONFIG_DIR}/topgrade.d/misc.toml

[misc]
# Run `sudo -v` to cache credentials at the start of the run
# This avoids a blocking password prompt in the middle of an unattended run
# (default: false)
# pre_sudo = false
pre_sudo = true

# Sudo command to be used
# sudo_command = "sudo"

# Disable specific steps - same options as the command line flag
# disable = ["system", "emacs"]
disable = ["mas", "system", "shell", "vim", "vscode", "gem", "ruby_gems"]

# Ignore failures for these steps
# ignore_failures = ["powershell"]
ignore_failures = ["github_cli_extensions"]

# List of remote machines with Topgrade installed on them
# remote_topgrades = ["toothless", "pi", "parnas"]

# Path to Topgrade executable on remote machines
# remote_topgrade_path = ".cargo/bin/topgrade"

# Arguments to pass to SSH when upgrading remote systems
# ssh_arguments = "-o ConnectTimeout=2"

# Arguments to pass tmux when pulling Repositories
# tmux_arguments = "-S /var/tmux.sock"

# Do not set the terminal title (default: true)
set_title = true

# Display the time in step titles (default: true)
display_time = true

# Don't ask for confirmations (no default value)
assume_yes = true

# Do not ask to retry failed steps (default: false)
no_retry = true

# Run inside tmux (default: false)
# run_in_tmux = true

# Cleanup temporary or old files (default: false)
cleanup = true

# Send a notification for every step (default: false)
# notify_each_step = false

# Skip sending a notification at the end of a run (default: false)
# skip_notify = true

# The Bash-it branch to update (default: "stable")
# bashit_branch = "stable"

# Run specific steps - same options as the command line flag
# only = ["system", "emacs"]

# Whether to self update
#
# this will be ignored if the binary is built without self update support
#
# available also via setting the environment variable TOPGRADE_NO_SELF_UPGRADE)
# no_self_update = true

# Extra tracing filter directives
# These are prepended to the `--log-filter` argument
# See: https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#directives
# log_filters = ["topgrade::command=debug", "warn"]

pre_sudo を true にしてますが、諸事情でしてます。(忘れました)
通常は false で大丈夫です。

disable で shell, vim, vscode などしてますが邪魔だったんだろうなぁ・・・(記憶がありませんw)

${CONFIG_DIR}/topgrade.d/brew.toml

homebrew も制御下にいれることができます。

[brew]
# For the BrewCask step
# If `Repo Cask Upgrade` exists, then use the `-a` option.
# Otherwise, use the `--greedy` option.
# greedy_cask = true

# For the BrewCask step
# If `Repo Cask Upgrade` does not exist, then use the `--greedy_latest` option.
# NOTE: the above entry `greedy_cask` contains this entry, though you can enable
# both of them, they won't clash with each other.
# greedy_latest = true

# For the BrewFormula step
# Execute `brew autoremove` after the step.
autoremove = true

# For the BrewFormula step
# Upgrade formulae built from the HEAD branch; `brew upgrade --fetch-HEAD`
# fetch_head = true

${CONFIG_DIR}/topgrade.d/commands.toml

topgrade はコマンドを発行して独自に拡張が可能です。

anyenv はもう使うのやめています。
Perl は書かなくなり・・・依存していた plenv は必要なくなり
Python を書くようになったので pyenvrye から uv へ移行し
neovim で絶対に必要な lualuaenvluaver
またごく一部に node を使ってたけど nodenv から volta へ移行
またまたごく一部に go のバイナリを触りたいので goenv を使ってましたが、つい先日 gobrew へ移行しました。

# Custom commands
[commands]
## anyenv
#"anyenv update" = "~/anyenv/bin/anyenv update"
## perl
#"cpan-outdated and update" = "~/anyenv/envs/plenv/shims/cpan-outdated -p | ~/anyenv/envs/plenv/shims/cpanm"
#"plenv list-modules" = "~/anyenv/envs/plenv/bin/plenv list-modules && ~/anyenv/envs/plenv/bin/plenv list-modules > ~/ProtonDrive/Mackup/plenv_list-modules.txt"

# python
# rye
#"rye self update" = "~/rye/shims/rye self update"
#"rye tools list" = "~/rye/shims/rye tools list --include-version > ~/ProtonDrive/Mackup/rye_tools_list.txt"

# uv
"uv self update" = "~/rust/bin/uv self update"
"uv tool list" = "~/rust/bin/uv tool list > ~/ProtonDrive/Mackup/uv_tool_list.txt"
"uv cache clean/prune" = "~/rust/bin/uv cache clean && ~/rust/bin/uv cache prune"

# luaver
"luarocks update" = "for rocks in $(luarocks list --outdated | grep -v '^Outdated rocks:' | grep '^[a-z]'); do luarocks install ${rocks}; done"

# gobrew
"gobrew self-update" = "~/.gobrew/bin/gobrew self-update"
"go-global-update" = "~/go/bin/go-global-update"

# rust
"rustup self update" = "~/rust/bin/rustup self update"
"cargo backup" = "~/rust/bin/rustup run stable cargo backup --out ~/ProtonDrive/Mackup/cargo-backup.json"

# lporg
"lporg save" = "/opt/homebrew/bin/lporg save --config ~/.config/lporg/lporg.yaml"

# homebrew
"brew bundle dump" = "/opt/homebrew/bin/brew bundle --force dump"

# for macos
"mackup backup" = "~/uv/bin/mackup --force backup"

私は各言語の Version Manager 以外で以下を発行してます。

[commands] の前には [pre_commands][post_commands] があります。

これは topgrade の開始前、終了前に実行される commands 郡になります。何か事前処理や事後処理したい際に使うと良いと思います。
本来、homebrewbundle dumpmackup は post_commands が良いと思いますが、まだ pre/post_commands がなかった頃から使っていて、現時点で特段困ることもないので commands で処理してしまっています。

${CONFIG_DIR}/topgrade.d/git.toml

git も管理できます。

[git]
# How many repos to pull at max in parallel
# max_concurrency = 5
max_concurrency = 5

# Additional git repositories to pull
# repos = [
# "~/src/*/",
# "~/.config/something"
# ]
repos = [
"~/envutils-darwin",
"~/local/mo",
"~/local/rerun",
]

# Don't pull the predefined git repos
# pull_predefined = false

# Arguments to pass Git when pulling Repositories
# arguments = "--rebase --autostash"

実はもっとお手製の Tool や IceCream-Bash やらあるのですが・・・恥ずいので消しましたw

envutils-darwin は私物で macOS 用の rerun(bash 用の Command-Line Framework です。)の modules や mustacheこちらはいろいろな言語や環境で利用できる Template Engine です。) template が含まれています。

topgrade はコマンド一発で OS の update を管理できます。

エンジニアのみなさんはけっこうこれが大変なんじゃないでしょうか?

update したいものとしたくないものなどあると思いますが、制御して対応すれば日々の作業が楽になります。

めんどくさいことは topgrade にまかせてしまいましょう。

ターミナル環境について他の記事も書いているので、よろしければこちらもご覧ください!
『ターミナルがダサいとモテない』シリーズ一覧

転載:ターミナルがダサいとモテない。topgrade で update 管理編 part2


採用情報
お問い合わせ