superconfig 1.0.0 → 2.0.1
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/.github/workflows/ruby-tests.yml +13 -6
- data/.rubocop.yml +0 -3
- data/CHANGELOG.md +6 -2
- data/README.md +42 -1
- data/lib/superconfig.rb +45 -13
- metadata +3 -3
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: fbd7451e326a63df725764a9e0b29dec045b330b499eefefe40437808e0049b0
         | 
| 4 | 
            +
              data.tar.gz: bfa6173594fe005b5a379e3208aaa2df3495ce9abbd25a25d443c8df282a97c9
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e02df280e20253019f4f5d1e2c36df847c48e7057976371b6dd03ad19b873c42c9d2eba90d11a48a4e8cdd7059a7c488e6a986711ebe771d9380f115b96ebc01
         | 
| 7 | 
            +
              data.tar.gz: 9151d646da85061a80cad78aa9ea58391319550e5d72afcf8a7793ebd40ed6f37f0af22932de46f309009fe14c8e6e597e07535a4ee3d2d377b2e983d94fef01
         | 
| @@ -2,8 +2,10 @@ | |
| 2 2 | 
             
            name: ruby-tests
         | 
| 3 3 |  | 
| 4 4 | 
             
            on:
         | 
| 5 | 
            -
               | 
| 5 | 
            +
              pull_request_target:
         | 
| 6 6 | 
             
              push:
         | 
| 7 | 
            +
                branches:
         | 
| 8 | 
            +
                  - main
         | 
| 7 9 | 
             
              workflow_dispatch:
         | 
| 8 10 | 
             
                inputs: {}
         | 
| 9 11 |  | 
| @@ -11,23 +13,28 @@ jobs: | |
| 11 13 | 
             
              build:
         | 
| 12 14 | 
             
                name: Tests with Ruby ${{ matrix.ruby }} and ${{ matrix.gemfile }}
         | 
| 13 15 | 
             
                runs-on: "ubuntu-latest"
         | 
| 16 | 
            +
                if: |
         | 
| 17 | 
            +
                  github.actor == 'dependabot[bot]' && github.event_name == 'pull_request_target' ||
         | 
| 18 | 
            +
                  github.actor != 'dependabot[bot]'
         | 
| 14 19 | 
             
                strategy:
         | 
| 15 20 | 
             
                  fail-fast: false
         | 
| 16 21 | 
             
                  matrix:
         | 
| 17 | 
            -
                    ruby: ["2.7", "3.0"]
         | 
| 22 | 
            +
                    ruby: ["2.7", "3.0", "3.1"]
         | 
| 18 23 | 
             
                    gemfile:
         | 
| 19 24 | 
             
                      - Gemfile
         | 
| 20 25 |  | 
| 21 26 | 
             
                steps:
         | 
| 22 | 
            -
                  - uses: actions/checkout@ | 
| 27 | 
            +
                  - uses: actions/checkout@v3
         | 
| 23 28 |  | 
| 24 | 
            -
                  - uses: actions/cache@ | 
| 29 | 
            +
                  - uses: actions/cache@v3
         | 
| 25 30 | 
             
                    with:
         | 
| 26 31 | 
             
                      path: vendor/bundle
         | 
| 27 32 | 
             
                      key: >
         | 
| 28 | 
            -
                        ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ | 
| 33 | 
            +
                        ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
         | 
| 34 | 
            +
                        hashFiles(matrix.gemfile) }}
         | 
| 29 35 | 
             
                      restore-keys: >
         | 
| 30 | 
            -
                        ${{ runner.os }}-${{ matrix.ruby }}-gems-${{ | 
| 36 | 
            +
                        ${{ runner.os }}-${{ matrix.ruby }}-gems-${{
         | 
| 37 | 
            +
                        hashFiles(matrix.gemfile) }}
         | 
| 31 38 |  | 
| 32 39 | 
             
                  - name: Set up Ruby
         | 
| 33 40 | 
             
                    uses: ruby/setup-ruby@v1
         | 
    
        data/.rubocop.yml
    CHANGED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -11,6 +11,10 @@ Prefix your message with one of the following: | |
| 11 11 | 
             
            - [Security] in case of vulnerabilities.
         | 
| 12 12 | 
             
            -->
         | 
| 13 13 |  | 
| 14 | 
            -
            ##  | 
| 14 | 
            +
            ## v2.0.1
         | 
| 15 15 |  | 
| 16 | 
            -
            -  | 
| 16 | 
            +
            - [Changed] Ensure bad JSON strings doesn't leak it's contents.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ## v2.0.0
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            - Initial release.
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            
         | 
| 2 2 |  | 
| 3 3 | 
             
            <p align="center">
         | 
| 4 | 
            -
              <a href="https://github.com/fnando/superconfig/actions/workflows/tests.yml"><img src="https://github.com/fnando/superconfig/workflows/ | 
| 4 | 
            +
              <a href="https://github.com/fnando/superconfig/actions/workflows/ruby-tests.yml"><img src="https://github.com/fnando/superconfig/workflows/ruby-tests/badge.svg" alt="Github Actions"></a>
         | 
| 5 5 | 
             
              <a href="https://codeclimate.com/github/fnando/superconfig"><img src="https://codeclimate.com/github/fnando/superconfig/badges/gpa.svg" alt="Code Climate"></a>
         | 
| 6 6 | 
             
              <a href="https://rubygems.org/gems/superconfig"><img src="https://img.shields.io/gem/v/superconfig.svg" alt="Gem"></a>
         | 
| 7 7 | 
             
              <a href="https://rubygems.org/gems/superconfig"><img src="https://img.shields.io/gem/dt/superconfig.svg" alt="Gem"></a>
         | 
| @@ -118,6 +118,47 @@ You can coerce values to the following types: | |
| 118 118 | 
             
            - `json`: E.g. `mandatory :keyring, json`. The environment variable must be
         | 
| 119 119 | 
             
              parseable by `JSON.parse(content)`.
         | 
| 120 120 |  | 
| 121 | 
            +
            ### Report
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            Sometimes it gets hard to understand what's set and what's not. In this case,
         | 
| 124 | 
            +
            you can get a report by calling `SuperConfig::Base#report`. If you're using
         | 
| 125 | 
            +
            Rails, you can create a rake task like this:
         | 
| 126 | 
            +
             | 
| 127 | 
            +
            ```ruby
         | 
| 128 | 
            +
            # frozen_string_literal: true
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            desc "Show SuperConfig report"
         | 
| 131 | 
            +
            task superconfig: [:environment] do
         | 
| 132 | 
            +
              puts YourAppNamespace::Config.report
         | 
| 133 | 
            +
            end
         | 
| 134 | 
            +
            ```
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            Then, change your configuration so it doesn't raise an exception.
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            ```ruby
         | 
| 139 | 
            +
            # frozen_string_literal: true
         | 
| 140 | 
            +
            # file: config/config.rb
         | 
| 141 | 
            +
             | 
| 142 | 
            +
            module YourAppNamespace
         | 
| 143 | 
            +
              Config = SuperConfig.new(raise_exception: false) do
         | 
| 144 | 
            +
                mandatory :database_url, string
         | 
| 145 | 
            +
                optional :app_name, string
         | 
| 146 | 
            +
                optional :wait, string
         | 
| 147 | 
            +
                optional :force_ssl, bool, true
         | 
| 148 | 
            +
              end
         | 
| 149 | 
            +
            end
         | 
| 150 | 
            +
            ```
         | 
| 151 | 
            +
             | 
| 152 | 
            +
            Finally, run the following command:
         | 
| 153 | 
            +
             | 
| 154 | 
            +
            ```console
         | 
| 155 | 
            +
            $ rails superconfig
         | 
| 156 | 
            +
            ❌ DATABASE_URL is not set (mandatory)
         | 
| 157 | 
            +
            ✅ APP_NAME is set (optional)
         | 
| 158 | 
            +
            ⚠️ WAIT is not set (optional)
         | 
| 159 | 
            +
            ✅ FORCE_SSL is not set, but has default value (optional)
         | 
| 160 | 
            +
            ```
         | 
| 161 | 
            +
             | 
| 121 162 | 
             
            ### Dotenv integration
         | 
| 122 163 |  | 
| 123 164 | 
             
            If you're using [dotenv](https://rubygems.org/gems/dotenv), you can simply
         | 
    
        data/lib/superconfig.rb
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            module SuperConfig
         | 
| 4 | 
            -
              VERSION = " | 
| 4 | 
            +
              VERSION = "2.0.1"
         | 
| 5 5 |  | 
| 6 6 | 
             
              MissingEnvironmentVariable = Class.new(StandardError)
         | 
| 7 7 | 
             
              MissingCallable = Class.new(StandardError)
         | 
| @@ -18,6 +18,7 @@ module SuperConfig | |
| 18 18 | 
             
                  @env = env
         | 
| 19 19 | 
             
                  @raise_exception = raise_exception
         | 
| 20 20 | 
             
                  @stderr = stderr
         | 
| 21 | 
            +
                  @attributes = {}
         | 
| 21 22 | 
             
                  @__cache__ = {}
         | 
| 22 23 | 
             
                  instance_eval(&block)
         | 
| 23 24 | 
             
                end
         | 
| @@ -37,6 +38,9 @@ module SuperConfig | |
| 37 38 | 
             
                )
         | 
| 38 39 | 
             
                  name = name.to_s
         | 
| 39 40 | 
             
                  env_var = name.upcase
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  @attributes[env_var] = {required: required, default: default}
         | 
| 43 | 
            +
             | 
| 40 44 | 
             
                  name = "#{name}?" if type == bool
         | 
| 41 45 |  | 
| 42 46 | 
             
                  validate!(env_var, required, description)
         | 
| @@ -44,7 +48,7 @@ module SuperConfig | |
| 44 48 | 
             
                  define_singleton_method(name) do
         | 
| 45 49 | 
             
                    return default unless @env.key?(env_var)
         | 
| 46 50 |  | 
| 47 | 
            -
                    coerce(type, @env[env_var])
         | 
| 51 | 
            +
                    coerce(env_var, type, @env[env_var])
         | 
| 48 52 | 
             
                  end
         | 
| 49 53 |  | 
| 50 54 | 
             
                  aliases.each do |alias_name|
         | 
| @@ -139,41 +143,69 @@ module SuperConfig | |
| 139 143 | 
             
                  :json
         | 
| 140 144 | 
             
                end
         | 
| 141 145 |  | 
| 142 | 
            -
                 | 
| 146 | 
            +
                def report
         | 
| 147 | 
            +
                  attrs = @attributes.sort
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  report = attrs.each_with_object([]) do |(env_var, info), buffer|
         | 
| 150 | 
            +
                    icon, message = if @env.key?(env_var)
         | 
| 151 | 
            +
                                      ["✅", "is set"]
         | 
| 152 | 
            +
                                    elsif info[:required]
         | 
| 153 | 
            +
                                      ["❌", "is not set"]
         | 
| 154 | 
            +
                                    elsif !info[:required] && !info[:default].nil?
         | 
| 155 | 
            +
                                      ["✅", "is not set, but has default value"]
         | 
| 156 | 
            +
                                    else
         | 
| 157 | 
            +
                                      ["⚠️", "is not set"]
         | 
| 158 | 
            +
                                    end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                    label = if info[:required]
         | 
| 161 | 
            +
                              "mandatory"
         | 
| 162 | 
            +
                            else
         | 
| 163 | 
            +
                              "optional"
         | 
| 164 | 
            +
                            end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                    buffer << [icon, env_var, message, "(#{label})"].join(" ")
         | 
| 167 | 
            +
                  end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  "#{report.join("\n")}\n"
         | 
| 170 | 
            +
                end
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                private def coerce_to_string(_name, value)
         | 
| 143 173 | 
             
                  value
         | 
| 144 174 | 
             
                end
         | 
| 145 175 |  | 
| 146 | 
            -
                private def coerce_to_bool(value)
         | 
| 176 | 
            +
                private def coerce_to_bool(_name, value)
         | 
| 147 177 | 
             
                  BOOL_TRUE.include?(value)
         | 
| 148 178 | 
             
                end
         | 
| 149 179 |  | 
| 150 | 
            -
                private def coerce_to_int(value)
         | 
| 180 | 
            +
                private def coerce_to_int(_name, value)
         | 
| 151 181 | 
             
                  Integer(value) if !BOOL_FALSE.include?(value) && value
         | 
| 152 182 | 
             
                end
         | 
| 153 183 |  | 
| 154 | 
            -
                private def coerce_to_float(value)
         | 
| 184 | 
            +
                private def coerce_to_float(_name, value)
         | 
| 155 185 | 
             
                  Float(value) if value
         | 
| 156 186 | 
             
                end
         | 
| 157 187 |  | 
| 158 | 
            -
                private def coerce_to_bigdecimal(value)
         | 
| 188 | 
            +
                private def coerce_to_bigdecimal(_name, value)
         | 
| 159 189 | 
             
                  BigDecimal(value) if value
         | 
| 160 190 | 
             
                end
         | 
| 161 191 |  | 
| 162 | 
            -
                private def coerce_to_symbol(value)
         | 
| 192 | 
            +
                private def coerce_to_symbol(_name, value)
         | 
| 163 193 | 
             
                  value&.to_sym
         | 
| 164 194 | 
             
                end
         | 
| 165 195 |  | 
| 166 | 
            -
                private def coerce_to_array(value, type)
         | 
| 167 | 
            -
                  value&.split(/, */)&.map {|v| coerce(type, v) }
         | 
| 196 | 
            +
                private def coerce_to_array(name, value, type)
         | 
| 197 | 
            +
                  value&.split(/, */)&.map {|v| coerce(name, type, v) }
         | 
| 168 198 | 
             
                end
         | 
| 169 199 |  | 
| 170 | 
            -
                private def coerce_to_json(value)
         | 
| 200 | 
            +
                private def coerce_to_json(name, value)
         | 
| 171 201 | 
             
                  value && JSON.parse(value)
         | 
| 202 | 
            +
                rescue JSON::ParserError
         | 
| 203 | 
            +
                  raise ArgumentError, "#{name} is not a valid JSON string"
         | 
| 172 204 | 
             
                end
         | 
| 173 205 |  | 
| 174 | 
            -
                private def coerce(type, value)
         | 
| 206 | 
            +
                private def coerce(name, type, value)
         | 
| 175 207 | 
             
                  main_type, sub_type = type
         | 
| 176 | 
            -
                  args = [value]
         | 
| 208 | 
            +
                  args = [name, value]
         | 
| 177 209 | 
             
                  args << sub_type if sub_type
         | 
| 178 210 |  | 
| 179 211 | 
             
                  send("coerce_to_#{main_type}", *args)
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: superconfig
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 2.0.1
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Nando Vieira
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 11 | 
            +
            date: 2023-02-15 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -184,7 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 184 184 | 
             
                - !ruby/object:Gem::Version
         | 
| 185 185 | 
             
                  version: '0'
         | 
| 186 186 | 
             
            requirements: []
         | 
| 187 | 
            -
            rubygems_version: 3. | 
| 187 | 
            +
            rubygems_version: 3.4.6
         | 
| 188 188 | 
             
            signing_key:
         | 
| 189 189 | 
             
            specification_version: 4
         | 
| 190 190 | 
             
            summary: Access environment variables. Also includes presence validation, type coercion
         |