dip 8.2.6 → 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 +67 -5
- data/lib/dip/cli/console.rb +10 -2
- data/lib/dip/cli.rb +9 -1
- data/lib/dip/commands/console.rb +175 -12
- data/lib/dip/commands/preflight.rb +15 -0
- data/lib/dip/config.rb +16 -8
- data/lib/dip/version.rb +1 -1
- data/schema.json +10 -0
- metadata +2 -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
|
@@ -20,6 +20,14 @@ The dip is a CLI dev–tool that provides native-like interaction with a Dockeri
|
|
|
20
20
|
|
|
21
21
|
[](https://asciinema.org/a/210236)
|
|
22
22
|
|
|
23
|
+
## Quick start with AI
|
|
24
|
+
|
|
25
|
+
[dip-skill](https://github.com/kalashnikovisme/dip-skill) helps you quickly configure a `dip` environment for your project. It detects the tech stack and bootstraps `dip.yml`, compose files, and Dockerfiles.
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
npx skills add kalashnikovisme/dip-skill
|
|
29
|
+
```
|
|
30
|
+
|
|
23
31
|
## Installation
|
|
24
32
|
|
|
25
33
|
```sh
|
|
@@ -28,12 +36,34 @@ gem install dip
|
|
|
28
36
|
|
|
29
37
|
### Integration with shell
|
|
30
38
|
|
|
31
|
-
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
|
+
```
|
|
32
47
|
|
|
33
48
|
```sh
|
|
49
|
+
# ZSH — ~/.zshrc
|
|
34
50
|
eval "$(dip console)"
|
|
35
51
|
```
|
|
36
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
|
+
|
|
37
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.
|
|
38
68
|
|
|
39
69
|
After that we can type commands without `dip` prefix. For example:
|
|
@@ -46,16 +76,27 @@ ktl *any-kubectl-arg
|
|
|
46
76
|
provision
|
|
47
77
|
```
|
|
48
78
|
|
|
49
|
-
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.
|
|
50
80
|
|
|
51
|
-
Also, in shell mode Dip
|
|
81
|
+
Also, in shell mode Dip tries to determine manually passed environment variables. For example:
|
|
52
82
|
|
|
53
83
|
```sh
|
|
54
84
|
VERSION=20180515103400 rails db:migrate:down
|
|
55
85
|
```
|
|
56
86
|
|
|
57
|
-
|
|
58
|
-
|
|
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`).
|
|
59
100
|
|
|
60
101
|
## Usage
|
|
61
102
|
|
|
@@ -178,8 +219,16 @@ provision:
|
|
|
178
219
|
- dip clean_cache
|
|
179
220
|
- dip compose up -d pg redis
|
|
180
221
|
- dip bash -c ./bin/setup
|
|
222
|
+
|
|
223
|
+
preflight:
|
|
224
|
+
- ./bin/check-credentials
|
|
225
|
+
- test -f .env
|
|
181
226
|
```
|
|
182
227
|
|
|
228
|
+
`preflight` is an array of shell commands that dip runs before any command that touches a running container or cluster: `dip compose ...` (and its aliases `dip up`, `dip build`, `dip stop`, `dip down`), `dip ktl ...`, and `dip run ...` (including the interaction shorthand `dip <name>`). If any command exits non-zero, dip aborts before the underlying operation runs. Useful for verifying credentials are present, required files exist, env vars are set, etc.
|
|
229
|
+
|
|
230
|
+
Not triggered by `dip down --all` (cross-project teardown), `dip ssh`, `dip infra`, or `dip provision`.
|
|
231
|
+
|
|
183
232
|
### Predefined environment variables
|
|
184
233
|
|
|
185
234
|
#### $DIP_OS
|
|
@@ -493,6 +542,19 @@ You can skip validation by setting `DIP_SKIP_VALIDATION` environment variable.
|
|
|
493
542
|
|
|
494
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).
|
|
495
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
|
+
|
|
496
558
|
## Changelog
|
|
497
559
|
|
|
498
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
|
@@ -49,7 +49,10 @@ module Dip
|
|
|
49
49
|
|
|
50
50
|
desc "compose CMD [OPTIONS]", "Run Docker Compose commands"
|
|
51
51
|
def compose(*argv)
|
|
52
|
+
require_relative "commands/preflight"
|
|
52
53
|
require_relative "commands/compose"
|
|
54
|
+
|
|
55
|
+
Dip::Commands::Preflight.new.execute
|
|
53
56
|
Dip::Commands::Compose.new(*argv).execute
|
|
54
57
|
end
|
|
55
58
|
|
|
@@ -84,7 +87,10 @@ module Dip
|
|
|
84
87
|
|
|
85
88
|
desc "ktl CMD [OPTIONS]", "Run kubectl commands"
|
|
86
89
|
def ktl(*argv)
|
|
90
|
+
require_relative "commands/preflight"
|
|
87
91
|
require_relative "commands/kubectl"
|
|
92
|
+
|
|
93
|
+
Dip::Commands::Preflight.new.execute
|
|
88
94
|
Dip::Commands::Kubectl.new(*argv).execute
|
|
89
95
|
end
|
|
90
96
|
|
|
@@ -96,8 +102,10 @@ module Dip
|
|
|
96
102
|
if argv.empty? || options[:help]
|
|
97
103
|
invoke :help, ["run"]
|
|
98
104
|
else
|
|
105
|
+
require_relative "commands/preflight"
|
|
99
106
|
require_relative "commands/run"
|
|
100
107
|
|
|
108
|
+
Dip::Commands::Preflight.new.execute
|
|
101
109
|
Dip::Commands::Run.new(
|
|
102
110
|
*argv,
|
|
103
111
|
**options.to_h.transform_keys!(&:to_sym)
|
|
@@ -135,7 +143,7 @@ module Dip
|
|
|
135
143
|
subcommand :infra, Dip::CLI::Infra
|
|
136
144
|
|
|
137
145
|
require_relative "cli/console"
|
|
138
|
-
desc "console", "Integrate Dip commands into shell (
|
|
146
|
+
desc "console", "Integrate Dip commands into shell (Bash, ZSH and Fish are supported)"
|
|
139
147
|
subcommand :console, Dip::CLI::Console
|
|
140
148
|
end
|
|
141
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"
|
|
@@ -20,10 +20,11 @@ module Dip
|
|
|
20
20
|
kubectl: {},
|
|
21
21
|
infra: {},
|
|
22
22
|
interaction: {},
|
|
23
|
-
provision: []
|
|
23
|
+
provision: [],
|
|
24
|
+
preflight: []
|
|
24
25
|
}.freeze
|
|
25
26
|
|
|
26
|
-
TOP_LEVEL_KEYS = %i[environment compose kubectl infra interaction provision].freeze
|
|
27
|
+
TOP_LEVEL_KEYS = %i[environment compose kubectl infra interaction provision preflight].freeze
|
|
27
28
|
|
|
28
29
|
ConfigKeyMissingError = Class.new(ArgumentError)
|
|
29
30
|
|
|
@@ -113,15 +114,22 @@ module Dip
|
|
|
113
114
|
end
|
|
114
115
|
end
|
|
115
116
|
|
|
116
|
-
|
|
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)
|
|
117
121
|
raise Dip::Error, "Config file path is not set" if file_path.nil?
|
|
118
122
|
raise Dip::Error, "Config file not found: #{file_path}" unless File.exist?(file_path)
|
|
119
123
|
|
|
120
124
|
schema_path = File.join(File.dirname(__FILE__), "../../schema.json")
|
|
121
125
|
raise Dip::Error, "Schema file not found: #{schema_path}" unless File.exist?(schema_path)
|
|
122
126
|
|
|
123
|
-
|
|
124
|
-
|
|
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))
|
|
125
133
|
JSON::Validator.validate!(schema, data)
|
|
126
134
|
rescue Psych::SyntaxError => e
|
|
127
135
|
raise Dip::Error, "Invalid YAML syntax in config file: #{e.message}"
|
|
@@ -129,7 +137,7 @@ module Dip
|
|
|
129
137
|
data_display = data ? data.to_yaml.gsub("\n", "\n ") : "nil"
|
|
130
138
|
error_message = "Schema validation failed: #{e.message}\nInput data:\n #{data_display}"
|
|
131
139
|
raise Dip::Error, error_message
|
|
132
|
-
rescue JSON::Schema::JsonParseError => e
|
|
140
|
+
rescue JSON::Schema::JsonParseError, JSON::ParserError => e
|
|
133
141
|
raise Dip::Error, "Error parsing schema file: #{e.message}"
|
|
134
142
|
end
|
|
135
143
|
|
|
@@ -178,7 +186,7 @@ module Dip
|
|
|
178
186
|
@config = CONFIG_DEFAULTS.merge(base_config)
|
|
179
187
|
|
|
180
188
|
unless ENV.key?("DIP_SKIP_VALIDATION")
|
|
181
|
-
validate
|
|
189
|
+
validate(config)
|
|
182
190
|
end
|
|
183
191
|
|
|
184
192
|
@config
|
data/lib/dip/version.rb
CHANGED
data/schema.json
CHANGED
|
@@ -175,6 +175,16 @@
|
|
|
175
175
|
]
|
|
176
176
|
]
|
|
177
177
|
},
|
|
178
|
+
"preflight": {
|
|
179
|
+
"type": "array",
|
|
180
|
+
"items": {
|
|
181
|
+
"type": "string"
|
|
182
|
+
},
|
|
183
|
+
"description": "Shell commands to run before any `dip compose` subcommand. A non-zero exit aborts the command.",
|
|
184
|
+
"examples": [
|
|
185
|
+
["./bin/check-credentials", "test -f .env"]
|
|
186
|
+
]
|
|
187
|
+
},
|
|
178
188
|
"environment": {
|
|
179
189
|
"$ref": "#/definitions/environment_vars"
|
|
180
190
|
},
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dip
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 8.
|
|
4
|
+
version: 8.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- bibendi
|
|
@@ -231,6 +231,7 @@ files:
|
|
|
231
231
|
- lib/dip/commands/infra/service.rb
|
|
232
232
|
- lib/dip/commands/kubectl.rb
|
|
233
233
|
- lib/dip/commands/list.rb
|
|
234
|
+
- lib/dip/commands/preflight.rb
|
|
234
235
|
- lib/dip/commands/provision.rb
|
|
235
236
|
- lib/dip/commands/run.rb
|
|
236
237
|
- lib/dip/commands/runners/base.rb
|