Created
May 5, 2026 18:54
-
-
Save mokolabs/b0baf9aa4d908b0100baa778337c3027 to your computer and use it in GitHub Desktop.
Reporting tool for SERVICES.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| require "io/console" | |
| require "set" | |
| require "terminal-table" | |
| require "yaml" | |
| # SERVICES REPORTER | |
| # This script generates a report about all third-party services used by Ruby | |
| # apps in the ~/Sites directory. The report includes the app name and all | |
| # third-party services used by the app. | |
| # Apps must have a SERVICES.yml file to be included. | |
| # Install the `terminal-table` gem if you don't have it: | |
| # gem install terminal-table | |
| # Usage: | |
| # ruby services.rb # Generate report on all services used by all apps | |
| # ruby services.rb app # Generate report on all services used by single app | |
| # ruby services.rb all # Generate report on all unique service providers | |
| # ruby services.rb help # Show this help message | |
| # METHODS | |
| # Set terminal width | |
| $terminal_width = IO.console ? IO.console.winsize[1] : 103 | |
| # Format report header | |
| def header(text) | |
| puts "\n..#{text}".ljust($terminal_width, ".") | |
| end | |
| # Output text and replace any `+` with newlines | |
| # (but ignore terminal tables) | |
| def output(text) | |
| # Replace `+` at the start or end of the string, ignoring `+` near `-` | |
| formatted_text = text.gsub(/\A\++(?!-)|(?<!-)\++\z/) { |match| "\n" * match.length } | |
| puts formatted_text | |
| end | |
| # Load services from all apps | |
| def load_services | |
| data = [] | |
| Dir.glob("#{File.expand_path("~/Sites")}/*").select do |app| | |
| File.directory?(app) && File.exist?(File.join(app, "SERVICES.yml")) | |
| end.each do |app| | |
| name = File.basename(app) | |
| services = YAML.load_file(File.join(app, "SERVICES.yml")) | |
| services.each do |category, value| | |
| if value.is_a?(Hash) | |
| value.each do |subcategory, provider| | |
| Array(provider).each { |p| data << [name, "#{category} (#{subcategory})", p] } | |
| end | |
| else | |
| Array(value).each { |v| data << [name, category, v] } | |
| end | |
| end | |
| end | |
| data | |
| end | |
| # Generate report on single app | |
| if app_name = ARGV[0] and !app_name.match?(/help|all|-h|--help/) | |
| app_path = File.expand_path("~/Sites/#{app_name}") | |
| services_file = File.join(app_path, "SERVICES.yml") | |
| if File.directory?(app_path) && File.exist?(services_file) | |
| header "#{app_name.upcase} SERVICES" | |
| services = YAML.load_file(services_file) | |
| output "+#{YAML.dump(services).gsub("---\n", "")}+" | |
| else | |
| output "There was a problem! No services found in ~/Sites/#{app_name}" | |
| end | |
| exit | |
| end | |
| # Generate report on all apps | |
| if ARGV[0].nil? | |
| rows = [] | |
| categories = Set.new | |
| data = load_services | |
| grouped = data.group_by { |_, category, _| category } | |
| grouped.sort.each do |category, entries| | |
| entries.group_by { |_, _, provider| provider }.each do |provider, group| | |
| group.each_with_index do |(app, _, _), index| | |
| # Show category and provider only once | |
| rows << [ | |
| categories.include?(category) ? "" : category, | |
| index.zero? ? provider : "", | |
| app | |
| ] | |
| categories.add(category) | |
| end | |
| end | |
| rows << :separator | |
| end | |
| rows.pop if rows.last == :separator | |
| report = Terminal::Table.new do |table| | |
| table.headings = %w[Category Provider App] | |
| rows.each { |row| row == :separator ? table.add_separator : table.add_row(row) } | |
| end | |
| header "SERVICES" | |
| output "+#{report}++" | |
| exit | |
| end | |
| # Generate report on all providers (with counts) | |
| if ARGV[0] == "all" | |
| services = load_services | |
| providers = services.each_with_object(Hash.new(0)) do |(_, _, provider), counts| | |
| counts[provider] += 1 | |
| end | |
| header "SERVICES" | |
| output "+#{providers.sort.map { |provider, count| "#{provider} (#{count})" }.join("\n")}++" | |
| exit | |
| end | |
| # Show help message | |
| if ARGV[0] == "help" || ARGV[0] == "--help" || ARGV[0] == "-h" | |
| puts "Usage: services [options]" | |
| puts | |
| puts "Description:" | |
| puts " Generates reports about third-party services used by local Ruby apps" | |
| puts | |
| puts "Options:" | |
| puts " (none) Generate report on all services used by all apps" | |
| puts " app Generate report on all services used by single app" | |
| puts " all Generate report on all unique service providers" | |
| puts " ..." | |
| puts " help Show this help message" | |
| exit | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment