gem_enforcer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +29 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +23 -0
- data/CODEOWNERS +1 -0
- data/Dockerfile +15 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +101 -0
- data/Makefile +21 -0
- data/README.md +33 -0
- data/bin/console +11 -0
- data/docker-compose.yml +15 -0
- data/gem_enforcer.gemspec +40 -0
- data/gem_enforcer.yml +61 -0
- data/lib/gem_enforcer/configuration.rb +37 -0
- data/lib/gem_enforcer/errors.rb +6 -0
- data/lib/gem_enforcer/retrieve/gem_server.rb +35 -0
- data/lib/gem_enforcer/retrieve/git_tag.rb +28 -0
- data/lib/gem_enforcer/retrieve.rb +28 -0
- data/lib/gem_enforcer/setup/helper/on_failure.rb +58 -0
- data/lib/gem_enforcer/setup/helper/retrieval.rb +60 -0
- data/lib/gem_enforcer/setup/helper/version.rb +151 -0
- data/lib/gem_enforcer/setup/validate.rb +64 -0
- data/lib/gem_enforcer/setup.rb +41 -0
- data/lib/gem_enforcer/version.rb +5 -0
- data/lib/gem_enforcer.rb +32 -0
- metadata +171 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 259683929871f4f3ba6aabed1d4730837860fd2fe0c983f19baf735da1be2edc
|
4
|
+
data.tar.gz: 962e62bd2f891d48b4abf50efe0e44fbb4d43938ef745189c075c5753ca86faf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 86b8b4f2755007c7f1973c2dc844066b4060cc0eb1729906cdabcbd3ad91d17eed1274be1bc3c26a01d6c5459ed660cd547657409b25b844b45d7dc75919e8e0
|
7
|
+
data.tar.gz: debf1f1abd7668a5a36413ee1156b69bba9b0a8d0cb0f4bfd16801c5db74cb58d66e3175a5b1e92d21d1df216a8cebe7da9a0b3db996152aaafef450304d2a4d
|
@@ -0,0 +1,29 @@
|
|
1
|
+
version: 2.1
|
2
|
+
|
3
|
+
orbs:
|
4
|
+
ruby: circleci/ruby@1.0
|
5
|
+
node: circleci/node@2
|
6
|
+
cst: cst/framework@1
|
7
|
+
|
8
|
+
workflows:
|
9
|
+
version: 2
|
10
|
+
yeet-le-jobs:
|
11
|
+
jobs:
|
12
|
+
- cst/enforce-gem-version-bump
|
13
|
+
- cst/rspec-ruby:
|
14
|
+
rspec-system-args: "SIMPLE_COV_RUN=true"
|
15
|
+
cc-report-collect-ruby: "3.2.5"
|
16
|
+
matrix:
|
17
|
+
parameters:
|
18
|
+
ruby-version: ["3.2.5", "3.3.5"]
|
19
|
+
alias: required-matrix-tests
|
20
|
+
name: test-ruby<< matrix.ruby-version >>
|
21
|
+
- cst/publish-gem:
|
22
|
+
publish-git: true
|
23
|
+
publish-default-gem: true
|
24
|
+
requires:
|
25
|
+
- required-matrix-tests
|
26
|
+
filters:
|
27
|
+
branches:
|
28
|
+
only:
|
29
|
+
- main
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.4
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [Unreleased]
|
9
|
+
|
10
|
+
## [X.y.z] - YYYY-MM-DD
|
11
|
+
|
12
|
+
### Added
|
13
|
+
|
14
|
+
### Changed
|
15
|
+
- Changed feature 1
|
16
|
+
|
17
|
+
### Removed
|
18
|
+
- Removed feature 1
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
- Bug fix 1
|
22
|
+
|
23
|
+
[//]: # (Added, Changed, Removed, Fixed are the possible headers for each changlog version)
|
data/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @matt-taylor
|
data/Dockerfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
FROM ruby:3.2.5
|
2
|
+
RUN cd /tmp && curl -L --output ghr.tar.gz https://github.com/tcnksm/ghr/releases/download/v0.12.0/ghr_v0.12.0_linux_amd64.tar.gz && \
|
3
|
+
tar -xzvf ghr.tar.gz && chmod +x ghr_v0.12.0_linux_amd64/ghr && mv ghr_v0.12.0_linux_amd64/ghr /usr/local/bin/ghr && rm -rf /tmp/*
|
4
|
+
|
5
|
+
WORKDIR /gem
|
6
|
+
COPY Gemfile /gem/Gemfile
|
7
|
+
|
8
|
+
COPY gem_enforcer.gemspec /gem/gem_enforcer.gemspec
|
9
|
+
COPY lib/gem_enforcer/version.rb /gem/lib/gem_enforcer/version.rb
|
10
|
+
|
11
|
+
|
12
|
+
RUN gem update --system && gem install bundler && bundle install --jobs=3 --retry=3 && \
|
13
|
+
rm -rf /usr/local/bundle/cache
|
14
|
+
|
15
|
+
COPY . /gem
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
gem "faraday", "< 2.6"
|
8
|
+
gem 'activesupport'
|
9
|
+
gem 'faker'
|
10
|
+
gem 'pry'
|
11
|
+
gem 'rspec', '~> 3.0'
|
12
|
+
gem 'rspec_junit_formatter'
|
13
|
+
gem 'simplecov', require: false, group: :test
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
gem_enforcer (0.0.1)
|
5
|
+
class_composer (>= 1.0)
|
6
|
+
faraday
|
7
|
+
octokit
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (7.1.4)
|
13
|
+
base64
|
14
|
+
bigdecimal
|
15
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
16
|
+
connection_pool (>= 2.2.5)
|
17
|
+
drb
|
18
|
+
i18n (>= 1.6, < 2)
|
19
|
+
minitest (>= 5.1)
|
20
|
+
mutex_m
|
21
|
+
tzinfo (~> 2.0)
|
22
|
+
addressable (2.8.7)
|
23
|
+
public_suffix (>= 2.0.2, < 7.0)
|
24
|
+
base64 (0.2.0)
|
25
|
+
bigdecimal (3.1.8)
|
26
|
+
byebug (11.1.3)
|
27
|
+
class_composer (1.0.2)
|
28
|
+
coderay (1.1.3)
|
29
|
+
concurrent-ruby (1.3.4)
|
30
|
+
connection_pool (2.4.1)
|
31
|
+
diff-lcs (1.5.1)
|
32
|
+
docile (1.4.1)
|
33
|
+
drb (2.2.1)
|
34
|
+
faker (3.4.2)
|
35
|
+
i18n (>= 1.8.11, < 2)
|
36
|
+
faraday (2.5.2)
|
37
|
+
faraday-net_http (>= 2.0, < 3.1)
|
38
|
+
ruby2_keywords (>= 0.0.4)
|
39
|
+
faraday-net_http (3.0.2)
|
40
|
+
i18n (1.14.5)
|
41
|
+
concurrent-ruby (~> 1.0)
|
42
|
+
method_source (1.1.0)
|
43
|
+
minitest (5.25.1)
|
44
|
+
mutex_m (0.2.0)
|
45
|
+
octokit (9.1.0)
|
46
|
+
faraday (>= 1, < 3)
|
47
|
+
sawyer (~> 0.9)
|
48
|
+
pry (0.14.2)
|
49
|
+
coderay (~> 1.1)
|
50
|
+
method_source (~> 1.0)
|
51
|
+
pry-byebug (3.10.1)
|
52
|
+
byebug (~> 11.0)
|
53
|
+
pry (>= 0.13, < 0.15)
|
54
|
+
public_suffix (6.0.1)
|
55
|
+
rake (12.3.3)
|
56
|
+
rspec (3.13.0)
|
57
|
+
rspec-core (~> 3.13.0)
|
58
|
+
rspec-expectations (~> 3.13.0)
|
59
|
+
rspec-mocks (~> 3.13.0)
|
60
|
+
rspec-core (3.13.1)
|
61
|
+
rspec-support (~> 3.13.0)
|
62
|
+
rspec-expectations (3.13.3)
|
63
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
64
|
+
rspec-support (~> 3.13.0)
|
65
|
+
rspec-mocks (3.13.1)
|
66
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
+
rspec-support (~> 3.13.0)
|
68
|
+
rspec-support (3.13.1)
|
69
|
+
rspec_junit_formatter (0.6.0)
|
70
|
+
rspec-core (>= 2, < 4, != 2.12.0)
|
71
|
+
ruby2_keywords (0.0.5)
|
72
|
+
sawyer (0.9.2)
|
73
|
+
addressable (>= 2.3.5)
|
74
|
+
faraday (>= 0.17.3, < 3)
|
75
|
+
simplecov (0.22.0)
|
76
|
+
docile (~> 1.1)
|
77
|
+
simplecov-html (~> 0.11)
|
78
|
+
simplecov_json_formatter (~> 0.1)
|
79
|
+
simplecov-html (0.13.0)
|
80
|
+
simplecov_json_formatter (0.1.4)
|
81
|
+
tzinfo (2.0.6)
|
82
|
+
concurrent-ruby (~> 1.0)
|
83
|
+
|
84
|
+
PLATFORMS
|
85
|
+
aarch64-linux
|
86
|
+
ruby
|
87
|
+
|
88
|
+
DEPENDENCIES
|
89
|
+
activesupport
|
90
|
+
faker
|
91
|
+
faraday (< 2.6)
|
92
|
+
gem_enforcer!
|
93
|
+
pry
|
94
|
+
pry-byebug
|
95
|
+
rake (~> 12.0)
|
96
|
+
rspec (~> 3.0)
|
97
|
+
rspec_junit_formatter
|
98
|
+
simplecov
|
99
|
+
|
100
|
+
BUNDLED WITH
|
101
|
+
2.5.18
|
data/Makefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
.PHONY: bash build bundle rspec
|
2
|
+
|
3
|
+
APP_NAME?=gem_enforcer
|
4
|
+
|
5
|
+
build: #: Build the containers that we'll need
|
6
|
+
docker-compose build --pull
|
7
|
+
|
8
|
+
bash: #: Get a bash prompt on the core container
|
9
|
+
docker-compose run --rm -e RAILS_ENV=development $(APP_NAME) bash
|
10
|
+
|
11
|
+
bash_test: #: Get a test bash prompt on the core container
|
12
|
+
docker-compose run --rm -e RAILS_ENV=test $(APP_NAME) bash
|
13
|
+
|
14
|
+
down: #: Bring down the service -- Destroys everything in redis and all containers
|
15
|
+
docker-compose down
|
16
|
+
|
17
|
+
clean: #: Clean up stopped/exited containers
|
18
|
+
docker-compose rm -f
|
19
|
+
|
20
|
+
bundle: #: install gems for Dummy App with
|
21
|
+
docker-compose run --rm $(APP_NAME) bundle install
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# GemEnforcer
|
2
|
+
|
3
|
+
`GemEnforcer` is
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'gem_enforcer'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install gem_enforcer
|
20
|
+
|
21
|
+
|
22
|
+
## Development
|
23
|
+
|
24
|
+
This gem can be developed against local machine or while using docker. Simpleified Docker commands can be found in the `Makefile` or execute `make help`
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
This gem welcomes contribution.
|
29
|
+
|
30
|
+
Bug reports and pull requests are welcome on GitHub at
|
31
|
+
https://github.com/matt-taylor/json_schematize.
|
32
|
+
|
33
|
+
|
data/bin/console
ADDED
data/docker-compose.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
services:
|
2
|
+
gem_enforcer:
|
3
|
+
command: tail -f /dev/null
|
4
|
+
build:
|
5
|
+
context: .
|
6
|
+
dockerfile: ./Dockerfile
|
7
|
+
volumes:
|
8
|
+
- .:/gem
|
9
|
+
- ..:/local
|
10
|
+
- bundle-cache:/usr/local/bundle:delegated
|
11
|
+
environment:
|
12
|
+
GITHUB_TOKEN: ${GITHUB_TOKEN}
|
13
|
+
|
14
|
+
volumes:
|
15
|
+
bundle-cache:
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/gem_enforcer/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "gem_enforcer"
|
7
|
+
spec.version = GemEnforcer::VERSION
|
8
|
+
spec.authors = ["Matt Taylor"]
|
9
|
+
spec.email = ["mattius.taylor@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Long form of the description"
|
12
|
+
spec.description = "Provide the ability to validate targetted gems are up to date before executing commands"
|
13
|
+
spec.homepage = "https://github.com/matt-taylor/gem_enforcer"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.2")
|
17
|
+
|
18
|
+
spec.metadata = {
|
19
|
+
"homepage_uri" => spec.homepage,
|
20
|
+
"source_code_uri" => spec.homepage,
|
21
|
+
}
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
%x(git ls-files -z).split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_dependency "class_composer", ">= 1.0"
|
33
|
+
spec.add_dependency "faraday"
|
34
|
+
spec.add_dependency "octokit"
|
35
|
+
|
36
|
+
spec.add_development_dependency "pry-byebug"
|
37
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
39
|
+
spec.add_development_dependency "simplecov", "~> 0.17.0"
|
40
|
+
end
|
data/gem_enforcer.yml
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
---
|
2
|
+
invalid_config:
|
3
|
+
log_level: error
|
4
|
+
behavior: exit
|
5
|
+
gems:
|
6
|
+
rails:
|
7
|
+
on_failure:
|
8
|
+
log_level: warn # on failure, log a warn message
|
9
|
+
behavior: exit
|
10
|
+
version_threshold:
|
11
|
+
minor: 3 # within the last 3 minor releases
|
12
|
+
server: true # when set to true, defaults to https://rubygems.org
|
13
|
+
|
14
|
+
shoryuken:
|
15
|
+
on_failure:
|
16
|
+
log_level: info # on failure, log a info message
|
17
|
+
behavior: skip
|
18
|
+
version_threshold:
|
19
|
+
# Must be within the most current version released
|
20
|
+
# If above is true, must be within the last 2 minor releases
|
21
|
+
# If above is true, must be within the last 3 patches released
|
22
|
+
major: 0 # within the current major version
|
23
|
+
minor: 2 # within the last 3 minor releases
|
24
|
+
patch: 3 # within the last 3 patches released
|
25
|
+
server: true # when set to true, defaults to https://rubygems.org
|
26
|
+
|
27
|
+
redis:
|
28
|
+
on_failure:
|
29
|
+
log_level: error
|
30
|
+
behavior: raise # on failure, log error and exit(1)
|
31
|
+
enforce_insync: true # Ensure gem is up to date
|
32
|
+
server:
|
33
|
+
source: https://rubygems.org
|
34
|
+
|
35
|
+
faraday:
|
36
|
+
on_failure:
|
37
|
+
log_level: error
|
38
|
+
behavior: exit # on failure, log error and exit(1)
|
39
|
+
enforce_insync: true
|
40
|
+
# version_threshold:
|
41
|
+
|
42
|
+
# For most gems, this is effectively the same as `enforce_insync: true`
|
43
|
+
# major: 0
|
44
|
+
# minor: 6
|
45
|
+
# patch: 0
|
46
|
+
server:
|
47
|
+
source: https://rubygems.org
|
48
|
+
|
49
|
+
custom_gem:
|
50
|
+
enforce_insync: true
|
51
|
+
server: true
|
52
|
+
sidekiq:
|
53
|
+
version_threshold:
|
54
|
+
releases: 5 # within the last 5 releases
|
55
|
+
git:
|
56
|
+
owner: sidekiq # Github root page for the gem
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "class_composer"
|
4
|
+
require "logger"
|
5
|
+
require "gem_enforcer/errors"
|
6
|
+
|
7
|
+
module GemEnforcer
|
8
|
+
class Configuration
|
9
|
+
include ClassComposer::Generator
|
10
|
+
|
11
|
+
GITHUB_ACCESS_TOKEN = Proc.new do
|
12
|
+
token = ENV.fetch("GITHUB_TOKEN") do
|
13
|
+
ENV.fetch("BUNDLE_GITHUB__COM") do
|
14
|
+
raise GemEnforcer::Error, "Expected access token in `GITHUB_TOKEN` or `BUNDLE_GITHUB__COM`"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
if token.end_with?(":x-oauth-basic")
|
18
|
+
token.split(":x-oauth-basic")[0]
|
19
|
+
else
|
20
|
+
token
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
DEFAULT_YAML_PATH = Proc.new do
|
25
|
+
if defined?(Rails)
|
26
|
+
"#{Rails.root}/config/gem_enforcer.yml"
|
27
|
+
else
|
28
|
+
"/gem/gem_enforcer.yml"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
add_composer :github_access_token, allowed: String, default: GITHUB_ACCESS_TOKEN.()
|
33
|
+
add_composer :yml_config_path, allowed: String, default: DEFAULT_YAML_PATH.()
|
34
|
+
add_composer :raise_on_invalid_config, allowed: [TrueClass, FalseClass], default: true
|
35
|
+
add_composer :logger, allowed: [Logger, (TTY::Logger if defined?(TTY::Logger))].compact, default: Logger.new(STDOUT)
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "faraday"
|
4
|
+
|
5
|
+
module GemEnforcer
|
6
|
+
module Retrieve
|
7
|
+
class GemServer
|
8
|
+
def initialize(source: DEFAULT_SOURCE)
|
9
|
+
@source = source
|
10
|
+
end
|
11
|
+
|
12
|
+
def gem_versions(name:)
|
13
|
+
raw_gem_versions = raw_server_versions.select { _1.match?(/^#{name} /) }
|
14
|
+
return [] if raw_gem_versions.nil? || raw_gem_versions.empty?
|
15
|
+
|
16
|
+
versions = raw_gem_versions.map do |metadata|
|
17
|
+
raw_name, raw_version_list, _sha = metadata.split(" ")
|
18
|
+
next if raw_name != name
|
19
|
+
|
20
|
+
raw_version_list.split(",").map { Gem::Version.new(_1) }
|
21
|
+
end.flatten.compact.uniq
|
22
|
+
|
23
|
+
versions
|
24
|
+
end
|
25
|
+
|
26
|
+
# expensive call .. do this once gem source
|
27
|
+
def raw_server_versions
|
28
|
+
@server_versions ||= begin
|
29
|
+
api_call = Faraday.new(url: @source).get("versions")
|
30
|
+
api_call.body.split("\n")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "octokit"
|
4
|
+
|
5
|
+
module GemEnforcer
|
6
|
+
module Retrieve
|
7
|
+
class GitTag
|
8
|
+
def initialize(owner:, access_token: GemEnforcer.github_access_token)
|
9
|
+
@access_token = access_token
|
10
|
+
@owner = owner
|
11
|
+
end
|
12
|
+
|
13
|
+
def gem_versions(name:)
|
14
|
+
repo_name = "#{@owner}/#{name}"
|
15
|
+
releases = client.releases(repo_name, { per_page: 50 })
|
16
|
+
while next_page_href = client.last_response.rels[:next]&.href
|
17
|
+
releases.concat(client.get(next_page_href, { per_page: 50 }))
|
18
|
+
end
|
19
|
+
|
20
|
+
releases.map { Gem::Version.new(_1.tag_name.gsub(/.*?(?=\d*\.)/im, "")) }.compact
|
21
|
+
end
|
22
|
+
|
23
|
+
def client
|
24
|
+
@client ||= ::Octokit::Client.new(access_token: @access_token)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "gem_enforcer/retrieve/gem_server"
|
4
|
+
require "gem_enforcer/retrieve/git_tag"
|
5
|
+
|
6
|
+
module GemEnforcer
|
7
|
+
module Retrieve
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def server_retrieval_by_source(source:)
|
11
|
+
@server_retrieval_by_source ||= {}
|
12
|
+
|
13
|
+
return @server_retrieval_by_source[source] if @server_retrieval_by_source[source]
|
14
|
+
|
15
|
+
@server_retrieval_by_source[source] = GemServer.new(source: source)
|
16
|
+
@server_retrieval_by_source[source]
|
17
|
+
end
|
18
|
+
|
19
|
+
def github_retrieval_by_owner(owner:)
|
20
|
+
@github_retrieval_by_owner ||= {}
|
21
|
+
|
22
|
+
return @github_retrieval_by_owner[owner] if @github_retrieval_by_owner[owner]
|
23
|
+
|
24
|
+
@github_retrieval_by_owner[owner] = GitTag.new(owner: owner)
|
25
|
+
@github_retrieval_by_owner[owner]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GemEnforcer
|
4
|
+
module Setup
|
5
|
+
module Helper
|
6
|
+
module OnFailure
|
7
|
+
ALLOWED_ON_FAILURE = [:raise, :exit, DEFAULT_BEHAVIOR = :none]
|
8
|
+
DEFAULT_LOG_LEVEL = :error
|
9
|
+
|
10
|
+
def validate_on_failure
|
11
|
+
on_failure = params["on_failure"]
|
12
|
+
if on_failure.nil?
|
13
|
+
@on_failure_log_level = DEFAULT_LOG_LEVEL
|
14
|
+
@on_failure_behavior = DEFAULT_BEHAVIOR
|
15
|
+
return true
|
16
|
+
end
|
17
|
+
|
18
|
+
if Hash === on_failure
|
19
|
+
@on_failure_log_level = on_failure.fetch("log_level", DEFAULT_LOG_LEVEL)
|
20
|
+
behavior = on_failure.fetch("behavior", DEFAULT_BEHAVIOR).to_sym rescue nil
|
21
|
+
if ALLOWED_ON_FAILURE.include?(behavior)
|
22
|
+
@on_failure_behavior = behavior
|
23
|
+
return true
|
24
|
+
else
|
25
|
+
errors << "on_failure.behavior: Expected behavior to be in #{ALLOWED_ON_FAILURE}"
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
errors << "on_failure: Expected value hash with :behavior and/or :log_level keys"
|
31
|
+
false
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_failure_default_message
|
35
|
+
message = params.dig("on_failure", "message") rescue nil
|
36
|
+
return message if message
|
37
|
+
|
38
|
+
version_default_message
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_failure_behavior(msg:)
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
def execute_on_failure!(behavior:, msg: on_failure_default_message)
|
46
|
+
GemEnforcer.logger.public_send(@on_failure_log_level, "Validation failed for #{gem_name}. Current Version is #{current_version}. #{msg}")
|
47
|
+
|
48
|
+
case @on_failure_behavior.to_sym
|
49
|
+
when :raise
|
50
|
+
raise ValidationError, "Validation failed for #{gem_name}. Current Version is #{current_version}. #{msg}"
|
51
|
+
when :exit
|
52
|
+
Kernel.exit(1)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GemEnforcer
|
4
|
+
module Setup
|
5
|
+
module Helper
|
6
|
+
module Retrieval
|
7
|
+
def validate_retrieval
|
8
|
+
if params["server"]
|
9
|
+
@retrieval_method = :server
|
10
|
+
server_result = _server_validate
|
11
|
+
@factory_version_list = Retrieve.server_retrieval_by_source(source: @retrieval_source)
|
12
|
+
|
13
|
+
server_result
|
14
|
+
elsif params["git"]
|
15
|
+
@retrieval_method = :git
|
16
|
+
git_result = _git_validate
|
17
|
+
@factory_version_list = Retrieve.github_retrieval_by_owner(owner: @retrieval_owner)
|
18
|
+
|
19
|
+
git_result
|
20
|
+
else
|
21
|
+
errors << "retrieval: Missing retrieval type. Expected `server` or `git`"
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def retrieve_version_list
|
27
|
+
@factory_version_list.gem_versions(name: @gem_name).sort
|
28
|
+
end
|
29
|
+
|
30
|
+
def _server_validate
|
31
|
+
server = params.dig("server")
|
32
|
+
|
33
|
+
if server == true
|
34
|
+
@retrieval_source = GemEnforcer::DEFAULT_SERVER_SOURCE
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
|
38
|
+
if Hash === server && server["source"]
|
39
|
+
@retrieval_source = server["source"]
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
|
43
|
+
errors << "retrieval.server: Missing source"
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def _git_validate
|
48
|
+
git = params.dig("git")
|
49
|
+
if Hash === git && git["owner"]
|
50
|
+
@retrieval_owner = git["owner"]
|
51
|
+
return true
|
52
|
+
end
|
53
|
+
|
54
|
+
errors << "retrieval.git: Missing owner"
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GemEnforcer
|
4
|
+
module Setup
|
5
|
+
module Helper
|
6
|
+
module Version
|
7
|
+
ALLOWED_VERSION_REALEASE = :releases
|
8
|
+
ALLOWED_VERSION_SEMVER = [:major, :minor, :patch]
|
9
|
+
ALLOWED_VERSION_THRESHOLD_KEYS = [ALLOWED_VERSION_REALEASE, *ALLOWED_VERSION_SEMVER]
|
10
|
+
|
11
|
+
def version_default_message
|
12
|
+
@default_version_message
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate_version
|
16
|
+
if params.keys.include?("enforce_insync") && params.keys.include?("version_threshold")
|
17
|
+
errors << "version: Must only contain `enforce_insync` or `version_threshold`"
|
18
|
+
return false
|
19
|
+
end
|
20
|
+
|
21
|
+
if params["enforce_insync"]
|
22
|
+
@version_type = :enforce_insync
|
23
|
+
@default_version_message = "Version must be the most recently released version."
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
|
27
|
+
@version_type = :version_threshold
|
28
|
+
version_threshold_keys = params["version_threshold"]&.keys || []
|
29
|
+
if version_threshold_keys.sort == [ALLOWED_VERSION_REALEASE.to_s].sort
|
30
|
+
@version_threshold = :releases
|
31
|
+
@default_version_message = "Version must be within #{params["version_threshold"]["releases"]} of the most recently released versions"
|
32
|
+
_releases_validate
|
33
|
+
elsif ALLOWED_VERSION_THRESHOLD_KEYS.any? { version_threshold_keys.include?(_1.to_s) }
|
34
|
+
@version_threshold = :semver
|
35
|
+
message = []
|
36
|
+
message << "#{params["version_threshold"]["major"]} major versions" if params["version_threshold"]["major"]
|
37
|
+
message << "#{params["version_threshold"]["minor"]} minor versions" if params["version_threshold"]["minor"]
|
38
|
+
message << "#{params["version_threshold"]["patch"]} patch versions" if params["version_threshold"]["patch"]
|
39
|
+
@default_version_message = "Version must be within #{message.join(" and ")} of the most recent release."
|
40
|
+
_semver_validate
|
41
|
+
else
|
42
|
+
errors << "version.version_threshold: Expected keys to contain [#{ALLOWED_VERSION_REALEASE}] or #{ALLOWED_VERSION_SEMVER}"
|
43
|
+
false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def _semver_validate
|
48
|
+
boolean = true
|
49
|
+
if major = params["version_threshold"]["major"]
|
50
|
+
unless Integer === major
|
51
|
+
boolean = false
|
52
|
+
errors << "version.version_threshold.major: Expected value to be an Integer"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if minor = params["version_threshold"]["minor"]
|
57
|
+
unless Integer === minor
|
58
|
+
boolean = false
|
59
|
+
errors << "version.version_threshold.minor: Expected value to be an Integer"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
if patch = params["version_threshold"]["patch"]
|
64
|
+
unless Integer === patch
|
65
|
+
boolean = false
|
66
|
+
errors << "version.version_threshold.patch: Expected value to be an Integer"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
boolean
|
71
|
+
end
|
72
|
+
|
73
|
+
def _releases_validate
|
74
|
+
release_count = params["version_threshold"]["releases"]
|
75
|
+
unless Integer === release_count
|
76
|
+
errors << "version.version_threshold.releases: Expected value to be an Integer"
|
77
|
+
return false
|
78
|
+
end
|
79
|
+
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def version_execute?(version_list:)
|
84
|
+
if @version_type == :enforce_insync
|
85
|
+
__validate_enforce_insync?(version_list:)
|
86
|
+
else
|
87
|
+
if @version_threshold == :releases
|
88
|
+
__validate_version_threshold_releases?(version_list:)
|
89
|
+
else
|
90
|
+
__validate_version_threshold_semver?(version_list:)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def __validate_version_threshold_semver?(version_list:)
|
96
|
+
if max_major_versions_behind = params.dig("version_threshold", "major")
|
97
|
+
return false unless __threshold_semver_distance(type: :major, number: current_version.segments[0], list: version_list.map { _1.segments[0] }, threshold: max_major_versions_behind)
|
98
|
+
end
|
99
|
+
|
100
|
+
if max_minor_versions_behind = params.dig("version_threshold", "minor")
|
101
|
+
# Select only the minor versions that match the major version
|
102
|
+
current_major_version = current_version.segments[0]
|
103
|
+
minor_version_check_list = version_list.select { _1.segments[0] == current_major_version }.map { _1.segments[1] }
|
104
|
+
return false unless __threshold_semver_distance(type: :minor, number: current_version.segments[1], list: minor_version_check_list, threshold: max_minor_versions_behind)
|
105
|
+
end
|
106
|
+
|
107
|
+
if max_patch_versions_behind = params.dig("version_threshold", "patch")
|
108
|
+
# Select only the patch versions that match the major version
|
109
|
+
current_major_minor_version = current_version.segments[0..1]
|
110
|
+
patch_version_check_list = version_list.select { _1.segments[0..1] == current_major_minor_version }.map { _1.segments[2] }
|
111
|
+
return false unless __threshold_semver_distance(type: :patch, number: current_version.segments[2], list: patch_version_check_list, threshold: max_patch_versions_behind)
|
112
|
+
end
|
113
|
+
|
114
|
+
true
|
115
|
+
end
|
116
|
+
|
117
|
+
def __threshold_semver_distance(type:, number:, list:, threshold:)
|
118
|
+
# remove duplicates ans sort in highest to lowest number
|
119
|
+
uniq_list = list.uniq.sort.reverse
|
120
|
+
|
121
|
+
# get the position in the sorted array
|
122
|
+
position_in_sorted_array = uniq_list.find_index(number)
|
123
|
+
|
124
|
+
# if position is less than or equal to the threshold, we are good
|
125
|
+
# otherwise, it is out of compliance
|
126
|
+
return true if position_in_sorted_array <= threshold
|
127
|
+
|
128
|
+
@default_version_message += " Failed to match #{type} version threshold"
|
129
|
+
|
130
|
+
false
|
131
|
+
end
|
132
|
+
|
133
|
+
def __validate_version_threshold_releases?(version_list:)
|
134
|
+
releases_behind = params.dig("version_threshold", "releases").to_i
|
135
|
+
|
136
|
+
min_version_allowed = version_list[-releases_behind]
|
137
|
+
current_version >= min_version_allowed
|
138
|
+
end
|
139
|
+
|
140
|
+
def __validate_enforce_insync?(version_list:)
|
141
|
+
max_version = version_list.max
|
142
|
+
return true if current_version >= max_version
|
143
|
+
|
144
|
+
@default_version_message += " Please upgrade to at least v#{max_version}"
|
145
|
+
|
146
|
+
false
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
require "gem_enforcer/setup/helper/retrieval"
|
6
|
+
require "gem_enforcer/setup/helper/on_failure"
|
7
|
+
require "gem_enforcer/setup/helper/version"
|
8
|
+
|
9
|
+
module GemEnforcer
|
10
|
+
module Setup
|
11
|
+
class Validate
|
12
|
+
attr_reader :gem_name, :params, :validation_status
|
13
|
+
|
14
|
+
include Helper::Retrieval
|
15
|
+
include Helper::OnFailure
|
16
|
+
include Helper::Version
|
17
|
+
|
18
|
+
def initialize(name:, **params)
|
19
|
+
@params = params
|
20
|
+
@gem_name = name
|
21
|
+
|
22
|
+
@validation_status = validate!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Allow behavior to be overridden if desired
|
26
|
+
def run_validation!(behavior: nil)
|
27
|
+
unless validation_status
|
28
|
+
raise Error, "Unable to run validation with invalid config."
|
29
|
+
end
|
30
|
+
|
31
|
+
return true if current_version.nil?
|
32
|
+
|
33
|
+
return true if version_execute?(version_list: retrieve_version_list)
|
34
|
+
|
35
|
+
execute_on_failure!(behavior: behavior)
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_version
|
40
|
+
Gem.loaded_specs[gem_name]&.version
|
41
|
+
end
|
42
|
+
|
43
|
+
def error_status
|
44
|
+
return nil if errors.empty?
|
45
|
+
|
46
|
+
errors.map { "#{gem_name}.#{_1}" }
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def errors
|
52
|
+
@errors ||= []
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate!
|
56
|
+
boolean = validate_retrieval
|
57
|
+
boolean &= validate_on_failure
|
58
|
+
boolean &= validate_version
|
59
|
+
|
60
|
+
boolean
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "gem_enforcer/setup/validate"
|
5
|
+
|
6
|
+
module GemEnforcer
|
7
|
+
module Setup
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def validate_yml!
|
11
|
+
errors = config_yml["gems"].map do |name, metadata|
|
12
|
+
validator = Validate.new(name: name, **metadata)
|
13
|
+
validations << validator
|
14
|
+
|
15
|
+
validator.error_status
|
16
|
+
end.compact
|
17
|
+
return true if errors.empty?
|
18
|
+
|
19
|
+
log_level = config_yml.dig("invalid_config", "log_level") || "error"
|
20
|
+
behavior = config_yml.dig("invalid_config", "behavior") || "exit"
|
21
|
+
end
|
22
|
+
|
23
|
+
def validations
|
24
|
+
@validations ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
def run_validations!(behavior: nil)
|
28
|
+
validations.each { _1.run_validation!(behavior: behavior) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def config_yml
|
32
|
+
@read_config_yml ||= begin
|
33
|
+
path = GemEnforcer.configuration.yml_config_path
|
34
|
+
file = File.read(path)
|
35
|
+
erb = ERB.new(file)
|
36
|
+
|
37
|
+
YAML.load(erb.result)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/gem_enforcer.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "gem_enforcer/configuration"
|
4
|
+
require "gem_enforcer/errors"
|
5
|
+
require "gem_enforcer/retrieve"
|
6
|
+
require "gem_enforcer/setup"
|
7
|
+
require "gem_enforcer/version"
|
8
|
+
|
9
|
+
module GemEnforcer
|
10
|
+
DEFAULT_SERVER_SOURCE = "https://rubygems.org"
|
11
|
+
def self.configure
|
12
|
+
yield configuration if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configuration
|
16
|
+
@configuration ||= GemEnforcer::Configuration.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configuration=(object)
|
20
|
+
raise ConfigError, "Expected configuration to be a GemEnforcer::Configuration" unless object.is_a?(GemEnforcer::Configuration)
|
21
|
+
|
22
|
+
@configuration = object
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.github_access_token
|
26
|
+
configuration.github_access_token
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.logger
|
30
|
+
configuration.logger
|
31
|
+
end
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gem_enforcer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt Taylor
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-09-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: class_composer
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: octokit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry-byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '12.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '12.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.17.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.17.0
|
111
|
+
description: Provide the ability to validate targetted gems are up to date before
|
112
|
+
executing commands
|
113
|
+
email:
|
114
|
+
- mattius.taylor@gmail.com
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".circleci/config.yml"
|
120
|
+
- ".gitignore"
|
121
|
+
- ".rspec"
|
122
|
+
- ".ruby-version"
|
123
|
+
- CHANGELOG.md
|
124
|
+
- CODEOWNERS
|
125
|
+
- Dockerfile
|
126
|
+
- Gemfile
|
127
|
+
- Gemfile.lock
|
128
|
+
- Makefile
|
129
|
+
- README.md
|
130
|
+
- bin/console
|
131
|
+
- docker-compose.yml
|
132
|
+
- gem_enforcer.gemspec
|
133
|
+
- gem_enforcer.yml
|
134
|
+
- lib/gem_enforcer.rb
|
135
|
+
- lib/gem_enforcer/configuration.rb
|
136
|
+
- lib/gem_enforcer/errors.rb
|
137
|
+
- lib/gem_enforcer/retrieve.rb
|
138
|
+
- lib/gem_enforcer/retrieve/gem_server.rb
|
139
|
+
- lib/gem_enforcer/retrieve/git_tag.rb
|
140
|
+
- lib/gem_enforcer/setup.rb
|
141
|
+
- lib/gem_enforcer/setup/helper/on_failure.rb
|
142
|
+
- lib/gem_enforcer/setup/helper/retrieval.rb
|
143
|
+
- lib/gem_enforcer/setup/helper/version.rb
|
144
|
+
- lib/gem_enforcer/setup/validate.rb
|
145
|
+
- lib/gem_enforcer/version.rb
|
146
|
+
homepage: https://github.com/matt-taylor/gem_enforcer
|
147
|
+
licenses:
|
148
|
+
- MIT
|
149
|
+
metadata:
|
150
|
+
homepage_uri: https://github.com/matt-taylor/gem_enforcer
|
151
|
+
source_code_uri: https://github.com/matt-taylor/gem_enforcer
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '3.2'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubygems_version: 3.5.9
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: Long form of the description
|
171
|
+
test_files: []
|