Skip to content

Commit

Permalink
Merge pull request #173 from emfy0/implement-modules
Browse files Browse the repository at this point in the history
Modules section for dip
  • Loading branch information
bibendi authored Jul 31, 2024
2 parents 0bea681 + 7fdd65b commit 5a6c659
Show file tree
Hide file tree
Showing 8 changed files with 168 additions and 2 deletions.
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,92 @@ services:

The container will run using the same user ID as your host machine.

### Modules

Modules are defined as array in `modules` section of dip.yml, modules are stored in `.dip` subdirectory of dip.yml directory.

The main purpose of modules is to improve maintainability for a group of projects.
Imagine having multiple gems which are managed with dip, each of them has the same commands, so to change one command in dip you need to update all gems individualy.

With `modules` you can define a group of modules for dip.

For example having setup as this:

```yml
# ./dip.yml
modules:
- sasts
- rails
...
```

```yml
# ./.dip/sasts.yml
interaction:
brakeman:
description: Check brakeman sast
command: docker run ...
```

```yml
# ./.dip/rails.yml
interaction:
annotate:
description: Run annotate command
service: backend
command: bundle exec annotate
```

Will be expanded to:

```yml
# resultant configuration
interaction:
brakeman:
description: Check brakeman sast
command: docker run ...
annotate:
description: Run annotate command
service: backend
command: bundle exec annotate
```

Imagine `.dip` to be a submodule so it can be managed only in one place.

If you want to override module command, you can redefine it in dip.yml

```yml
# ./dip.yml
modules:
- sasts
interaction:
brakeman:
description: Check brakeman sast
command: docker run another-image ...
```

```yml
# ./.dip/sasts.yml
interaction:
brakeman:
description: Check brakeman sast
command: docker run some-image ...
```

Will be expanded to:

```yml
# resultant configuration
interaction:
brakeman:
description: Check brakeman sast
command: docker run another-image ...
```

Nested modules are not supported.

### dip run

Run commands defined within the `interaction` section of dip.yml
Expand Down
30 changes: 28 additions & 2 deletions lib/dip/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ def exist?
file_path&.exist?
end

def modules_dir
file_path.dirname / ".dip"
end

private

attr_reader :override
Expand Down Expand Up @@ -90,6 +94,10 @@ def file_path
finder.file_path
end

def module_file(filename)
finder.modules_dir / "#{filename}.yml"
end

def exist?
finder.exist?
end
Expand Down Expand Up @@ -125,10 +133,28 @@ def config
"Please upgrade your dip!"
end

base_config = {}

if (modules = config[:modules])
raise Dip::Error, "Modules should be specified as array" unless modules.is_a?(Array)

modules.each do |m|
file = module_file(m)
raise Dip::Error, "Could not find module `#{m}`" unless file.exist?

module_config = self.class.load_yaml(file)
raise Dip::Error, "Nested modules are not supported" if module_config[:modules]

base_config.deep_merge!(module_config)
end
end

base_config.deep_merge!(config)

override_finder = ConfigFinder.new(work_dir, override: true)
config.deep_merge!(self.class.load_yaml(override_finder.file_path)) if override_finder.exist?
base_config.deep_merge!(self.class.load_yaml(override_finder.file_path)) if override_finder.exist?

@config = CONFIG_DEFAULTS.merge(config)
@config = CONFIG_DEFAULTS.merge(base_config)
end

def config_missing_error(config_key)
Expand Down
3 changes: 3 additions & 0 deletions spec/fixtures/modules/.dip/first.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interaction:
test_app:
service: test_backend
3 changes: 3 additions & 0 deletions spec/fixtures/modules/.dip/last.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interaction:
test_app:
service: test_frontend
3 changes: 3 additions & 0 deletions spec/fixtures/modules/.dip/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interaction:
app:
service: backend
17 changes: 17 additions & 0 deletions spec/fixtures/modules/dip.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: '2'

modules:
- first
- last
- test

environment:
FOO: bar

compose:
files:
- docker-compose.yml

interaction:
app1:
service: frontend
4 changes: 4 additions & 0 deletions spec/fixtures/unknown_module/dip.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
version: '2'

modules:
- unknown
24 changes: 24 additions & 0 deletions spec/lib/dip/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,30 @@
end
end

context "when config has modules", :env do
let(:env) { {"DIP_FILE" => fixture_path("modules", "dip.yml")} }

it "expands modules to main config" do
expect(subject.interaction[:app][:service]).to eq "backend"
end

it "merges modules to main config" do
expect(subject.interaction[:app1][:service]).to eq "frontend"
end

it "overrides first defined module with the last one" do
expect(subject.interaction[:test_app][:service]).to eq "test_frontend"
end
end

context "when config has unknown module", :env do
let(:env) { {"DIP_FILE" => fixture_path("unknown_module", "dip.yml")} }

it "raises and error" do
expect { subject.interaction }.to raise_error(Dip::Error, /Could not find module/)
end
end

context "when config located two levels higher and overridden at one level higher", :env do
subject { described_class.new(fixture_path("cascade", "sub_a", "sub_b")) }

Expand Down

0 comments on commit 5a6c659

Please sign in to comment.