diff --git a/app/controllers/api/v1/archives_controller.rb b/app/controllers/api/v1/archives_controller.rb index 40ee93a..f1cf79c 100644 --- a/app/controllers/api/v1/archives_controller.rb +++ b/app/controllers/api/v1/archives_controller.rb @@ -26,4 +26,15 @@ def readme render json: readme end end + + def changelog + expires_in(60.days, public: true, "s-maxage" => 60.days) # TODO this needs to be more dynamic to take into account headers from where the file was loaded + @archive = Archive.new(params[:url]) + changelog = @archive.changelog + if changelog.nil? + render json: {:error => "path not found"}, :status => 404 + else + render json: changelog + end + end end \ No newline at end of file diff --git a/app/models/archive.rb b/app/models/archive.rb index f9b066e..40bb03c 100644 --- a/app/models/archive.rb +++ b/app/models/archive.rb @@ -159,4 +159,33 @@ def readme } end end + + def changelog + Dir.mktmpdir do |dir| + download_file(dir) + base_path = extract(dir) + + return nil if base_path.nil? + all_files = Dir.glob("**/*", File::FNM_DOTMATCH, base: base_path).tap{|a| a.delete(".")} + + changelog_files = all_files.select{|path| path.match(/^changelog/i) } + + return nil if changelog_files.empty? + + changelog_file = changelog_files.first + + raw = File.read(File.join(base_path, changelog_file)) + html = GitHub::Markup.render(changelog_file, raw.force_encoding("UTF-8")) + language = GitHub::Markup.language(changelog_file, raw.force_encoding("UTF-8")).try(:name) + + return { + name: changelog_file, + raw: raw, + html: html, + plain: Nokogiri::HTML(html).try(:text), + extension: File.extname(changelog_file), + language: language + } + end + end end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index e777ec7..d5baf0a 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -9,6 +9,7 @@ get :list get :contents get :readme + get :changelog end end end diff --git a/openapi/api/v1/openapi.yaml b/openapi/api/v1/openapi.yaml index 9501efd..7ea7319 100644 --- a/openapi/api/v1/openapi.yaml +++ b/openapi/api/v1/openapi.yaml @@ -78,6 +78,24 @@ paths: application/json: schema: $ref: '#/components/schemas/Readme' + /archives/changelog: + get: + summary: get changelog from a package archive + operationId: changelog + parameters: + - name: url + in: query + description: url to package archive + required: true + schema: + type: string + responses: + 200: + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Changelog' components: schemas: Content: @@ -107,4 +125,19 @@ components: other_readme_files: type: array items: - type: string \ No newline at end of file + type: string + Changelog: + type: object + properties: + name: + type: string + raw: + type: string + html: + type: string + plain: + type: string + extension: + type: string + language: + type: string \ No newline at end of file diff --git a/test/controllers/api/v1/archives_controller_test.rb b/test/controllers/api/v1/archives_controller_test.rb index b4c8344..51db635 100644 --- a/test/controllers/api/v1/archives_controller_test.rb +++ b/test/controllers/api/v1/archives_controller_test.rb @@ -164,4 +164,21 @@ class ApiV1ArchivesControllerTest < ActionDispatch::IntegrationTest assert_equal actual_response['language'], "Markdown" assert_equal actual_response['other_readme_files'], [] end + + test 'changelog' do + stub_request(:get, "https://github.com/splitrb/split/archive/refs/heads/main.zip") + .to_return({ status: 200, body: File.open(File.join(Rails.root, 'test', 'fixtures', 'files','main.zip')).read }) + + get changelog_api_v1_archives_path(url: 'https://github.com/splitrb/split/archive/refs/heads/main.zip') + assert_response :success + actual_response = JSON.parse(@response.body) + + assert_equal actual_response['name'], 'CHANGELOG.md' + assert_equal actual_response['raw'][0..20], "# 4.0.2 (December 2nd" + assert_equal actual_response['html'][0..30], "