require 'yaml' namespace :api_docs do desc 'Generate OpenAPI schema' task generate: :environment do Rails.application.eager_load! # Ensure all controllers and API definitions are loaded ApiRegulator::OpenApiGenerator.generate(ApiRegulator.api_definitions) end desc "Upload OpenAPI schema to ReadMe" task :upload => :environment do # ReadMe API key and version readme_api_key = ENV['RDME_API_KEY'] || raise("RDME_API_KEY is not set") # ReadMe API endpoint readme_api_endpoint = "https://dash.readme.com/api/v1/api-specification" # Read the OpenAPI schema file schema_path = "#{ApiRegulator.configuration.docs_path}/openapi.json" unless File.exist?(schema_path) raise "OpenAPI schema file not found at #{schema_path}" end openapi_content = File.read(schema_path) # Upload to ReadMe require 'net/http' require 'uri' require 'json' if ApiRegulator.configuration.rdme_api_id uri = URI.parse("#{readme_api_endpoint}/#{ApiRegulator.configuration.rdme_api_id}") request = Net::HTTP::Put.new(uri) else uri = URI.parse(readme_api_endpoint) request = Net::HTTP::Post.new(uri) end request["Authorization"] = "Basic #{Base64.strict_encode64(readme_api_key)}" request["Content-Type"] = "application/json" request.body = { spec: JSON.parse(openapi_content) }.to_json response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http| http.request(request) end if response.code.to_i == 200 puts "OpenAPI schema successfully updated!" elsif response.code.to_i == 201 puts "OpenAPI schema successfully created!" puts "To use this for future publishing, add this to your ApiRegulator configs:" puts "" puts " config.rdme_api_id = \"#{JSON.parse(response.body)["_id"]}\"" puts "" else puts "Failed to upload OpenAPI schema to ReadMe!" puts "Response Code: #{response.code}" puts "Response Body:" pp JSON.parse(response.body) end end desc 'Generate and upload OpenAPI schema' task publish: :environment do Rake::Task["api_docs:generate"].invoke Rake::Task["api_docs:upload"].invoke Rake::Task["api_docs:upload_pages"].invoke end desc "Upload custom pages to ReadMe" task :upload_pages => :environment do # Configuration readme_api_key = ENV['RDME_API_KEY'] || raise("RDME_API_KEY is not set") base_readme_api_endpoint = "https://dash.readme.com/api/v1/docs" # Discover all documentation files pages_directory = "#{ApiRegulator.configuration.docs_path}/**/*.md" page_files = Dir.glob(pages_directory) # Iterate through each file page_files.each do |file_path| # Extract metadata and body metadata, body = parse_markdown_file(file_path) raise "No metadata found in #{file_path}" unless metadata # Use metadata to build the API request slug = metadata["slug"] || File.basename(file_path, ".md").gsub("_", "-") request_body = { type: "basic", categorySlug: "documentation", hidden: false, body: body }.merge(metadata) request_body["slug"] ||= slug raise("Title missing in #{file_path}") unless request_body["title"].present? # Build the API request if check_if_page_exists(slug) uri = URI.parse("#{base_readme_api_endpoint}/#{slug}") request = Net::HTTP::Put.new(uri) else uri = URI.parse("#{base_readme_api_endpoint}") request = Net::HTTP::Post.new(uri) end request["Authorization"] = "Basic #{Base64.strict_encode64(readme_api_key)}" request["Content-Type"] = "application/json" request.body = request_body.compact.to_json # Send the request response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http| http.request(request) end # Handle the response case response.code.to_i when 200 puts "Page '#{request_body["title"]}' successfully updated!" when 201 puts "Page '#{request_body["title"]}' successfully created!" else puts "Failed to upload page '#{request_body["title"]}'!" puts "Response Code: #{response.code}" puts "Response Body: #{response.body}" end end end desc "View all categories on Readme.com" task :fetch_categories => :environment do # Configuration readme_api_key = ENV['RDME_API_KEY'] || raise("RDME_API_KEY is not set") readme_categories_api_endpoint = "https://dash.readme.com/api/v1/categories" # Build the API request uri = URI.parse(readme_categories_api_endpoint) request = Net::HTTP::Get.new(uri) request["Authorization"] = "Basic #{Base64.strict_encode64(readme_api_key)}" request["Content-Type"] = "application/json" # Send the request response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http| http.request(request) end # Handle the response case response.code.to_i when 200 puts "Categories" pp JSON.parse(response.body) else puts "Failed to fetch categories" puts "Response Code: #{response.code}" puts "Response Body: #{response.body}" end end def parse_markdown_file(file_path) content = File.read(file_path) metadata = nil body = "" # Split metadata and body if content =~ /\A---\s*\n(.*?)\n---\s*\n(.*)/m metadata = YAML.safe_load($1) body = $2 else raise "YAML front matter missing in #{file_path}" end [metadata, body] end def check_if_page_exists(slug) readme_api_key = ENV['RDME_API_KEY'] || raise("RDME_API_KEY is not set") uri = URI.parse("https://dash.readme.com/api/v1/docs/#{slug}") request = Net::HTTP::Get.new(uri) request["Authorization"] = "Basic #{Base64.strict_encode64(readme_api_key)}" request["Content-Type"] = "application/json" # Send the request response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http| http.request(request) end # Handle the response case response.code.to_i when 200 true when 404 false else puts "Failed to serach for page" puts "Response Code: #{response.code}" puts "Response Body: #{response.body}" end end end