dip 8.3.0 → 8.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +52 -5
- data/lib/dip/cli/console.rb +10 -2
- data/lib/dip/cli.rb +1 -1
- data/lib/dip/commands/console.rb +175 -12
- data/lib/dip/config.rb +13 -6
- data/lib/dip/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: eae945780bd009e844b733abddfbc4529204ff443a4b112b39e13dfdc4f8e987
|
|
4
|
+
data.tar.gz: 60790bd09dda4ebda2c18a08c774b5deb9e52336c51723fa153dc034376c8806
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e881c360bfb42ef5e6e3ca150e656b0cca36adbbf171424ca4a7fc78771bd15b6572a7438aae53009a73123b541ab47af1afd873f1734263a3bfde6d400f959
|
|
7
|
+
data.tar.gz: 93fadd1ead85482d4b9b7a128cfbd5e75de0df7e2d575f9d9ba766c86a7221c4b3ec32bbb999e6041bf2418b58cade580cb3c9e9e0160d2f4dc797e139c15974
|
data/README.md
CHANGED
|
@@ -36,12 +36,34 @@ gem install dip
|
|
|
36
36
|
|
|
37
37
|
### Integration with shell
|
|
38
38
|
|
|
39
|
-
Dip can be injected into the current shell (
|
|
39
|
+
Dip can be injected into the current shell so that interaction commands (and `compose`, `up`, `stop`, `down`, `build`, `provision`) become available without the `dip` prefix. **Bash**, **ZSH**, and **Fish** are supported.
|
|
40
|
+
|
|
41
|
+
Add the matching line to your shell startup file so the integration is loaded in every session:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
# Bash — ~/.bashrc or ~/.bash_profile
|
|
45
|
+
eval "$(dip console)"
|
|
46
|
+
```
|
|
40
47
|
|
|
41
48
|
```sh
|
|
49
|
+
# ZSH — ~/.zshrc
|
|
42
50
|
eval "$(dip console)"
|
|
43
51
|
```
|
|
44
52
|
|
|
53
|
+
```fish
|
|
54
|
+
# Fish — ~/.config/fish/config.fish
|
|
55
|
+
dip console | source
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The target shell is autodetected from the `$SHELL` environment variable, so the snippets above work as-is. If autodetection is wrong (for example, you run Fish but `$SHELL` still points to Bash), force the dialect explicitly:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
eval "$(dip console --shell zsh)" # Bash / ZSH
|
|
62
|
+
dip console --shell fish | source # Fish
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`--shell` accepts `bash`, `zsh`, or `fish` (`bash` and `zsh` produce the same POSIX output).
|
|
66
|
+
|
|
45
67
|
**IMPORTANT**: Beware of possible collisions with local tools. One particular example is supporting both local and Docker frontend build tools, such as Yarn. If you want some developer to run `yarn` locally and other to use Docker for that, you should either avoid adding the `yarn` command to the `dip.yml` or avoid using the shell integration for hybrid development.
|
|
46
68
|
|
|
47
69
|
After that we can type commands without `dip` prefix. For example:
|
|
@@ -54,16 +76,27 @@ ktl *any-kubectl-arg
|
|
|
54
76
|
provision
|
|
55
77
|
```
|
|
56
78
|
|
|
57
|
-
When we change the current directory, all shell aliases
|
|
79
|
+
When we change the current directory, all shell aliases are automatically removed. When we enter a directory that has a `dip.yml` file (in it or in a parent), the aliases are renewed. This is wired through the shell's directory-change hook — `chpwd_functions` on ZSH, a `cd`/`pushd`/`popd` wrapper on Bash, and a `--on-variable PWD` handler on Fish. The hook resolves the applicable `dip.yml` itself (no `dip` process involved) and only actually reloads when that path changes, so `cd`ing around inside the same project doesn't re-run `dip` on every prompt.
|
|
58
80
|
|
|
59
|
-
Also, in shell mode Dip
|
|
81
|
+
Also, in shell mode Dip tries to determine manually passed environment variables. For example:
|
|
60
82
|
|
|
61
83
|
```sh
|
|
62
84
|
VERSION=20180515103400 rails db:migrate:down
|
|
63
85
|
```
|
|
64
86
|
|
|
65
|
-
|
|
66
|
-
|
|
87
|
+
Once the startup snippet is in place, the integration is applied automatically every time you open your terminal.
|
|
88
|
+
|
|
89
|
+
#### How it works
|
|
90
|
+
|
|
91
|
+
`dip console` prints a bootstrap script that defines three helpers:
|
|
92
|
+
|
|
93
|
+
- `dip_inject` — evaluates `dip console inject`, which emits one shell function per interaction command plus the built-in `compose`/`up`/`stop`/`down`/`build`/`provision` wrappers. An interaction command whose name collides with a shell builtin/keyword (`jobs`, `test`, `read`, `set`, …) is skipped, with a warning on stderr — run it as `dip <name>` instead, or rename it.
|
|
94
|
+
- `dip_clear` — removes the functions previously injected (regenerated on every inject so it always matches the current `dip.yml`).
|
|
95
|
+
- `dip_reload` — runs `dip_clear` then `dip_inject`; also bound to the directory-change hook, which calls it only when the resolved `dip.yml` path actually changed.
|
|
96
|
+
|
|
97
|
+
The bootstrap also exports `DIP_SHELL=1`, `DIP_EARLY_ENVS` (the list of variables present at load time, used to detect manually passed env vars), and `DIP_PROMPT_TEXT` (`ⅆ`). On ZSH with the `agnoster` theme, `DIP_PROMPT_TEXT` is added as a prompt segment; other shells and themes are left untouched.
|
|
98
|
+
|
|
99
|
+
You can force a reload at any time by running `dip_reload` (useful after editing `dip.yml`).
|
|
67
100
|
|
|
68
101
|
## Usage
|
|
69
102
|
|
|
@@ -508,6 +541,20 @@ If validation fails, you'll get detailed error messages indicating what needs to
|
|
|
508
541
|
You can skip validation by setting `DIP_SKIP_VALIDATION` environment variable.
|
|
509
542
|
|
|
510
543
|
Add `# yaml-language-server: $schema=https://raw.githubusercontent.com/bibendi/dip/refs/heads/master/schema.json` to the top of your dip.yml to get schema validation in VSCode. Read more about [YAML Language Server](https://github.com/redhat-developer/vscode-yaml?tab=readme-ov-file#associating-schemas).
|
|
544
|
+
|
|
545
|
+
### dip console
|
|
546
|
+
|
|
547
|
+
Prints the shell integration script for the current shell. See [Integration with shell](#integration-with-shell) for the full setup.
|
|
548
|
+
|
|
549
|
+
```sh
|
|
550
|
+
dip console [--shell bash|zsh|fish] # bootstrap script (default subcommand)
|
|
551
|
+
dip console inject [--shell bash|zsh|fish] # just the command aliases
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
- `--shell` (`-s`) selects the dialect: `bash`, `zsh`, or `fish`. When omitted, it is autodetected from `$SHELL`, falling back to POSIX (Bash/ZSH) output.
|
|
555
|
+
- `dip console` is meant to be evaluated by your shell: `eval "$(dip console)"` for Bash/ZSH, `dip console | source` for Fish.
|
|
556
|
+
- `dip console inject` is called internally by the bootstrap script (via `dip_reload`); you normally don't run it by hand. It only needs the interaction command names, so it skips full `dip.yml` schema validation — run `dip validate` (or any other `dip` command) to check the file against the schema.
|
|
557
|
+
|
|
511
558
|
## Changelog
|
|
512
559
|
|
|
513
560
|
See [CHANGELOG.md](CHANGELOG.md).
|
data/lib/dip/cli/console.rb
CHANGED
|
@@ -7,14 +7,21 @@ require_relative "../commands/console"
|
|
|
7
7
|
module Dip
|
|
8
8
|
class CLI
|
|
9
9
|
class Console < Base
|
|
10
|
+
SHELL_OPTION = [
|
|
11
|
+
:shell,
|
|
12
|
+
{aliases: "-s", type: :string, enum: %w[bash zsh fish posix],
|
|
13
|
+
desc: "Target shell dialect (autodetected from $SHELL by default)"}
|
|
14
|
+
].freeze
|
|
15
|
+
|
|
10
16
|
desc "start", "Integrate Dip into current shell"
|
|
11
17
|
method_option :help, aliases: "-h", type: :boolean,
|
|
12
18
|
desc: "Display usage information"
|
|
19
|
+
method_option(*SHELL_OPTION)
|
|
13
20
|
def start
|
|
14
21
|
if options[:help]
|
|
15
22
|
invoke :help, ["start"]
|
|
16
23
|
else
|
|
17
|
-
Dip::Commands::Console::Start.new.execute
|
|
24
|
+
Dip::Commands::Console::Start.new(shell: options[:shell]).execute
|
|
18
25
|
end
|
|
19
26
|
end
|
|
20
27
|
|
|
@@ -23,11 +30,12 @@ module Dip
|
|
|
23
30
|
desc "inject", "Inject aliases"
|
|
24
31
|
method_option :help, aliases: "-h", type: :boolean,
|
|
25
32
|
desc: "Display usage information"
|
|
33
|
+
method_option(*SHELL_OPTION)
|
|
26
34
|
def inject
|
|
27
35
|
if options[:help]
|
|
28
36
|
invoke :help, ["inject"]
|
|
29
37
|
else
|
|
30
|
-
Dip::Commands::Console::Inject.new.execute
|
|
38
|
+
Dip::Commands::Console::Inject.new(shell: options[:shell]).execute
|
|
31
39
|
end
|
|
32
40
|
end
|
|
33
41
|
end
|
data/lib/dip/cli.rb
CHANGED
|
@@ -143,7 +143,7 @@ module Dip
|
|
|
143
143
|
subcommand :infra, Dip::CLI::Infra
|
|
144
144
|
|
|
145
145
|
require_relative "cli/console"
|
|
146
|
-
desc "console", "Integrate Dip commands into shell (
|
|
146
|
+
desc "console", "Integrate Dip commands into shell (Bash, ZSH and Fish are supported)"
|
|
147
147
|
subcommand :console, Dip::CLI::Console
|
|
148
148
|
end
|
|
149
149
|
end
|
data/lib/dip/commands/console.rb
CHANGED
|
@@ -5,14 +5,50 @@ require_relative "../command"
|
|
|
5
5
|
module Dip
|
|
6
6
|
module Commands
|
|
7
7
|
module Console
|
|
8
|
+
# Interaction command names come straight from `dip.yml`, and `inject`
|
|
9
|
+
# turns each one into a same-named shell function. A name that collides
|
|
10
|
+
# with a shell builtin/keyword silently shadows it for the rest of the
|
|
11
|
+
# session — e.g. an interaction called `jobs` breaks `jobs`, which
|
|
12
|
+
# things like Starship's prompt call on every render, turning every
|
|
13
|
+
# keystroke into a `dip jobs` invocation. Skip those instead of
|
|
14
|
+
# aliasing over them.
|
|
15
|
+
RESERVED_NAMES = %w[
|
|
16
|
+
cd pwd test read set jobs type command builtin history alias unalias
|
|
17
|
+
source eval exec exit return break continue trap kill wait bg fg
|
|
18
|
+
export unset declare typeset readonly local shift times true false
|
|
19
|
+
echo printf time status functions function end
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
# Figure out which shell dialect to generate integration code for.
|
|
23
|
+
#
|
|
24
|
+
# An explicit value (from `--shell`) always wins. Otherwise we guess from
|
|
25
|
+
# the `$SHELL` environment variable and fall back to the POSIX flavour
|
|
26
|
+
# (bash/zsh) which was the only supported one historically.
|
|
27
|
+
def self.detect_shell(explicit = nil)
|
|
28
|
+
name = (explicit || File.basename(ENV["SHELL"].to_s)).to_s.downcase
|
|
29
|
+
name.include?("fish") ? :fish : :posix
|
|
30
|
+
end
|
|
31
|
+
|
|
8
32
|
class Start < Dip::Command
|
|
33
|
+
def initialize(shell: nil)
|
|
34
|
+
@shell = Console.detect_shell(shell)
|
|
35
|
+
end
|
|
36
|
+
|
|
9
37
|
def execute
|
|
10
|
-
puts
|
|
38
|
+
puts fish? ? fish_script : posix_script
|
|
11
39
|
end
|
|
12
40
|
|
|
13
41
|
private
|
|
14
42
|
|
|
15
|
-
def
|
|
43
|
+
def fish?
|
|
44
|
+
@shell == :fish
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def inject_command
|
|
48
|
+
"#{Dip.bin_path} console inject --shell #{@shell}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def posix_script
|
|
16
52
|
<<-SH.gsub(/^ {12}/, "")
|
|
17
53
|
export DIP_SHELL=1
|
|
18
54
|
export DIP_EARLY_ENVS=#{ENV.keys.join(",")}
|
|
@@ -24,7 +60,7 @@ module Dip
|
|
|
24
60
|
}
|
|
25
61
|
|
|
26
62
|
function dip_inject() {
|
|
27
|
-
eval "$(#{
|
|
63
|
+
eval "$(#{inject_command})"
|
|
28
64
|
}
|
|
29
65
|
|
|
30
66
|
function dip_reload() {
|
|
@@ -32,6 +68,36 @@ module Dip
|
|
|
32
68
|
dip_inject
|
|
33
69
|
}
|
|
34
70
|
|
|
71
|
+
# Resolves the dip.yml that applies to $PWD (or $DIP_FILE), without
|
|
72
|
+
# spawning a `dip` process — used to skip redundant reloads below.
|
|
73
|
+
function __dip_config_path() {
|
|
74
|
+
if [ -n "${DIP_FILE:-}" ]; then
|
|
75
|
+
printf '%s\\n' "$DIP_FILE"
|
|
76
|
+
return
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
\\typeset __dip_dir="$PWD"
|
|
80
|
+
while :; do
|
|
81
|
+
if [ -e "$__dip_dir/dip.yml" ]; then
|
|
82
|
+
printf '%s\\n' "$__dip_dir/dip.yml"
|
|
83
|
+
return
|
|
84
|
+
fi
|
|
85
|
+
[ "$__dip_dir" = "/" ] && return
|
|
86
|
+
__dip_dir=$(dirname "$__dip_dir")
|
|
87
|
+
done
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Only reload aliases on `cd` when the resolved dip.yml actually
|
|
91
|
+
# changed — most `cd`s stay within the same project and would
|
|
92
|
+
# otherwise re-spawn `dip` (Ruby boot + schema validation) for nothing.
|
|
93
|
+
function __dip_auto_reload() {
|
|
94
|
+
\\typeset __dip_new_config_path
|
|
95
|
+
__dip_new_config_path="$(__dip_config_path)"
|
|
96
|
+
[ "$__dip_new_config_path" = "${__DIP_CONFIG_PATH:-}" ] && return
|
|
97
|
+
__DIP_CONFIG_PATH="$__dip_new_config_path"
|
|
98
|
+
dip_reload
|
|
99
|
+
}
|
|
100
|
+
|
|
35
101
|
# Inspired by RVM
|
|
36
102
|
function __zsh_like_cd() {
|
|
37
103
|
\\typeset __zsh_like_cd_hook
|
|
@@ -58,7 +124,7 @@ module Dip
|
|
|
58
124
|
}
|
|
59
125
|
|
|
60
126
|
export -a chpwd_functions
|
|
61
|
-
[[ " ${chpwd_functions[*]} " == *"
|
|
127
|
+
[[ " ${chpwd_functions[*]} " == *" __dip_auto_reload "* ]] || chpwd_functions+=(__dip_auto_reload)
|
|
62
128
|
|
|
63
129
|
if [[ "$ZSH_THEME" = "agnoster" ]]; then
|
|
64
130
|
eval "`declare -f prompt_end | sed '1s/.*/_&/'`"
|
|
@@ -73,22 +139,87 @@ module Dip
|
|
|
73
139
|
fi
|
|
74
140
|
|
|
75
141
|
dip_reload
|
|
142
|
+
__DIP_CONFIG_PATH="$(__dip_config_path)"
|
|
76
143
|
SH
|
|
77
144
|
end
|
|
145
|
+
|
|
146
|
+
def fish_script
|
|
147
|
+
<<-FISH.gsub(/^ {12}/, "")
|
|
148
|
+
set -gx DIP_SHELL 1
|
|
149
|
+
set -gx DIP_EARLY_ENVS "#{ENV.keys.join(",")}"
|
|
150
|
+
set -gx DIP_PROMPT_TEXT "ⅆ"
|
|
151
|
+
|
|
152
|
+
function dip_clear
|
|
153
|
+
# just stub, will be redefined after injecting aliases
|
|
154
|
+
true
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
function dip_inject
|
|
158
|
+
#{inject_command} | source
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
function dip_reload
|
|
162
|
+
dip_clear
|
|
163
|
+
dip_inject
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Resolves the dip.yml that applies to $PWD (or $DIP_FILE), without
|
|
167
|
+
# spawning a `dip` process — used to skip redundant reloads below.
|
|
168
|
+
function __dip_config_path
|
|
169
|
+
if set -q DIP_FILE
|
|
170
|
+
echo "$DIP_FILE"
|
|
171
|
+
return
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
set -l __dip_dir "$PWD"
|
|
175
|
+
while true
|
|
176
|
+
if test -e "$__dip_dir/dip.yml"
|
|
177
|
+
echo "$__dip_dir/dip.yml"
|
|
178
|
+
return
|
|
179
|
+
end
|
|
180
|
+
if test "$__dip_dir" = "/"
|
|
181
|
+
return
|
|
182
|
+
end
|
|
183
|
+
set __dip_dir (dirname "$__dip_dir")
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Renew aliases whenever the working directory changes — but only
|
|
188
|
+
# when the resolved dip.yml actually changed. Most `cd`s stay within
|
|
189
|
+
# the same project and would otherwise re-spawn `dip` (Ruby boot +
|
|
190
|
+
# schema validation) for nothing.
|
|
191
|
+
function __dip_chpwd --on-variable PWD
|
|
192
|
+
set -l __dip_new_config_path (__dip_config_path)
|
|
193
|
+
if test "$__dip_new_config_path" != "$__dip_config_path_cache"
|
|
194
|
+
set -g __dip_config_path_cache "$__dip_new_config_path"
|
|
195
|
+
dip_reload
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
dip_reload
|
|
200
|
+
set -g __dip_config_path_cache (__dip_config_path)
|
|
201
|
+
FISH
|
|
202
|
+
end
|
|
78
203
|
end
|
|
79
204
|
|
|
80
205
|
class Inject < Dip::Command
|
|
81
206
|
attr_reader :out, :aliases
|
|
82
207
|
|
|
83
|
-
def initialize
|
|
208
|
+
def initialize(shell: nil)
|
|
209
|
+
@shell = Console.detect_shell(shell)
|
|
84
210
|
@aliases = []
|
|
85
211
|
@out = []
|
|
86
212
|
end
|
|
87
213
|
|
|
88
214
|
def execute
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
215
|
+
# Runs on every automatic shell reload (e.g. on `cd`), so it only needs
|
|
216
|
+
# the interaction command names, not full schema conformance — skip the
|
|
217
|
+
# `json-schema` require and validation pass that every other command pays.
|
|
218
|
+
with_validation_skipped do
|
|
219
|
+
if Dip.config.exist?
|
|
220
|
+
add_aliases(*Dip.config.interaction.keys) if Dip.config.interaction
|
|
221
|
+
add_aliases("compose", "up", "stop", "down", "provision", "build")
|
|
222
|
+
end
|
|
92
223
|
end
|
|
93
224
|
|
|
94
225
|
clear_aliases
|
|
@@ -98,17 +229,49 @@ module Dip
|
|
|
98
229
|
|
|
99
230
|
private
|
|
100
231
|
|
|
232
|
+
def with_validation_skipped
|
|
233
|
+
had_key = ENV.key?("DIP_SKIP_VALIDATION")
|
|
234
|
+
previous = ENV["DIP_SKIP_VALIDATION"]
|
|
235
|
+
ENV["DIP_SKIP_VALIDATION"] = "1"
|
|
236
|
+
yield
|
|
237
|
+
ensure
|
|
238
|
+
if had_key
|
|
239
|
+
ENV["DIP_SKIP_VALIDATION"] = previous
|
|
240
|
+
else
|
|
241
|
+
ENV.delete("DIP_SKIP_VALIDATION")
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def fish?
|
|
246
|
+
@shell == :fish
|
|
247
|
+
end
|
|
248
|
+
|
|
101
249
|
def add_aliases(*names)
|
|
102
250
|
names.each do |name|
|
|
251
|
+
if Console::RESERVED_NAMES.include?(name.to_s)
|
|
252
|
+
warn "dip: skipping alias `#{name}` — it would shadow the `#{name}` shell builtin. " \
|
|
253
|
+
"Run it as `#{Dip.bin_path} #{name}`, or rename it in dip.yml."
|
|
254
|
+
next
|
|
255
|
+
end
|
|
256
|
+
|
|
103
257
|
aliases << name
|
|
104
|
-
out <<
|
|
258
|
+
out << if fish?
|
|
259
|
+
"function #{name}; #{Dip.bin_path} #{name} $argv; end"
|
|
260
|
+
else
|
|
261
|
+
"function #{name}() { #{Dip.bin_path} #{name} $@; }"
|
|
262
|
+
end
|
|
105
263
|
end
|
|
106
264
|
end
|
|
107
265
|
|
|
108
266
|
def clear_aliases
|
|
109
|
-
out <<
|
|
110
|
-
|
|
111
|
-
|
|
267
|
+
out << if fish?
|
|
268
|
+
body = aliases.any? ? "functions -e #{aliases.join(" ")}" : "true"
|
|
269
|
+
"function dip_clear; #{body}; end"
|
|
270
|
+
else
|
|
271
|
+
"function dip_clear() { \n" \
|
|
272
|
+
"#{aliases.any? ? aliases.map { |a| " unset -f #{a}" }.join("\n") : "true"} " \
|
|
273
|
+
"\n}"
|
|
274
|
+
end
|
|
112
275
|
end
|
|
113
276
|
end
|
|
114
277
|
end
|
data/lib/dip/config.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
require "yaml"
|
|
4
4
|
require "erb"
|
|
5
5
|
require "pathname"
|
|
6
|
-
require "json
|
|
6
|
+
require "json"
|
|
7
7
|
|
|
8
8
|
require "dip/version"
|
|
9
9
|
require "dip/ext/hash"
|
|
@@ -114,15 +114,22 @@ module Dip
|
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
# `data`, when given, is the already-parsed raw config (as produced by
|
|
118
|
+
# `load_yaml`) so callers that parsed the file themselves don't pay for
|
|
119
|
+
# parsing it a second time here.
|
|
120
|
+
def validate(data = nil)
|
|
118
121
|
raise Dip::Error, "Config file path is not set" if file_path.nil?
|
|
119
122
|
raise Dip::Error, "Config file not found: #{file_path}" unless File.exist?(file_path)
|
|
120
123
|
|
|
121
124
|
schema_path = File.join(File.dirname(__FILE__), "../../schema.json")
|
|
122
125
|
raise Dip::Error, "Schema file not found: #{schema_path}" unless File.exist?(schema_path)
|
|
123
126
|
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
require "json-schema"
|
|
128
|
+
|
|
129
|
+
data ||= self.class.load_yaml(file_path)
|
|
130
|
+
# Parse with the stdlib rather than JSON::Validator.parse: the latter passes
|
|
131
|
+
# `quirks_mode:` to JSON.parse, which the json gem removed in 3.0 (Ruby 3.5+).
|
|
132
|
+
schema = JSON.parse(File.read(schema_path))
|
|
126
133
|
JSON::Validator.validate!(schema, data)
|
|
127
134
|
rescue Psych::SyntaxError => e
|
|
128
135
|
raise Dip::Error, "Invalid YAML syntax in config file: #{e.message}"
|
|
@@ -130,7 +137,7 @@ module Dip
|
|
|
130
137
|
data_display = data ? data.to_yaml.gsub("\n", "\n ") : "nil"
|
|
131
138
|
error_message = "Schema validation failed: #{e.message}\nInput data:\n #{data_display}"
|
|
132
139
|
raise Dip::Error, error_message
|
|
133
|
-
rescue JSON::Schema::JsonParseError => e
|
|
140
|
+
rescue JSON::Schema::JsonParseError, JSON::ParserError => e
|
|
134
141
|
raise Dip::Error, "Error parsing schema file: #{e.message}"
|
|
135
142
|
end
|
|
136
143
|
|
|
@@ -179,7 +186,7 @@ module Dip
|
|
|
179
186
|
@config = CONFIG_DEFAULTS.merge(base_config)
|
|
180
187
|
|
|
181
188
|
unless ENV.key?("DIP_SKIP_VALIDATION")
|
|
182
|
-
validate
|
|
189
|
+
validate(config)
|
|
183
190
|
end
|
|
184
191
|
|
|
185
192
|
@config
|
data/lib/dip/version.rb
CHANGED