mirror of
https://github.com/ivuorinen/dotfiles.git
synced 2026-02-08 09:50:52 +00:00
Compare commits
8 Commits
26.2.7
...
renovate/p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21f8d7161d | ||
| a18c16b0b9 | |||
| 785a8e8eb7 | |||
| 1cda859999 | |||
| bc69560da4 | |||
| 2ee9407a43 | |||
| 765c2fce72 | |||
| 88eceaf194 |
26
.claude/settings.json
Normal file
26
.claude/settings.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && case \"$fp\" in */fzf-tmux|*/yarn.lock|*/.yarn/*) echo \"BLOCKED: $fp is a vendor/lock file — do not edit directly\" >&2; exit 2;; esac; exit 0"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Edit|Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "fp=$(cat | jq -r '.tool_input.file_path // empty') && [ -n \"$fp\" ] && [ -f \"$fp\" ] && case \"$fp\" in *.sh|*/bin/*) head -1 \"$fp\" | grep -qE '^#!.*(ba)?sh' && command -v shfmt > /dev/null && shfmt -i 2 -bn -ci -sr -fn -w \"$fp\";; esac; exit 0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
37
.claude/skills/shell-validate/SKILL.md
Normal file
37
.claude/skills/shell-validate/SKILL.md
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
name: shell-validate
|
||||
description: Validate shell scripts after editing. Apply when writing or modifying any shell script in local/bin/ or scripts/.
|
||||
user-invocable: false
|
||||
allowed-tools: Bash, Read, Grep
|
||||
---
|
||||
|
||||
After editing any shell script in `local/bin/`, `scripts/`, or `config/` (files with a `#!` shebang or `# shellcheck shell=` directive), validate it:
|
||||
|
||||
## 1. Determine the shell
|
||||
|
||||
- `/bin/sh` or `#!/usr/bin/env sh` shebang -> POSIX, use `sh -n`
|
||||
- `/bin/bash` or `#!/usr/bin/env bash` shebang -> Bash, use `bash -n`
|
||||
- `# shellcheck shell=bash` directive (no shebang) -> use `bash -n`
|
||||
- `# shellcheck shell=sh` directive (no shebang) -> use `sh -n`
|
||||
- No shebang and no directive -> default to `bash -n`
|
||||
|
||||
## 2. Syntax check
|
||||
|
||||
Run the appropriate syntax checker:
|
||||
|
||||
```bash
|
||||
bash -n <file> # for bash scripts
|
||||
sh -n <file> # for POSIX sh scripts
|
||||
```
|
||||
|
||||
If syntax check fails, fix the issue before proceeding.
|
||||
|
||||
## 3. ShellCheck
|
||||
|
||||
Run `shellcheck <file>`. The project `.shellcheckrc` already disables SC2039, SC2166, SC2154, SC1091, SC2174, SC2016. Only report and fix warnings that are NOT in that exclude list.
|
||||
|
||||
## Key files to never validate (not shell scripts)
|
||||
|
||||
- `local/bin/fzf-tmux` (vendor file)
|
||||
- `*.md` files
|
||||
- `*.bats` test files (Bats, not plain shell)
|
||||
@@ -1 +1 @@
|
||||
3.14.2
|
||||
3.14.3
|
||||
|
||||
36
CLAUDE.md
36
CLAUDE.md
@@ -34,6 +34,8 @@ yarn install
|
||||
yarn lint # Run biome + prettier + editorconfig-checker
|
||||
yarn lint:biome # Biome only
|
||||
yarn lint:ec # EditorConfig checker only
|
||||
yarn lint:md-table # Markdown table formatting check
|
||||
yarn fix:md-table # Auto-fix markdown tables
|
||||
|
||||
# Formatting
|
||||
yarn fix:biome # Autofix with biome (JS/TS/JSON/MD)
|
||||
@@ -74,12 +76,24 @@ which loads:
|
||||
Zsh additionally uses **antidote** (in `tools/antidote/`)
|
||||
for plugin management and **oh-my-posh** for the prompt.
|
||||
|
||||
### msgr — Messaging Helper
|
||||
|
||||
`local/bin/msgr` provides colored output functions (`msgr msg`,
|
||||
`msgr run`, `msgr yay`, `msgr err`, `msgr warn`). Sourced by `dfm`
|
||||
and most scripts in `local/bin/`.
|
||||
|
||||
### dfm — Dotfiles Manager
|
||||
|
||||
`local/bin/dfm` is the main management script. Key commands:
|
||||
- `dfm install all` — install everything (called during `./install`)
|
||||
- `dfm install all` — install everything in tiered stages
|
||||
- `dfm brew install` / `dfm brew update` — Homebrew management
|
||||
- `dfm apt upkeep` — APT package maintenance (Debian/Ubuntu)
|
||||
- `dfm dotfiles fmt` / `dfm dotfiles shfmt` — format configs/scripts
|
||||
- `dfm helpers <name>` — inspect aliases, colors, env, functions, path
|
||||
- `dfm docs all` — regenerate documentation under `docs/`
|
||||
- `dfm check arch` / `dfm check host` — system info
|
||||
- `dfm scripts` — run scripts from `scripts/` (discovered via `@description` tags)
|
||||
- `dfm tests` — test visualization helpers
|
||||
|
||||
### Submodules
|
||||
|
||||
@@ -118,6 +132,26 @@ SC2039 (POSIX `local`), SC2166 (`-o` in test),
|
||||
SC2154 (unassigned variables), SC1091 (source following),
|
||||
SC2174 (mkdir -p -m), SC2016 (single-quote expressions).
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **POSIX scripts**: `x-ssh-audit`, `x-codeql`, `x-until-error`,
|
||||
`x-until-success`, `x-ssl-expiry-date` use `/bin/sh`.
|
||||
Validate with `sh -n`, not `bash -n`.
|
||||
- **Vendor file**: `local/bin/fzf-tmux` is vendored from
|
||||
junegunn/fzf — do not modify.
|
||||
- **Fish config**: `config/fish/` has its own config chain
|
||||
(`config.fish`, `exports.fish`, `alias.fish`) plus 80+ functions.
|
||||
- **Python**: Two scripts (`x-compare-versions.py`,
|
||||
`x-git-largest-files.py`) linted by Ruff (config in `pyproject.toml`).
|
||||
|
||||
## Claude Code Configuration
|
||||
|
||||
- **Hooks** (`.claude/settings.json`):
|
||||
- *PreToolUse*: Blocks edits to `fzf-tmux`, `yarn.lock`, `.yarn/`
|
||||
- *PostToolUse*: Auto-runs `shfmt` on shell scripts after Edit/Write
|
||||
- **Skills** (`.claude/skills/`):
|
||||
- `shell-validate`: Auto-validates shell scripts (syntax + shellcheck)
|
||||
|
||||
## Package Manager
|
||||
|
||||
Yarn (v4.12.0) is the package manager. Do not use npm.
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
|
||||
# Set XDG directories if not already set
|
||||
# https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
[ -z "$XDG_CONFIG_HOME" ] && export XDG_CONFIG_HOME="$HOME/.config"
|
||||
[ -z "$XDG_DATA_HOME" ] && export XDG_DATA_HOME="$HOME/.local/share"
|
||||
[ -z "$XDG_CACHE_HOME" ] && export XDG_CACHE_HOME="$HOME/.cache"
|
||||
[ -z "$XDG_STATE_HOME" ] && export XDG_STATE_HOME="$HOME/.local/state"
|
||||
[ -z "$XDG_BIN_HOME" ] && export XDG_BIN_HOME="$HOME/.local/bin"
|
||||
[ -z "$XDG_RUNTIME_DIR" ] && export XDG_RUNTIME_DIR="$HOME/.local/run"
|
||||
[ -z "${XDG_CONFIG_HOME:-}" ] && export XDG_CONFIG_HOME="$HOME/.config"
|
||||
[ -z "${XDG_DATA_HOME:-}" ] && export XDG_DATA_HOME="$HOME/.local/share"
|
||||
[ -z "${XDG_CACHE_HOME:-}" ] && export XDG_CACHE_HOME="$HOME/.cache"
|
||||
[ -z "${XDG_STATE_HOME:-}" ] && export XDG_STATE_HOME="$HOME/.local/state"
|
||||
[ -z "${XDG_BIN_HOME:-}" ] && export XDG_BIN_HOME="$HOME/.local/bin"
|
||||
[ -z "${XDG_RUNTIME_DIR:-}" ] && export XDG_RUNTIME_DIR="$HOME/.local/run"
|
||||
|
||||
# if DOTFILES is not set, set it to the default location
|
||||
[ -z "$DOTFILES" ] && export DOTFILES="$HOME/.dotfiles"
|
||||
[ -z "${DOTFILES:-}" ] && export DOTFILES="$HOME/.dotfiles"
|
||||
|
||||
export PATH="$XDG_BIN_HOME:$DOTFILES/local/bin:$XDG_DATA_HOME/bob/nvim-bin:$XDG_DATA_HOME/cargo/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"
|
||||
|
||||
@@ -448,9 +448,9 @@ export ZSHZ_DATA="$XDG_STATE_HOME/z"
|
||||
export CHEAT_USE_FZF=true
|
||||
export SQLITE_HISTORY="${XDG_CACHE_HOME}/sqlite_history"
|
||||
|
||||
[ -f "$XDG_CONFIG_HOME/exports-secret" ] && source "$XDG_CONFIG_HOME/exports-secret"
|
||||
[ -f "$XDG_CONFIG_HOME/exports-local" ] && source "$XDG_CONFIG_HOME/exports-local"
|
||||
if [ -f "$XDG_CONFIG_HOME/exports-secret" ]; then source "$XDG_CONFIG_HOME/exports-secret"; fi
|
||||
if [ -f "$XDG_CONFIG_HOME/exports-local" ]; then source "$XDG_CONFIG_HOME/exports-local"; fi
|
||||
# shellcheck source=./exports-lakka
|
||||
[ -f "$XDG_CONFIG_HOME/exports-$(hostname)" ] && source "$XDG_CONFIG_HOME/exports-$(hostname)"
|
||||
if [ -f "$XDG_CONFIG_HOME/exports-$(hostname)" ]; then source "$XDG_CONFIG_HOME/exports-$(hostname)"; fi
|
||||
# shellcheck source=./exports-lakka-secret
|
||||
[ -f "$XDG_CONFIG_HOME/exports-$(hostname)-secret" ] && source "$XDG_CONFIG_HOME/exports-$(hostname)-secret"
|
||||
if [ -f "$XDG_CONFIG_HOME/exports-$(hostname)-secret" ]; then source "$XDG_CONFIG_HOME/exports-$(hostname)-secret"; fi
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# shellcheck shell=bash
|
||||
|
||||
# Defaults
|
||||
[[ -z "$DOTFILES" ]] && export DOTFILES="$HOME/.dotfiles"
|
||||
[[ -z "${DOTFILES:-}" ]] && export DOTFILES="$HOME/.dotfiles"
|
||||
DOTFILES_CURRENT_SHELL=$(basename "$SHELL")
|
||||
export DOTFILES_CURRENT_SHELL
|
||||
|
||||
@@ -76,9 +76,9 @@ x-path-prepend "$DOTFILES/local/bin"
|
||||
x-path-prepend "$XDG_BIN_HOME"
|
||||
|
||||
# Custom completion paths
|
||||
[[ -z "$ZSH_CUSTOM_COMPLETION_PATH" ]] && export ZSH_CUSTOM_COMPLETION_PATH="$XDG_CONFIG_HOME/zsh/completion"
|
||||
[[ -z "${ZSH_CUSTOM_COMPLETION_PATH:-}" ]] && export ZSH_CUSTOM_COMPLETION_PATH="$XDG_CONFIG_HOME/zsh/completion"
|
||||
x-dc "$ZSH_CUSTOM_COMPLETION_PATH"
|
||||
export FPATH="$ZSH_CUSTOM_COMPLETION_PATH:$FPATH"
|
||||
export FPATH="$ZSH_CUSTOM_COMPLETION_PATH:${FPATH:-}"
|
||||
|
||||
if ! declare -f msg > /dev/null; then
|
||||
# Function to print messages if VERBOSE is enabled
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
: "${DOTFILES:=$HOME/.dotfiles}"
|
||||
: "${BREWFILE:=$DOTFILES/config/homebrew/Brewfile}"
|
||||
: "${HOSTFILES:=$DOTFILES/hosts}"
|
||||
export DOTFILES BREWFILE HOSTFILES
|
||||
|
||||
SCRIPT=$(basename "$0")
|
||||
|
||||
@@ -71,33 +72,57 @@ section_install()
|
||||
|
||||
MENU=(
|
||||
"all:Installs everything in the correct order"
|
||||
"apt-packages:Install apt packages (Debian/Ubuntu)"
|
||||
"cargo:Install rust/cargo packages"
|
||||
"cheat-databases:Install cheat external cheatsheet databases"
|
||||
"composer:Install composer"
|
||||
"dnf-packages:Install dnf packages (Fedora/RHEL)"
|
||||
"fonts:Install programming fonts"
|
||||
"gh:Install GitHub CLI Extensions"
|
||||
"git-crypt:Install git-crypt from source"
|
||||
"go:Install Go Packages"
|
||||
"imagick:Install ImageMagick CLI"
|
||||
"macos:Setup nice macOS defaults"
|
||||
"npm-packages:Install NPM Packages"
|
||||
"ntfy:Install ntfy notification tool"
|
||||
"nvm-latest:Install latest lts node using nvm"
|
||||
"nvm:Install Node Version Manager (nvm)"
|
||||
"python-packages:Install Python packages via uv"
|
||||
"xcode-cli-tools:Install Xcode CLI tools (macOS)"
|
||||
"z:Install z"
|
||||
)
|
||||
|
||||
case "$1" in
|
||||
all)
|
||||
msgr msg "Starting to install all and reloading configurations..."
|
||||
$0 install macos
|
||||
$0 install fonts
|
||||
|
||||
# Tier 0: Platform foundations (OS packages, build tools)
|
||||
[[ "$(uname)" == "Darwin" ]] && $0 install macos
|
||||
[[ "$(uname)" == "Darwin" ]] && $0 install xcode-cli-tools
|
||||
command -v apt &> /dev/null && $0 install apt-packages
|
||||
command -v dnf &> /dev/null && $0 install dnf-packages
|
||||
|
||||
# Tier 1: Package managers & fonts
|
||||
$0 brew install
|
||||
$0 install fonts
|
||||
|
||||
# Tier 2: Language packages (depend on runtimes from Tier 1)
|
||||
$0 install cargo
|
||||
$0 install go
|
||||
$0 install composer
|
||||
$0 install cheat-databases
|
||||
$0 install nvm
|
||||
$0 install npm-packages
|
||||
$0 install python-packages
|
||||
|
||||
# Tier 3: Tool-dependent installers
|
||||
$0 install cheat-databases
|
||||
$0 install gh
|
||||
$0 install git-crypt
|
||||
$0 install ntfy
|
||||
|
||||
# Tier 4: Independent utilities
|
||||
$0 install z
|
||||
|
||||
msgr msg "Reloading configurations again..."
|
||||
# shellcheck disable=SC1091
|
||||
source "$DOTFILES/config/shared.sh"
|
||||
@@ -112,7 +137,7 @@ section_install()
|
||||
|
||||
cheat-databases)
|
||||
msgr run "Installing cheat databases..."
|
||||
for database in "$DOTFILES"/scripts/install-cheat-*; do
|
||||
for database in "$DOTFILES"/scripts/install-cheat-*.sh; do
|
||||
bash "$database" \
|
||||
&& msgr run_done "Cheat: $database run"
|
||||
done
|
||||
@@ -184,6 +209,42 @@ section_install()
|
||||
&& msgr yay "NPM Packages have been installed!"
|
||||
;;
|
||||
|
||||
apt-packages)
|
||||
msgr run "Installing apt packages..."
|
||||
bash "$DOTFILES/scripts/install-apt-packages.sh" \
|
||||
&& msgr yay "apt packages installed!"
|
||||
;;
|
||||
|
||||
dnf-packages)
|
||||
msgr run "Installing dnf packages..."
|
||||
bash "$DOTFILES/scripts/install-dnf-packages.sh" \
|
||||
&& msgr yay "dnf packages installed!"
|
||||
;;
|
||||
|
||||
git-crypt)
|
||||
msgr run "Installing git-crypt..."
|
||||
bash "$DOTFILES/scripts/install-git-crypt.sh" \
|
||||
&& msgr yay "git-crypt installed!"
|
||||
;;
|
||||
|
||||
ntfy)
|
||||
msgr run "Installing ntfy..."
|
||||
bash "$DOTFILES/scripts/install-ntfy.sh" \
|
||||
&& msgr yay "ntfy installed!"
|
||||
;;
|
||||
|
||||
python-packages)
|
||||
msgr run "Installing Python packages..."
|
||||
bash "$DOTFILES/scripts/install-python-packages.sh" \
|
||||
&& msgr yay "Python packages installed!"
|
||||
;;
|
||||
|
||||
xcode-cli-tools)
|
||||
msgr run "Installing Xcode CLI tools..."
|
||||
bash "$DOTFILES/scripts/install-xcode-cli-tools.sh" \
|
||||
&& msgr yay "Xcode CLI tools installed!"
|
||||
;;
|
||||
|
||||
z)
|
||||
msgr run "Installing z..."
|
||||
bash "$DOTFILES/scripts/install-z.sh" \
|
||||
|
||||
133
tests/dfm.bats
133
tests/dfm.bats
@@ -5,8 +5,141 @@ setup()
|
||||
export DOTFILES="$PWD"
|
||||
}
|
||||
|
||||
# ── Group 1: Main help & routing ──────────────────────────────
|
||||
|
||||
@test "dfm help shows usage" {
|
||||
run bash local/bin/dfm help
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"Usage: dfm"* ]]
|
||||
}
|
||||
|
||||
@test "dfm with no args shows full usage with all sections" {
|
||||
run bash local/bin/dfm
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"Usage: dfm"* ]]
|
||||
[[ "$output" == *"dfm install"* ]]
|
||||
[[ "$output" == *"dfm check"* ]]
|
||||
[[ "$output" == *"dfm helpers"* ]]
|
||||
[[ "$output" == *"dfm docs"* ]]
|
||||
[[ "$output" == *"dfm dotfiles"* ]]
|
||||
[[ "$output" == *"dfm scripts"* ]]
|
||||
}
|
||||
|
||||
@test "dfm with invalid section shows usage" {
|
||||
run bash local/bin/dfm nonexistent
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"Usage: dfm"* ]]
|
||||
}
|
||||
|
||||
# ── Group 2: Install menu completeness ────────────────────────
|
||||
|
||||
@test "dfm install menu shows all entries" {
|
||||
run bash local/bin/dfm install
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"all"* ]]
|
||||
[[ "$output" == *"apt-packages"* ]]
|
||||
[[ "$output" == *"cargo"* ]]
|
||||
[[ "$output" == *"cheat-databases"* ]]
|
||||
[[ "$output" == *"composer"* ]]
|
||||
[[ "$output" == *"dnf-packages"* ]]
|
||||
[[ "$output" == *"fonts"* ]]
|
||||
[[ "$output" == *"gh"* ]]
|
||||
[[ "$output" == *"git-crypt"* ]]
|
||||
[[ "$output" == *"go"* ]]
|
||||
[[ "$output" == *"imagick"* ]]
|
||||
[[ "$output" == *"macos"* ]]
|
||||
[[ "$output" == *"npm-packages"* ]]
|
||||
[[ "$output" == *"ntfy"* ]]
|
||||
[[ "$output" == *"nvm-latest"* ]]
|
||||
[[ "$output" == *"nvm"* ]]
|
||||
[[ "$output" == *"python-packages"* ]]
|
||||
[[ "$output" == *"xcode-cli-tools"* ]]
|
||||
[[ "$output" == *"z"* ]]
|
||||
}
|
||||
|
||||
@test "dfm install with invalid subcommand shows menu" {
|
||||
run bash local/bin/dfm install nonexistent
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"dfm install"* ]]
|
||||
}
|
||||
|
||||
# ── Group 3: Other section menus ──────────────────────────────
|
||||
|
||||
@test "dfm helpers menu shows entries" {
|
||||
run bash local/bin/dfm helpers
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"aliases"* ]]
|
||||
[[ "$output" == *"colors"* ]]
|
||||
[[ "$output" == *"path"* ]]
|
||||
[[ "$output" == *"env"* ]]
|
||||
}
|
||||
|
||||
@test "dfm docs menu shows entries" {
|
||||
run bash local/bin/dfm docs
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"all"* ]]
|
||||
[[ "$output" == *"tmux"* ]]
|
||||
[[ "$output" == *"nvim"* ]]
|
||||
[[ "$output" == *"wezterm"* ]]
|
||||
}
|
||||
|
||||
@test "dfm dotfiles menu shows entries" {
|
||||
run bash local/bin/dfm dotfiles
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"fmt"* ]]
|
||||
[[ "$output" == *"shfmt"* ]]
|
||||
[[ "$output" == *"yamlfmt"* ]]
|
||||
}
|
||||
|
||||
@test "dfm check menu shows entries" {
|
||||
run bash local/bin/dfm check
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"arch"* ]]
|
||||
[[ "$output" == *"host"* ]]
|
||||
}
|
||||
|
||||
@test "dfm scripts menu lists install scripts" {
|
||||
run bash local/bin/dfm scripts
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"cargo-packages"* ]]
|
||||
[[ "$output" == *"fonts"* ]]
|
||||
[[ "$output" == *"z"* ]]
|
||||
}
|
||||
|
||||
@test "dfm tests menu shows entries" {
|
||||
run bash local/bin/dfm tests
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"msgr"* ]]
|
||||
[[ "$output" == *"params"* ]]
|
||||
}
|
||||
|
||||
# ── Group 4: Check commands ───────────────────────────────────
|
||||
|
||||
@test "dfm check arch returns current arch" {
|
||||
run bash local/bin/dfm check arch
|
||||
[ "$status" -eq 0 ]
|
||||
[ -n "$output" ]
|
||||
}
|
||||
|
||||
@test "dfm check arch with matching value exits 0" {
|
||||
local current_arch
|
||||
current_arch="$(uname)"
|
||||
run bash local/bin/dfm check arch "$current_arch"
|
||||
[ "$status" -eq 0 ]
|
||||
}
|
||||
|
||||
@test "dfm check arch with non-matching value exits 1" {
|
||||
run bash local/bin/dfm check arch FakeArch
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
@test "dfm check host returns current hostname" {
|
||||
run bash local/bin/dfm check host
|
||||
[ "$status" -eq 0 ]
|
||||
[ -n "$output" ]
|
||||
}
|
||||
|
||||
@test "dfm check host with non-matching value exits 1" {
|
||||
run bash local/bin/dfm check host fakehostname
|
||||
[ "$status" -eq 1 ]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user