From e37202b296a9cfbb61fb3ff71fef14289f6df777 Mon Sep 17 00:00:00 2001 From: Alex Gusev Date: Fri, 5 Jun 2026 12:44:46 +0600 Subject: [PATCH 1/8] Fix Upload API sending Faraday's default User-Agent (cherry picked from commit 34554565db20b39faa39c67259765d3e203b034c) --- lib/uploadcare/api/upload.rb | 3 ++- spec/uploadcare/api/rest_spec.rb | 16 +++++++++++++++ spec/uploadcare/api/upload_spec.rb | 31 ++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/uploadcare/api/upload.rb b/lib/uploadcare/api/upload.rb index 3c36d563..11708b64 100644 --- a/lib/uploadcare/api/upload.rb +++ b/lib/uploadcare/api/upload.rb @@ -159,7 +159,7 @@ def build_request_uri(path, params, method) end def prepare_headers(req, _method, _uri, headers) - req.headers['User-Agent'] ||= Uploadcare::Internal::UserAgent.call(config: config) + req.headers['User-Agent'] = Uploadcare::Internal::UserAgent.call(config: config) req.headers.merge!(headers) end @@ -243,6 +243,7 @@ def private_ip?(address) def upload_part_request(conn:, request_uri:, data:, timeout:, open_timeout:) conn.put(request_uri) do |req| req.headers['Content-Type'] = 'application/octet-stream' + req.headers['User-Agent'] = Uploadcare::Internal::UserAgent.call(config: config) req.options.timeout = timeout if timeout req.options.open_timeout = open_timeout if open_timeout req.body = data diff --git a/spec/uploadcare/api/rest_spec.rb b/spec/uploadcare/api/rest_spec.rb index 3091748e..98bfb5e8 100644 --- a/spec/uploadcare/api/rest_spec.rb +++ b/spec/uploadcare/api/rest_spec.rb @@ -39,6 +39,22 @@ end end + describe 'User-Agent header' do + it 'sends the SDK User-Agent on REST API requests, not the Faraday default' do + expected_user_agent = Uploadcare::Internal::UserAgent.call(config: config) + stub_request(:get, 'https://api.uploadcare.com/files/') + .with(headers: { 'User-Agent' => expected_user_agent }) + .to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' }) + + rest.get(path: '/files/', params: {}, headers: {}, request_options: {}) + + expect( + a_request(:get, 'https://api.uploadcare.com/files/') + .with(headers: { 'User-Agent' => %r{\AUploadcareRuby/} }) + ).to have_been_made + end + end + describe '#get' do it 'returns a successful Result on 200' do stub_request(:get, 'https://api.uploadcare.com/files/') diff --git a/spec/uploadcare/api/upload_spec.rb b/spec/uploadcare/api/upload_spec.rb index 5982d4ff..b5f21a22 100644 --- a/spec/uploadcare/api/upload_spec.rb +++ b/spec/uploadcare/api/upload_spec.rb @@ -105,6 +105,37 @@ end end + describe 'User-Agent header' do + let(:expected_user_agent) { Uploadcare::Internal::UserAgent.call(config: config) } + + it 'sends the SDK User-Agent on Upload API requests, not the Faraday default' do + stub_request(:post, 'https://upload.uploadcare.com/base/') + .with(headers: { 'User-Agent' => expected_user_agent }) + .to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' }) + + upload.post(path: 'base/', params: { 'UPLOADCARE_PUB_KEY' => 'demopublickey' }) + + expect( + a_request(:post, 'https://upload.uploadcare.com/base/') + .with(headers: { 'User-Agent' => %r{\AUploadcareRuby/} }) + ).to have_been_made + end + + it 'sends the SDK User-Agent when uploading parts to a presigned URL' do + presigned_url = 'https://s3.amazonaws.com/bucket/part?signature=abc123' + stub_request(:put, presigned_url) + .with(headers: { 'User-Agent' => expected_user_agent }) + .to_return(status: 200, body: '', headers: {}) + + upload.upload_part_to_url(presigned_url, 'binary-data') + + expect( + a_request(:put, presigned_url) + .with(headers: { 'User-Agent' => %r{\AUploadcareRuby/} }) + ).to have_been_made + end + end + describe '#upload_part_to_url' do let(:presigned_url) { 'https://s3.amazonaws.com/bucket/part?signature=abc123' } From d8410d60568a53ac0dfa5f483b7aca38c824af91 Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Tue, 9 Jun 2026 15:34:46 +0530 Subject: [PATCH 2/8] Prepare 5.0.1 release --- CHANGELOG.md | 7 +++++++ lib/uploadcare/internal/user_agent.rb | 2 +- lib/uploadcare/version.rb | 2 +- spec/uploadcare/version_spec.rb | 2 +- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f340b393..d45a6d21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 5.0.1 — 2026-06-09 + +### Fixed + +* Upload API requests now send the SDK-generated `User-Agent` instead of Faraday's default header. +* Multipart upload part requests to presigned URLs now include the same SDK-generated `User-Agent`. + ## 5.0.0 — 2026-05-17 v5 is stable. diff --git a/lib/uploadcare/internal/user_agent.rb b/lib/uploadcare/internal/user_agent.rb index cb9b1014..0d3cef88 100644 --- a/lib/uploadcare/internal/user_agent.rb +++ b/lib/uploadcare/internal/user_agent.rb @@ -7,7 +7,7 @@ # # @example # Uploadcare::Internal::UserAgent.call(config: config) -# # => "UploadcareRuby/5.0.0/demopublickey (Ruby/3.3.0)" +# # => "UploadcareRuby/5.0.1/demopublickey (Ruby/3.3.0)" class Uploadcare::Internal::UserAgent # Build a User-Agent string. # diff --git a/lib/uploadcare/version.rb b/lib/uploadcare/version.rb index 058834c4..aff7aa75 100644 --- a/lib/uploadcare/version.rb +++ b/lib/uploadcare/version.rb @@ -3,5 +3,5 @@ # Root namespace for the Uploadcare Ruby SDK. module Uploadcare # Gem version. - VERSION = '5.0.0' + VERSION = '5.0.1' end diff --git a/spec/uploadcare/version_spec.rb b/spec/uploadcare/version_spec.rb index f0518adb..41e1ed04 100644 --- a/spec/uploadcare/version_spec.rb +++ b/spec/uploadcare/version_spec.rb @@ -2,6 +2,6 @@ RSpec.describe Uploadcare::VERSION do it 'has a version number' do - expect(Uploadcare::VERSION).to eq('5.0.0') + expect(Uploadcare::VERSION).to eq('5.0.1') end end From 8d90026510d70ba428065ba03701718092f66c4e Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Wed, 26 Aug 2026 13:45:00 +0530 Subject: [PATCH 3/8] Prepare 5.1.0 release --- CHANGELOG.md | 13 ++++++----- docs/release-notes-5.1.0.md | 33 +++++++++++++++++++++++++++ lib/uploadcare/internal/user_agent.rb | 2 +- lib/uploadcare/version.rb | 2 +- spec/uploadcare/version_spec.rb | 2 +- 5 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 docs/release-notes-5.1.0.md diff --git a/CHANGELOG.md b/CHANGELOG.md index e1814bc3..3e6ddd73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,15 @@ # Changelog -## Unreleased +## 5.1.0 — 2026-08-26 ### Added -* File search through `client.files.search`, including full-text, exact, metadata, tag, range, and image filters, - sorting, highlights, `include=appdata`, and POST-aware pagination -* Per-file tags through `client.file_tags` with list, replace, and atomic add/delete operations -* Upload-time `tags:` support for direct, batch, URL, and multipart uploads -* The `tags` attribute on file resources returned by the REST API +* Search files through `client.files.search` with full-text, UUID, exact, metadata, tag, range, and image filters, + sorting, highlights, `include=appdata`, and POST-aware pagination that preserves the original search options. +* Manage per-file tags through `client.file_tags` with list, replace, and atomic add/delete operations. +* Apply tags while uploading files directly, in batches, from URLs, or through multipart uploads. +* Read tags from file resources returned by the REST API. +* Call the raw REST file-search and file-tag endpoints through `client.api.rest` when exact endpoint parity is needed. ## 5.0.1 — 2026-06-09 diff --git a/docs/release-notes-5.1.0.md b/docs/release-notes-5.1.0.md new file mode 100644 index 00000000..4b34a8fa --- /dev/null +++ b/docs/release-notes-5.1.0.md @@ -0,0 +1,33 @@ +# uploadcare-ruby 5.1.0 + +This release adds file search and file-tag support to the v5 client API. It is backward compatible with 5.0.x and +does not require an application migration. + +## Highlights + +- Search files through `client.files.search` using text, UUID, metadata, tag, range, and image filters. +- Sort search results, inspect match highlights, request `appdata`, and paginate without rebuilding POST criteria. +- List, replace, add, and delete per-file tags through `client.file_tags`. +- Assign tags during direct, batch, URL, and multipart uploads. +- Read tags directly from returned file resources. +- Use `client.api.rest.files.search` and `client.api.rest.file_tags` for exact REST endpoint access. + +## Upgrade Notes + +- Requirement: Ruby `>= 3.3`. +- Update with `bundle update uploadcare-ruby` and run the application's test suite. +- No configuration or data migration is required from 5.0.x. +- File search results may be eventually consistent immediately after an upload; retry when a workflow searches for a + file it just created. +- Existing upload calls remain valid. Pass `tags: [...]` only where upload-time tagging is needed. +- Rollback: pin `uploadcare-ruby` to `5.0.1`. + +## Examples + +- File search: [`examples/file_search.rb`](../examples/file_search.rb) +- File tags: [`examples/file_tags.rb`](../examples/file_tags.rb) +- Raw REST examples: [`api_examples/README.md`](../api_examples/README.md) + +## Full Changelog + +See [CHANGELOG.md](../CHANGELOG.md). diff --git a/lib/uploadcare/internal/user_agent.rb b/lib/uploadcare/internal/user_agent.rb index 0d3cef88..c1326d94 100644 --- a/lib/uploadcare/internal/user_agent.rb +++ b/lib/uploadcare/internal/user_agent.rb @@ -7,7 +7,7 @@ # # @example # Uploadcare::Internal::UserAgent.call(config: config) -# # => "UploadcareRuby/5.0.1/demopublickey (Ruby/3.3.0)" +# # => "UploadcareRuby/5.1.0/demopublickey (Ruby/3.3.0)" class Uploadcare::Internal::UserAgent # Build a User-Agent string. # diff --git a/lib/uploadcare/version.rb b/lib/uploadcare/version.rb index aff7aa75..0d1a9295 100644 --- a/lib/uploadcare/version.rb +++ b/lib/uploadcare/version.rb @@ -3,5 +3,5 @@ # Root namespace for the Uploadcare Ruby SDK. module Uploadcare # Gem version. - VERSION = '5.0.1' + VERSION = '5.1.0' end diff --git a/spec/uploadcare/version_spec.rb b/spec/uploadcare/version_spec.rb index 41e1ed04..4c0457b2 100644 --- a/spec/uploadcare/version_spec.rb +++ b/spec/uploadcare/version_spec.rb @@ -2,6 +2,6 @@ RSpec.describe Uploadcare::VERSION do it 'has a version number' do - expect(Uploadcare::VERSION).to eq('5.0.1') + expect(Uploadcare::VERSION).to eq('5.1.0') end end From d12a554a6e6244afc47fd07302d98913e0e6c5a4 Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Wed, 26 Aug 2026 13:45:00 +0530 Subject: [PATCH 4/8] Pin RubyGems publishing action --- .github/workflows/gem-push.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 366d42d4..018ce08f 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -13,7 +13,7 @@ jobs: - name: Release Gem if: contains(github.ref, 'refs/tags/v') - uses: cadwallion/publish-rubygems-action@master + uses: cadwallion/publish-rubygems-action@94a6f4cd5350581749c569b5001eecc864e3ad0b # v1.1.0 env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}} From 79c918077f4309fcc15445129d6021cddce1b36c Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Wed, 26 Aug 2026 13:51:13 +0530 Subject: [PATCH 5/8] Declare release workflow permissions --- .github/workflows/gem-push.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/gem-push.yml b/.github/workflows/gem-push.yml index 018ce08f..d22f2c9f 100644 --- a/.github/workflows/gem-push.yml +++ b/.github/workflows/gem-push.yml @@ -7,6 +7,8 @@ on: jobs: build: runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v5 From a7f790e4cf3d43904ee66c612f1896e1f4b4768c Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Sat, 5 Sep 2026 23:39:59 +0530 Subject: [PATCH 6/8] Update 5.1.0 release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e6ddd73..1ff3150a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 5.1.0 — 2026-08-26 +## 5.1.0 — 2026-09-05 ### Added From 50f499e5a262f5ec2e460aa31639f9deb28e625f Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Mon, 7 Sep 2026 02:01:34 +0530 Subject: [PATCH 7/8] Correct 5.1.0 release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ff3150a..1c30e519 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## 5.1.0 — 2026-09-05 +## 5.1.0 — 2026-09-06 ### Added From 93bb2319a2c308ff9f9c2eaf7e0d8e38e0fc47f4 Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Mon, 7 Sep 2026 02:10:39 +0530 Subject: [PATCH 8/8] Document FileTags in v5 migration guide --- MIGRATING_V5.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MIGRATING_V5.md b/MIGRATING_V5.md index 8cf594d6..6a7fea2d 100644 --- a/MIGRATING_V5.md +++ b/MIGRATING_V5.md @@ -27,7 +27,7 @@ The examples expect `UPLOADCARE_PUBLIC_KEY` and `UPLOADCARE_SECRET_KEY` to come ## Recommended Migration Order 1. Introduce explicit `Uploadcare::Client` instances in your application. -2. Move app-facing code to `client.files`, `client.groups`, `client.uploads`, `client.project`, `client.webhooks`, `client.file_metadata`, `client.addons`, and `client.conversions`. +2. Move app-facing code to `client.files`, `client.groups`, `client.uploads`, `client.project`, `client.webhooks`, `client.file_metadata`, `client.file_tags`, `client.addons`, and `client.conversions`. 3. Keep `client.api.rest` and `client.api.upload` only where you need raw endpoint parity. 4. Audit return-type and error-handling assumptions. 5. Remove any app code that depends on internal transport classes. @@ -201,6 +201,7 @@ These top-level resource constants still exist: - `Uploadcare::Project` - `Uploadcare::Webhook` - `Uploadcare::FileMetadata` +- `Uploadcare::FileTags` - `Uploadcare::DocumentConversion` - `Uploadcare::VideoConversion`