up
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "6",
|
||||
"ruby.observation.packages": "9",
|
||||
"ruby.observation.ruby_version": "3.2.0",
|
||||
"ruby.observation.runtime_edges": "0"
|
||||
},
|
||||
"evidence": [
|
||||
@@ -20,8 +21,8 @@
|
||||
"kind": "derived",
|
||||
"source": "ruby.observation",
|
||||
"locator": "document",
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022bundler\u0022,\u0022version\u0022:\u00222.5.3\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022development\u0022]},{\u0022name\u0022:\u0022pastel\u0022,\u0022version\u0022:\u00220.8.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022thor\u0022,\u0022version\u0022:\u00221.3.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-color\u0022,\u0022version\u0022:\u00220.6.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-cursor\u0022,\u0022version\u0022:\u00220.7.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-prompt\u0022,\u0022version\u0022:\u00220.23.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-reader\u0022,\u0022version\u0022:\u00220.9.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-screen\u0022,\u0022version\u0022:\u00220.8.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022wisper\u0022,\u0022version\u0022:\u00222.0.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]}],\u0022entrypoints\u0022:[],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/pastel@0.8.0\u0022,\u0022to\u0022:\u0022tty-color\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.5\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-prompt@0.23.1\u0022,\u0022to\u0022:\u0022pastel\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.8\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-prompt@0.23.1\u0022,\u0022to\u0022:\u0022tty-reader\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.8\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-reader@0.9.0\u0022,\u0022to\u0022:\u0022tty-cursor\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.7\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-reader@0.9.0\u0022,\u0022to\u0022:\u0022tty-screen\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.8\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-reader@0.9.0\u0022,\u0022to\u0022:\u0022wisper\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022}],\u0022runtimeEdges\u0022:[],\u0022environment\u0022:{\u0022bundlerVersion\u0022:\u00222.5.3\u0022,\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:false,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[]},\u0022bundledWith\u0022:\u00222.5.3\u0022}",
|
||||
"sha256": "sha256:5ec8b45dc480086cefbee03575845d57fb9fe4a0b000b109af46af5f2fe3f05d"
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022bundler\u0022,\u0022version\u0022:\u00222.5.3\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022development\u0022]},{\u0022name\u0022:\u0022pastel\u0022,\u0022version\u0022:\u00220.8.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022thor\u0022,\u0022version\u0022:\u00221.3.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-color\u0022,\u0022version\u0022:\u00220.6.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-cursor\u0022,\u0022version\u0022:\u00220.7.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-prompt\u0022,\u0022version\u0022:\u00220.23.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-reader\u0022,\u0022version\u0022:\u00220.9.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022tty-screen\u0022,\u0022version\u0022:\u00220.8.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022wisper\u0022,\u0022version\u0022:\u00222.0.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]}],\u0022entrypoints\u0022:[],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/pastel@0.8.0\u0022,\u0022to\u0022:\u0022tty-color\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.5\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-prompt@0.23.1\u0022,\u0022to\u0022:\u0022pastel\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.8\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-prompt@0.23.1\u0022,\u0022to\u0022:\u0022tty-reader\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.8\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-reader@0.9.0\u0022,\u0022to\u0022:\u0022tty-cursor\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.7\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-reader@0.9.0\u0022,\u0022to\u0022:\u0022tty-screen\u0022,\u0022constraint\u0022:\u0022~\\u003E 0.8\u0022},{\u0022from\u0022:\u0022pkg:gem/tty-reader@0.9.0\u0022,\u0022to\u0022:\u0022wisper\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022}],\u0022runtimeEdges\u0022:[],\u0022environment\u0022:{\u0022rubyVersion\u0022:\u00223.2.0\u0022,\u0022bundlerVersion\u0022:\u00222.5.3\u0022,\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022rubyVersionSources\u0022:[{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022Gemfile\u0022,\u0022sourceType\u0022:\u0022gemfile\u0022}]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:false,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[]},\u0022bundledWith\u0022:\u00222.5.3\u0022}",
|
||||
"sha256": "sha256:b8346ca01f40135f4a8de7ae73a601b621e228473b26516cfda65cc046d7a7c4"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
"kind": "derived",
|
||||
"source": "ruby.observation",
|
||||
"locator": "document",
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022version\u0022:\u00223.0.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022ops\u0022]},{\u0022name\u0022:\u0022pagy\u0022,\u0022version\u0022:\u00226.5.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022web\u0022]},{\u0022name\u0022:\u0022pry\u0022,\u0022version\u0022:\u00220.14.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022tools\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.1.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022version\u0022:\u00227.2.1\u0022,\u0022source\u0022:\u0022vendor\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/custom-bundle/cache/sidekiq-7.2.1.gem\u0022,\u0022groups\u0022:[\u0022jobs\u0022]},{\u0022name\u0022:\u0022sinatra\u0022,\u0022version\u0022:\u00223.1.0\u0022,\u0022source\u0022:\u0022vendor-cache\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/cache/sinatra-3.1.0.gem\u0022,\u0022groups\u0022:[\u0022web\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022config/environment.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022pagy\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022coderay\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.1\u0022},{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022method_source\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sidekiq@7.2.1\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sinatra@3.1.0\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 3.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022clockwork\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pagy\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app/main.rb\u0022,\u0022config/environment.rb\u0022],\u0022entrypoints\u0022:[\u0022config/environment.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sidekiq\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sinatra\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022environment\u0022:{\u0022bundlerVersion\u0022:\u00222.5.3\u0022,\u0022bundlePaths\u0022:[\u0022/mnt/e/dev/git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/bin/Debug/net10.0/Fixtures/lang/ruby/complex-app/vendor/custom-bundle\u0022],\u0022gemfiles\u0022:[\u0022/mnt/e/dev/git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/bin/Debug/net10.0/Fixtures/lang/ruby/complex-app/Gemfile\u0022],\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022frameworks\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:true,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022bundledWith\u0022:\u00222.5.3\u0022}",
|
||||
"sha256": "sha256:58c8c02011baf8711e584a4b8e33effe7292a92af69cd6eaad6c3fd869ea93e0"
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022version\u0022:\u00223.0.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022ops\u0022]},{\u0022name\u0022:\u0022pagy\u0022,\u0022version\u0022:\u00226.5.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022web\u0022]},{\u0022name\u0022:\u0022pry\u0022,\u0022version\u0022:\u00220.14.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022tools\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.1.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022version\u0022:\u00227.2.1\u0022,\u0022source\u0022:\u0022vendor\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/custom-bundle/cache/sidekiq-7.2.1.gem\u0022,\u0022groups\u0022:[\u0022jobs\u0022]},{\u0022name\u0022:\u0022sinatra\u0022,\u0022version\u0022:\u00223.1.0\u0022,\u0022source\u0022:\u0022vendor-cache\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/cache/sinatra-3.1.0.gem\u0022,\u0022groups\u0022:[\u0022web\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022config/environment.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022pagy\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022coderay\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.1\u0022},{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022method_source\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sidekiq@7.2.1\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sinatra@3.1.0\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 3.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022clockwork\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pagy\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app/main.rb\u0022,\u0022config/environment.rb\u0022],\u0022entrypoints\u0022:[\u0022config/environment.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sidekiq\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sinatra\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022jobs\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022type\u0022:\u0022scheduler\u0022,\u0022scheduler\u0022:\u0022clockwork\u0022},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022type\u0022:\u0022scheduler\u0022,\u0022scheduler\u0022:\u0022sidekiq\u0022}],\u0022environment\u0022:{\u0022bundlerVersion\u0022:\u00222.5.3\u0022,\u0022bundlePaths\u0022:[\u0022/mnt/e/dev/git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/bin/Debug/net10.0/Fixtures/lang/ruby/complex-app/vendor/custom-bundle\u0022],\u0022gemfiles\u0022:[\u0022/mnt/e/dev/git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/bin/Debug/net10.0/Fixtures/lang/ruby/complex-app/Gemfile\u0022],\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022frameworks\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:true,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022bundledWith\u0022:\u00222.5.3\u0022}",
|
||||
"sha256": "sha256:bd15160e034ea5adf0a8384dc9ee18557f695b0952d4fb17214f1bd1381ad22a"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
3.2.0
|
||||
@@ -0,0 +1,2 @@
|
||||
ruby 3.2.0
|
||||
nodejs 20.10.0
|
||||
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
source "https://rubygems.org"
|
||||
|
||||
ruby "3.2.0"
|
||||
|
||||
gem "nokogiri", "~> 1.15"
|
||||
gem "pg", "~> 1.5"
|
||||
gem "puma", "~> 6.0"
|
||||
gem "rack", "~> 3.0"
|
||||
@@ -0,0 +1,29 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
mini_portile2 (2.8.4)
|
||||
nio4r (2.5.9)
|
||||
nokogiri (1.15.0)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
pg (1.5.4)
|
||||
puma (6.4.0)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.7.1)
|
||||
rack (3.0.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
nokogiri (~> 1.15)
|
||||
pg (~> 1.5)
|
||||
puma (~> 6.0)
|
||||
rack (~> 3.0)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.2.0p0
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.22
|
||||
@@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
require "rack"
|
||||
require "nokogiri"
|
||||
require "pg"
|
||||
|
||||
class App
|
||||
def call(env)
|
||||
[200, { "Content-Type" => "text/plain" }, ["Hello from container"]]
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
require "rack"
|
||||
require_relative "app"
|
||||
|
||||
run App
|
||||
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
workers ENV.fetch("WEB_CONCURRENCY", 2)
|
||||
threads_count = ENV.fetch("RAILS_MAX_THREADS", 5)
|
||||
threads threads_count, threads_count
|
||||
|
||||
preload_app!
|
||||
|
||||
port ENV.fetch("PORT", 3000)
|
||||
environment ENV.fetch("RACK_ENV", "development")
|
||||
@@ -0,0 +1,197 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "observation::ruby",
|
||||
"name": "Ruby Observation Summary",
|
||||
"type": "ruby-observation",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"ruby.observation.bundler_version": "2.4.22",
|
||||
"ruby.observation.capability.exec": "false",
|
||||
"ruby.observation.capability.net": "false",
|
||||
"ruby.observation.capability.schedulers": "0",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "3",
|
||||
"ruby.observation.packages": "7",
|
||||
"ruby.observation.ruby_version": "3.2.0",
|
||||
"ruby.observation.runtime_edges": "3",
|
||||
"ruby.observation.web_server_types": "puma",
|
||||
"ruby.observation.web_servers": "1"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "derived",
|
||||
"source": "ruby.observation",
|
||||
"locator": "document",
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022mini_portile2\u0022,\u0022version\u0022:\u00222.8.4\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022nio4r\u0022,\u0022version\u0022:\u00222.5.9\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022nokogiri\u0022,\u0022version\u0022:\u00221.15.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022pg\u0022,\u0022version\u0022:\u00221.5.4\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022puma\u0022,\u0022version\u0022:\u00226.4.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022racc\u0022,\u0022version\u0022:\u00221.7.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.0.8\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022app.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022nokogiri\u0022,\u0022pg\u0022,\u0022rack\u0022]},{\u0022path\u0022:\u0022config.ru\u0022,\u0022type\u0022:\u0022rack\u0022,\u0022requiredGems\u0022:[\u0022rack\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/nokogiri@1.15.0\u0022,\u0022to\u0022:\u0022mini_portile2\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.8.2\u0022},{\u0022from\u0022:\u0022pkg:gem/nokogiri@1.15.0\u0022,\u0022to\u0022:\u0022racc\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.4\u0022},{\u0022from\u0022:\u0022pkg:gem/puma@6.4.0\u0022,\u0022to\u0022:\u0022nio4r\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022nokogiri\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pg\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022,\u0022config.ru\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022,\u0022config.ru\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022configs\u0022:[{\u0022name\u0022:\u0022puma\u0022,\u0022type\u0022:\u0022web-server\u0022,\u0022filePath\u0022:\u0022config/puma.rb\u0022,\u0022settings\u0022:{\u0022preload_app\u0022:\u0022true\u0022}}],\u0022environment\u0022:{\u0022rubyVersion\u0022:\u00223.2.0\u0022,\u0022bundlerVersion\u0022:\u00222.4.22\u0022,\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022rubyVersionSources\u0022:[{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022.ruby-version\u0022,\u0022sourceType\u0022:\u0022ruby-version\u0022},{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022.tool-versions\u0022,\u0022sourceType\u0022:\u0022tool-versions\u0022},{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022Gemfile\u0022,\u0022sourceType\u0022:\u0022gemfile\u0022}],\u0022webServers\u0022:[{\u0022serverType\u0022:\u0022puma\u0022,\u0022configPath\u0022:\u0022config/puma.rb\u0022,\u0022settings\u0022:{\u0022preload_app\u0022:\u0022true\u0022}}]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:false,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[]},\u0022bundledWith\u0022:\u00222.4.22\u0022}",
|
||||
"sha256": "sha256:d5c7da885e1d05805981e2080c9023cd653ed464e993d5e48de6b9f55334eca7"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/mini_portile2@2.8.4",
|
||||
"purl": "pkg:gem/mini_portile2@2.8.4",
|
||||
"name": "mini_portile2",
|
||||
"version": "2.8.4",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/nio4r@2.5.9",
|
||||
"purl": "pkg:gem/nio4r@2.5.9",
|
||||
"name": "nio4r",
|
||||
"version": "2.5.9",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/nokogiri@1.15.0",
|
||||
"purl": "pkg:gem/nokogiri@1.15.0",
|
||||
"name": "nokogiri",
|
||||
"version": "1.15.0",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"runtime.entrypoints": "app.rb",
|
||||
"runtime.files": "app.rb",
|
||||
"runtime.reasons": "require-static",
|
||||
"runtime.used": "true",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/pg@1.5.4",
|
||||
"purl": "pkg:gem/pg@1.5.4",
|
||||
"name": "pg",
|
||||
"version": "1.5.4",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"runtime.entrypoints": "app.rb",
|
||||
"runtime.files": "app.rb",
|
||||
"runtime.reasons": "require-static",
|
||||
"runtime.used": "true",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/puma@6.4.0",
|
||||
"purl": "pkg:gem/puma@6.4.0",
|
||||
"name": "puma",
|
||||
"version": "6.4.0",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/racc@1.7.1",
|
||||
"purl": "pkg:gem/racc@1.7.1",
|
||||
"name": "racc",
|
||||
"version": "1.7.1",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "purl::pkg:gem/rack@3.0.8",
|
||||
"purl": "pkg:gem/rack@3.0.8",
|
||||
"name": "rack",
|
||||
"version": "3.0.8",
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"declaredOnly": "true",
|
||||
"groups": "default",
|
||||
"lockfile": "Gemfile.lock",
|
||||
"runtime.entrypoints": "app.rb;config.ru",
|
||||
"runtime.files": "app.rb;config.ru",
|
||||
"runtime.reasons": "require-static",
|
||||
"runtime.used": "true",
|
||||
"source": "https://rubygems.org/"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "Gemfile.lock",
|
||||
"locator": "Gemfile.lock"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1 @@
|
||||
ELF-fake-native-extension
|
||||
@@ -0,0 +1 @@
|
||||
ELF-fake-native-extension
|
||||
@@ -0,0 +1,14 @@
|
||||
# Rakefile for legacy app
|
||||
require 'rake'
|
||||
|
||||
desc "Run the application"
|
||||
task :run do
|
||||
ruby 'app.rb'
|
||||
end
|
||||
|
||||
desc "Run tests"
|
||||
task :test do
|
||||
sh 'ruby -Ilib test/*.rb'
|
||||
end
|
||||
|
||||
task default: :run
|
||||
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env ruby
|
||||
# Old-style Ruby app without Bundler
|
||||
require 'rubygems'
|
||||
require 'net/http'
|
||||
require 'json'
|
||||
require 'yaml'
|
||||
require_relative 'lib/helper'
|
||||
|
||||
class LegacyApp
|
||||
def run
|
||||
data = load_config
|
||||
process(data)
|
||||
end
|
||||
|
||||
def load_config
|
||||
YAML.load_file('config.yml')
|
||||
end
|
||||
|
||||
def process(data)
|
||||
uri = URI.parse(data['endpoint'])
|
||||
Net::HTTP.get(uri)
|
||||
end
|
||||
end
|
||||
|
||||
LegacyApp.new.run if __FILE__ == $0
|
||||
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -0,0 +1,14 @@
|
||||
# Helper module
|
||||
require 'fileutils'
|
||||
require 'open3'
|
||||
|
||||
module Helper
|
||||
def self.execute(cmd)
|
||||
stdout, stderr, status = Open3.capture3(cmd)
|
||||
{ stdout: stdout, stderr: stderr, success: status.success? }
|
||||
end
|
||||
|
||||
def self.copy_file(src, dest)
|
||||
FileUtils.cp(src, dest)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
# frozen_string_literal: true
|
||||
source "https://rubygems.org"
|
||||
|
||||
ruby "3.2.0"
|
||||
|
||||
gem "rails", "~> 7.1.0"
|
||||
gem "pg", "~> 1.5"
|
||||
gem "puma", "~> 6.0"
|
||||
gem "redis", "~> 5.0"
|
||||
|
||||
group :development, :test do
|
||||
gem "rspec-rails", "~> 6.0"
|
||||
gem "factory_bot_rails", "~> 6.2"
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem "rubocop-rails", "~> 2.21"
|
||||
end
|
||||
|
||||
group :production do
|
||||
gem "newrelic_rpm", "~> 9.0"
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (7.1.0)
|
||||
actionpack (= 7.1.0)
|
||||
actionpack (7.1.0)
|
||||
activesupport (= 7.1.0)
|
||||
rack (~> 3.0)
|
||||
activesupport (7.1.0)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
concurrent-ruby (1.2.2)
|
||||
factory_bot (6.2.1)
|
||||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
newrelic_rpm (9.6.0)
|
||||
nio4r (2.5.9)
|
||||
pg (1.5.4)
|
||||
puma (6.4.0)
|
||||
nio4r (~> 2.0)
|
||||
rack (3.0.8)
|
||||
rails (7.1.0)
|
||||
actioncable (= 7.1.0)
|
||||
actionpack (= 7.1.0)
|
||||
activesupport (= 7.1.0)
|
||||
redis (5.0.8)
|
||||
rspec (3.12.0)
|
||||
rspec-rails (6.0.3)
|
||||
rspec (~> 3.12)
|
||||
rubocop (1.57.2)
|
||||
rubocop-rails (2.21.2)
|
||||
rubocop (~> 1.33)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
factory_bot_rails (~> 6.2)
|
||||
newrelic_rpm (~> 9.0)
|
||||
pg (~> 1.5)
|
||||
puma (~> 6.0)
|
||||
rails (~> 7.1.0)
|
||||
redis (~> 5.0)
|
||||
rspec-rails (~> 6.0)
|
||||
rubocop-rails (~> 2.21)
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.2.0p0
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.22
|
||||
@@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
require "action_controller"
|
||||
require "redis"
|
||||
require "pg"
|
||||
|
||||
class ApplicationController < ActionController::Base
|
||||
before_action :authenticate_user!
|
||||
|
||||
private
|
||||
|
||||
def authenticate_user!
|
||||
# Authentication logic
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
# frozen_string_literal: true
|
||||
require_relative "config/environment"
|
||||
run Rails.application
|
||||
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
require "rails"
|
||||
require "action_controller/railtie"
|
||||
|
||||
module RailsApp
|
||||
class Application < Rails::Application
|
||||
config.load_defaults 7.1
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
# frozen_string_literal: true
|
||||
Rails.application.routes.draw do
|
||||
root "home#index"
|
||||
|
||||
resources :users do
|
||||
member do
|
||||
post :activate
|
||||
end
|
||||
end
|
||||
|
||||
namespace :api do
|
||||
namespace :v1 do
|
||||
resources :products, only: [:index, :show, :create]
|
||||
end
|
||||
end
|
||||
|
||||
get "/health", to: "health#check"
|
||||
end
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "sinatra", "~> 3.1"
|
||||
gem "sinatra-contrib", "~> 3.1"
|
||||
gem "puma", "~> 6.0"
|
||||
gem "rack", "~> 3.0"
|
||||
|
||||
group :development do
|
||||
gem "sinatra-reloader", "~> 1.0"
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
mustermann (3.0.0)
|
||||
ruby2_keywords (~> 0.0.1)
|
||||
nio4r (2.5.9)
|
||||
puma (6.4.0)
|
||||
nio4r (~> 2.0)
|
||||
rack (3.0.8)
|
||||
rack-protection (3.1.0)
|
||||
rack (~> 3.0)
|
||||
rack-session (2.0.0)
|
||||
rack (>= 3.0.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
sinatra (3.1.0)
|
||||
mustermann (~> 3.0)
|
||||
rack (~> 3.0)
|
||||
rack-protection (= 3.1.0)
|
||||
rack-session (>= 2.0.0, < 3)
|
||||
tilt (~> 2.0)
|
||||
sinatra-contrib (3.1.0)
|
||||
sinatra (= 3.1.0)
|
||||
tilt (~> 2.0)
|
||||
sinatra-reloader (1.0)
|
||||
sinatra (>= 1.4)
|
||||
tilt (2.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
puma (~> 6.0)
|
||||
rack (~> 3.0)
|
||||
sinatra (~> 3.1)
|
||||
sinatra-contrib (~> 3.1)
|
||||
sinatra-reloader (~> 1.0)
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.22
|
||||
@@ -0,0 +1,25 @@
|
||||
# frozen_string_literal: true
|
||||
require "sinatra/base"
|
||||
require "sinatra/json"
|
||||
require "json"
|
||||
|
||||
class SinatraApp < Sinatra::Base
|
||||
get "/" do
|
||||
"Hello World"
|
||||
end
|
||||
|
||||
get "/api/users" do
|
||||
content_type :json
|
||||
{ users: [] }.to_json
|
||||
end
|
||||
|
||||
post "/api/users" do
|
||||
content_type :json
|
||||
user = JSON.parse(request.body.read)
|
||||
{ created: user }.to_json
|
||||
end
|
||||
|
||||
get "/health" do
|
||||
"OK"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
require "rack"
|
||||
require_relative "app"
|
||||
|
||||
run SinatraApp
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,246 @@
|
||||
using System.Diagnostics;
|
||||
using FluentAssertions;
|
||||
using StellaOps.Scanner.Analyzers.Lang;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Ruby;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Ruby.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Performance benchmarks for Ruby analyzer components.
|
||||
/// Validates determinism requirements (<100 ms / workspace, <250 MB peak memory).
|
||||
/// </summary>
|
||||
public sealed class RubyBenchmarks
|
||||
{
|
||||
private const int WarmupIterations = 3;
|
||||
private const int BenchmarkIterations = 10;
|
||||
private const int MaxAnalysisTimeMs = 100;
|
||||
|
||||
[Fact]
|
||||
public async Task SimpleApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "simple-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"Simple app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ComplexApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "complex-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"Complex app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RailsApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "rails-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"Rails app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SinatraApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "sinatra-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"Sinatra app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainerApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "container-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"Container app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LegacyApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "legacy-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"Legacy app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CliApp_MeetsPerformanceTargetAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "cli-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
// Warmup
|
||||
for (var i = 0; i < WarmupIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
// Benchmark
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (var i = 0; i < BenchmarkIterations; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
||||
// Assert
|
||||
var avgMs = sw.ElapsedMilliseconds / (double)BenchmarkIterations;
|
||||
avgMs.Should().BeLessThan(MaxAnalysisTimeMs, $"CLI app analysis should complete in <{MaxAnalysisTimeMs}ms (actual: {avgMs:F2}ms)");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task MultipleRuns_ProduceDeterministicResultsAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "simple-app");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
|
||||
var results = new List<string>();
|
||||
|
||||
// Run multiple times to verify determinism
|
||||
for (var i = 0; i < 5; i++)
|
||||
{
|
||||
var context = new LanguageAnalyzerContext(fixturePath, TimeProvider.System);
|
||||
var result = await engine.AnalyzeAsync(context, CancellationToken.None);
|
||||
results.Add(result.ToJson(indent: false));
|
||||
}
|
||||
|
||||
// All results should be identical
|
||||
var firstResult = results[0];
|
||||
foreach (var result in results.Skip(1))
|
||||
{
|
||||
result.Should().Be(firstResult, "all runs should produce identical output for determinism");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,4 +100,134 @@ public sealed class RubyLanguageAnalyzerTests
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task RailsWorkspaceProducesDeterministicOutputAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "rails-app");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SinatraWorkspaceProducesDeterministicOutputAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "sinatra-app");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainerWorkspaceProducesDeterministicOutputAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "container-app");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainerWorkspaceDetectsRubyVersionAndNativeExtensionsAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "container-app");
|
||||
var store = new ScanAnalysisStore();
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
var context = new LanguageAnalyzerContext(
|
||||
fixturePath,
|
||||
TimeProvider.System,
|
||||
usageHints: null,
|
||||
services: null,
|
||||
analysisStore: store);
|
||||
|
||||
var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken);
|
||||
var snapshots = result.ToSnapshots();
|
||||
|
||||
var summary = Assert.Single(snapshots, snapshot => snapshot.Type == "ruby-observation");
|
||||
|
||||
// Verify Ruby version is detected
|
||||
Assert.True(summary.Metadata.TryGetValue("ruby.observation.ruby_version", out var rubyVersion));
|
||||
Assert.Equal("3.2.0", rubyVersion);
|
||||
|
||||
// Verify native extensions are detected
|
||||
Assert.True(summary.Metadata.TryGetValue("ruby.observation.native_extensions", out var nativeExtCount));
|
||||
Assert.NotNull(nativeExtCount);
|
||||
Assert.True(int.Parse(nativeExtCount!) >= 2); // nokogiri and pg
|
||||
|
||||
Assert.True(store.TryGet(ScanAnalysisKeys.RubyObservationPayload, out AnalyzerObservationPayload payload));
|
||||
using var document = JsonDocument.Parse(payload.Content.ToArray());
|
||||
var root = document.RootElement;
|
||||
var environment = root.GetProperty("environment");
|
||||
|
||||
// Check Ruby version sources
|
||||
Assert.True(environment.TryGetProperty("rubyVersionSources", out var versionSources));
|
||||
Assert.True(versionSources.GetArrayLength() >= 1);
|
||||
|
||||
// Check native extensions
|
||||
Assert.True(environment.TryGetProperty("nativeExtensions", out var nativeExtensions));
|
||||
Assert.True(nativeExtensions.GetArrayLength() >= 2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LegacyWorkspaceProducesDeterministicOutputAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "legacy-app");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
TestContext.Current.CancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LegacyWorkspaceDetectsCapabilitiesWithoutBundlerAsync()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "ruby", "legacy-app");
|
||||
var store = new ScanAnalysisStore();
|
||||
var analyzers = new ILanguageAnalyzer[] { new RubyLanguageAnalyzer() };
|
||||
var engine = new LanguageAnalyzerEngine(analyzers);
|
||||
var context = new LanguageAnalyzerContext(
|
||||
fixturePath,
|
||||
TimeProvider.System,
|
||||
usageHints: null,
|
||||
services: null,
|
||||
analysisStore: store);
|
||||
|
||||
var result = await engine.AnalyzeAsync(context, TestContext.Current.CancellationToken);
|
||||
var snapshots = result.ToSnapshots();
|
||||
|
||||
var summary = Assert.Single(snapshots, snapshot => snapshot.Type == "ruby-observation");
|
||||
|
||||
// Verify capabilities are still detected from source code analysis
|
||||
Assert.True(summary.Metadata.TryGetValue("ruby.observation.capability.exec", out var usesExec));
|
||||
Assert.Equal("true", usesExec);
|
||||
|
||||
Assert.True(summary.Metadata.TryGetValue("ruby.observation.capability.net", out var usesNet));
|
||||
Assert.Equal("true", usesNet);
|
||||
|
||||
// Verify entrypoints are detected
|
||||
Assert.True(summary.Metadata.TryGetValue("ruby.observation.entrypoints", out var entrypoints));
|
||||
Assert.NotNull(entrypoints);
|
||||
Assert.True(int.Parse(entrypoints!) >= 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentAssertions" Version="8.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit.v3" Version="3.0.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.3" />
|
||||
|
||||
Reference in New Issue
Block a user