ddenv 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d454d9e8eba496ccf1c073109663cd75eb360317650505ba195f46e35df21330
4
- data.tar.gz: ed0c07ba499cdb8ebbfdb0c24d4d57c64902eb4e5ec50599bed07c97961b1dff
3
+ metadata.gz: ec082036626c59440016bd290efe318994ed5d11affb29c29c74a40fb7bf6f57
4
+ data.tar.gz: 4af215b869b270245f24b97ac688301e6f8b53fac521c4c1c11c15c750279e99
5
5
  SHA512:
6
- metadata.gz: bd6afc63047346551aee1dbea9d9b29895e3f355dbbdfb3638fea312aa05daa658af804b282b6f9ac36d7d0b6b95849162bbbbec881dcd07e863c141aba33d91
7
- data.tar.gz: 3302364fce3c5cfee447a1cffecbf2ed5f691f1821e2b9db8a0a38ae362800cec2b8e0df7dc9f4bae28234ec2ee39c1eaa29f842cc2a7fd473ab09ee60f93584
6
+ metadata.gz: 9eb69dfcc93bc53d2757483eff2f14469666b220487e4356353c37687d1b22c7ff7d58a3c5a308d4565e891d08721fafca7eabc45e9a70958a7af4aecc26792c
7
+ data.tar.gz: '08f42ffb6c4ab4acf25ef12253dbbe5e8c2c8d2b9031562e55f7993e94023143055dddb319e45b2880c646f5c53815352b1cdbb3a98aac455397bc8f049f5ac7'
data/.rubocop.yml CHANGED
@@ -14,3 +14,6 @@ Style/Documentation:
14
14
 
15
15
  Metrics:
16
16
  Enabled: false
17
+
18
+ Naming/MemoizedInstanceVariableName:
19
+ EnforcedStyleForLeadingUnderscores: required
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.1.1] - 2024-04-29
4
+
5
+ - Add functioning `ddenv.yaml` with support for `homebrew` and `ruby` goals.
6
+
3
7
  ## [0.1.0] - 2024-04-28
4
8
 
5
9
  - Initial release
data/README.md CHANGED
@@ -1,39 +1,49 @@
1
- # Ddenv
1
+ # ddenv
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ **ddenv** (*Denis’ Developer Environment*) is a tool for maintaining a local
4
+ environment for development.
4
5
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/ddenv`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+ > [!CAUTION]
7
+ > This software is a pre-alpha work in progress. Do not use just yet.
6
8
 
7
- ## Installation
9
+ ## Requirements
8
10
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
11
+ - Homebrew
12
+ - fish shell
10
13
 
11
- Install the gem and add to the application's Gemfile by executing:
14
+ > [!NOTE]
15
+ > In the future, this will work for bash and zsh as well.
12
16
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
17
+ ## Quick start
14
18
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
19
+ Install it: `brew install denisdefreyne/ddenv/ddenv`.
16
20
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
21
+ Next, create a `ddenv.yaml` file which contains the list of dependencies to manage:
18
22
 
19
- ## Usage
23
+ ```yaml
24
+ up:
25
+ - homebrew: overmind
26
+ - ruby: 3.3.0
27
+ ```
20
28
 
21
- TODO: Write usage instructions here
29
+ Lastly, run `ddenv up`.
22
30
 
23
- ## Development
31
+ ```
32
+ % ddenv up
33
+ [✔] Installing Homebrew package overmind ... done (previously achieved)
34
+ [✔] Installing Homebrew package ruby-install... done (previously achieved)
35
+ [✔] Installing Ruby v3.3.0 ... done (previously achieved)
36
+ [✔] Initializing Shadowenv ... done (previously achieved)
37
+ [✔] Creating .shadowenv.d ... done (previously achieved)
38
+ [✔] Adding .shadowenv.d to .gitignore ... done (previously achieved)
39
+ [✔] Trusting .shadowenv.d ... done (previously achieved)
40
+ [✔] Adding Ruby to shadowenv ... done (previously achieved)
41
+ %
42
+ ```
24
43
 
25
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
44
+ Now your local developer environment is ready to be used.
26
45
 
27
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
46
+ ## Goals
28
47
 
29
- ## Contributing
30
-
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/ddenv. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/ddenv/blob/main/CODE_OF_CONDUCT.md).
32
-
33
- ## License
34
-
35
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
36
-
37
- ## Code of Conduct
38
-
39
- Everyone interacting in the Ddenv project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/ddenv/blob/main/CODE_OF_CONDUCT.md).
48
+ - <code>homebrew: <var>PACKAGENAME</var></code> installs the Homebrew package with the given name.
49
+ - <code>ruby: <var>VERSION</var></code> installs the given version of Ruby.
data/ddenv.yaml ADDED
@@ -0,0 +1,3 @@
1
+ up:
2
+ - homebrew: overmind
3
+ - ruby: 3.3.0
@@ -4,19 +4,26 @@ module Ddenv
4
4
  module Commands
5
5
  class Up < Ddenv::Command
6
6
  def call
7
- config = Ddenv::Config.read_from_file("dev.yml")
7
+ config = Ddenv::Config.read_from_file("ddenv.yaml")
8
+
9
+ all_goals = config.goals.flat_map(&:with_pre_and_post_goals).uniq
10
+
11
+ max_message_size = all_goals.map { _1.message.size }.max
12
+
13
+ all_goals.each do |goal|
14
+ spinner = TTY::Spinner.new("[:spinner] :message... :title")
15
+ spinner.update(message: format("%-#{max_message_size}s", goal.message))
16
+ spinner.update(title: "checking")
17
+ spinner.auto_spin
8
18
 
9
- config.goals.each do |goal|
10
- puts goal.message
11
- puts " Checking..."
12
19
  if goal.achieved?
13
- puts " Already achieved."
20
+ spinner.update(title: "done (previously achieved)")
14
21
  else
15
- puts " Achieving..."
22
+ spinner.update(title: "working...")
16
23
  goal.achieve
17
- puts " Newly achieved."
24
+ spinner.update(title: "done (newly achieved)")
18
25
  end
19
- puts
26
+ spinner.success
20
27
  end
21
28
  end
22
29
  end
data/lib/ddenv/config.rb CHANGED
@@ -26,6 +26,8 @@ module Ddenv
26
26
  case key
27
27
  when "homebrew"
28
28
  Goals::HomebrewPackageInstalled.new(value)
29
+ when "ruby"
30
+ Goals::RubyInstalled.new(value)
29
31
  end
30
32
  end
31
33
  end
data/lib/ddenv/goal.rb CHANGED
@@ -15,5 +15,37 @@ module Ddenv
15
15
  def achieve
16
16
  raise SubclassResponsibilityError.new(self.class, __method__)
17
17
  end
18
+
19
+ def pre_goals
20
+ []
21
+ end
22
+
23
+ def post_goals
24
+ []
25
+ end
26
+
27
+ def with_pre_and_post_goals
28
+ [
29
+ *pre_goals.flat_map(&:with_pre_and_post_goals),
30
+ self,
31
+ *post_goals.flat_map(&:with_pre_and_post_goals)
32
+ ]
33
+ end
34
+
35
+ def props
36
+ []
37
+ end
38
+
39
+ def ==(other)
40
+ self.class == other.class && props == other.props
41
+ end
42
+
43
+ def eql?(other)
44
+ self == other
45
+ end
46
+
47
+ def hash
48
+ [self.class, props].hash
49
+ end
18
50
  end
19
51
  end
@@ -3,6 +3,8 @@
3
3
  module Ddenv
4
4
  module Goals
5
5
  class HomebrewPackageInstalled < Goal
6
+ attr_reader :package_name
7
+
6
8
  def initialize(package_name)
7
9
  super()
8
10
  @package_name = package_name
@@ -21,6 +23,10 @@ module Ddenv
21
23
  cmd = TTY::Command.new(printer: :null)
22
24
  cmd.run("brew", "install", @package_name)
23
25
  end
26
+
27
+ def props
28
+ [@package_name]
29
+ end
24
30
  end
25
31
  end
26
32
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ module RubyInstallInstalled
6
+ def self.new
7
+ Ddenv::Goals::HomebrewPackageInstalled.new("ruby-install")
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ class RubyInstalled < Goal
6
+ def initialize(ruby_version)
7
+ super()
8
+ @ruby_version = ruby_version
9
+ end
10
+
11
+ def message
12
+ "Installing Ruby v#{@ruby_version}"
13
+ end
14
+
15
+ def achieved?
16
+ pathname = Pathname.new(Dir.home) / ".rubies" / "ruby-#{@ruby_version}"
17
+ pathname.directory?
18
+ end
19
+
20
+ def achieve
21
+ # TODO: use :pretty when passing --verbose
22
+ cmd = TTY::Command.new(printer: :null)
23
+ cmd.run("ruby-install", "--cleanup", @ruby_version)
24
+ end
25
+
26
+ def pre_goals
27
+ [
28
+ RubyInstallInstalled.new
29
+ ]
30
+ end
31
+
32
+ def post_goals
33
+ [
34
+ RubyShadowenvCreated.new(ruby_pathname.to_s, @ruby_version)
35
+ ]
36
+ end
37
+
38
+ def props
39
+ [@ruby_version]
40
+ end
41
+
42
+ private
43
+
44
+ def ruby_pathname
45
+ @_ruby_pathname ||= Pathname.new(Dir.home) / ".rubies" / "ruby-#{@ruby_version}"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ class RubyShadowenvCreated < Goal
6
+ PATH = ".shadowenv.d/10_ruby.lisp"
7
+
8
+ def initialize(ruby_version, ruby_path)
9
+ super()
10
+ @ruby_version = ruby_version
11
+ @ruby_path = ruby_path
12
+ end
13
+
14
+ def message
15
+ "Adding Ruby to shadowenv"
16
+ end
17
+
18
+ def achieved?
19
+ File.file?(PATH) && File.read(PATH) == shadowenv_contents
20
+ end
21
+
22
+ def achieve
23
+ File.write(PATH, shadowenv_contents)
24
+
25
+ # TODO: use :pretty when passing --verbose
26
+ cmd = TTY::Command.new(printer: :null)
27
+ cmd.run("shadowenv", "trust")
28
+ end
29
+
30
+ def pre_goals
31
+ [
32
+ Ddenv::Goals::ShadowenvDirCreated.new
33
+ ]
34
+ end
35
+
36
+ private
37
+
38
+ def shadowenv_contents
39
+ <<~CONTENTS
40
+ (provide "ruby" "#{@ruby_version}")
41
+
42
+ (when-let ((ruby-root (env/get "RUBY_ROOT")))
43
+ (env/remove-from-pathlist "PATH" (path-concat ruby-root "bin"))
44
+ (when-let ((gem-root (env/get "GEM_ROOT")))
45
+ (env/remove-from-pathlist "PATH" (path-concat gem-root "bin")))
46
+ (when-let ((gem-home (env/get "GEM_HOME")))
47
+ (env/remove-from-pathlist "PATH" (path-concat gem-home "bin"))))
48
+
49
+ (env/set "GEM_PATH" ())
50
+ (env/set "GEM_HOME" ())
51
+ (env/set "RUBYOPT" ())
52
+
53
+ (env/set "RUBY_ROOT" "#{@ruby_path}")
54
+ (env/prepend-to-pathlist "PATH" "#{@ruby_path}/bin")
55
+ (env/set "RUBY_ENGINE" "ruby")
56
+ (env/set "RUBY_VERSION" "#{@ruby_version}")
57
+ (env/set "GEM_ROOT" "#{@ruby_path}/lib/ruby/gems/#{@ruby_version}")
58
+
59
+ (when-let ((gem-root (env/get "GEM_ROOT")))
60
+ (env/prepend-to-pathlist "GEM_PATH" gem-root)
61
+ (env/prepend-to-pathlist "PATH" (path-concat gem-root "bin")))
62
+
63
+ (let ((gem-home
64
+ (path-concat (env/get "HOME") ".gem" (env/get "RUBY_ENGINE") (env/get "RUBY_VERSION"))))
65
+ (do
66
+ (env/set "GEM_HOME" gem-home)
67
+ (env/prepend-to-pathlist "GEM_PATH" gem-home)
68
+ (env/prepend-to-pathlist "PATH" (path-concat gem-home "bin"))))
69
+ CONTENTS
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ class ShadowenvDirCreated < Goal
6
+ PATH = ".shadowenv.d"
7
+
8
+ def message
9
+ "Creating .shadowenv.d"
10
+ end
11
+
12
+ def achieved?
13
+ Pathname.new(PATH).directory?
14
+ end
15
+
16
+ def achieve
17
+ FileUtils.mkdir_p(PATH)
18
+ end
19
+
20
+ def pre_goals
21
+ [
22
+ Ddenv::Goals::ShadowenvInitialized.new
23
+ ]
24
+ end
25
+
26
+ def post_goals
27
+ [
28
+ Ddenv::Goals::ShadowenvDirGitIgnored.new,
29
+ Ddenv::Goals::ShadowenvTrusted.new
30
+ ]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ class ShadowenvDirGitIgnored < Goal
6
+ PATH = ".shadowenv.d/.gitignore"
7
+ CONTENTS = "*\n"
8
+
9
+ def message
10
+ "Adding .shadowenv.d to .gitignore"
11
+ end
12
+
13
+ def achieved?
14
+ File.file?(PATH) && File.read(PATH) == CONTENTS
15
+ end
16
+
17
+ def achieve
18
+ File.write(PATH, CONTENTS)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ class ShadowenvInitialized < Goal
6
+ FISH_LINE = "shadowenv init fish | source"
7
+
8
+ def message
9
+ "Initializing Shadowenv"
10
+ end
11
+
12
+ # TODO: support bash and zsh
13
+
14
+ def achieved?
15
+ fish_config = File.read(fish_config_path)
16
+ fish_config.lines.any? { _1.chomp == FISH_LINE }
17
+ end
18
+
19
+ def achieve
20
+ File.write(fish_config_path, "\n\n#{FISH_LINE}", mode: "a+")
21
+ end
22
+
23
+ private
24
+
25
+ def fish_config_path
26
+ @_fish_config_path ||= File.expand_path("~/.config/fish/config.fish")
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ddenv
4
+ module Goals
5
+ class ShadowenvTrusted < Goal
6
+ def message
7
+ "Trusting .shadowenv.d"
8
+ end
9
+
10
+ def achieved?
11
+ # TODO: use :pretty when passing --verbose
12
+ cmd = TTY::Command.new(printer: :null)
13
+ begin
14
+ cmd.run("shadowenv", "exec", "--", "ls")
15
+ rescue StandardError
16
+ return false
17
+ end
18
+ true
19
+ end
20
+
21
+ def achieve
22
+ # TODO: use :pretty when passing --verbose
23
+ cmd = TTY::Command.new(printer: :null)
24
+ cmd.run("shadowenv", "trust")
25
+ end
26
+ end
27
+ end
28
+ end
data/lib/ddenv/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ddenv
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
data/lib/ddenv.rb CHANGED
@@ -4,6 +4,7 @@ require "json"
4
4
  require "yaml"
5
5
 
6
6
  require "tty-command"
7
+ require "tty-spinner"
7
8
 
8
9
  require_relative "ddenv/cli"
9
10
  require_relative "ddenv/command"
@@ -17,3 +18,10 @@ require_relative "ddenv/commands/help"
17
18
  require_relative "ddenv/commands/up"
18
19
 
19
20
  require_relative "ddenv/goals/homebrew_package_installed"
21
+ require_relative "ddenv/goals/ruby_install_installed"
22
+ require_relative "ddenv/goals/ruby_installed"
23
+ require_relative "ddenv/goals/ruby_shadowenv_created"
24
+ require_relative "ddenv/goals/shadowenv_initialized"
25
+ require_relative "ddenv/goals/shadowenv_dir_created"
26
+ require_relative "ddenv/goals/shadowenv_dir_git_ignored"
27
+ require_relative "ddenv/goals/shadowenv_trusted"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ddenv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Defreyne
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-spinner
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
27
41
  description: Creates and maintains an environment for local development, including
28
42
  Ruby and Node versions.
29
43
  email:
@@ -40,7 +54,7 @@ files:
40
54
  - LICENSE.txt
41
55
  - README.md
42
56
  - Rakefile
43
- - dev.yml
57
+ - ddenv.yaml
44
58
  - exe/ddenv
45
59
  - lib/ddenv.rb
46
60
  - lib/ddenv/cli.rb
@@ -50,6 +64,13 @@ files:
50
64
  - lib/ddenv/config.rb
51
65
  - lib/ddenv/goal.rb
52
66
  - lib/ddenv/goals/homebrew_package_installed.rb
67
+ - lib/ddenv/goals/ruby_install_installed.rb
68
+ - lib/ddenv/goals/ruby_installed.rb
69
+ - lib/ddenv/goals/ruby_shadowenv_created.rb
70
+ - lib/ddenv/goals/shadowenv_dir_created.rb
71
+ - lib/ddenv/goals/shadowenv_dir_git_ignored.rb
72
+ - lib/ddenv/goals/shadowenv_initialized.rb
73
+ - lib/ddenv/goals/shadowenv_trusted.rb
53
74
  - lib/ddenv/homebrew.rb
54
75
  - lib/ddenv/subclass_responsibility_error.rb
55
76
  - lib/ddenv/version.rb
data/dev.yml DELETED
@@ -1,4 +0,0 @@
1
- up:
2
- - homebrew: vim
3
- - homebrew: font-roboto
4
- - homebrew: font-roboto-mono