Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
6b7f9ed
Finalize v5 rewrite API and tests
vipulnsward Feb 8, 2026
9821a80
Fix cname cache scoping and tighten error handling
vipulnsward Feb 8, 2026
f22d44b
Address code review feedback on examples and resources
vipulnsward Feb 9, 2026
d496ae8
Adopt compact class syntax and qualify constants
vipulnsward Feb 9, 2026
6d51789
Update README title and remove outdated compatibility note
vipulnsward Feb 9, 2026
b36e40a
Trim README API reference section
vipulnsward Feb 9, 2026
ecbba8c
Address CodeRabbit review findings
vipulnsward Feb 9, 2026
376ad59
Harden file metadata paths and add coverage
vipulnsward Feb 9, 2026
8ff7ce6
Replace pending integration specs and satisfy rubocop
vipulnsward Feb 9, 2026
7dacd6b
Speed up multipart retry specs
vipulnsward Feb 9, 2026
3492470
Avoid regex stripping in Akamai HMAC key
vipulnsward Feb 9, 2026
1d9b3ea
Fix README API examples and headings
vipulnsward Feb 9, 2026
8194f31
Address review feedback on auth, conversion, and UUID handling
vipulnsward Feb 9, 2026
0d9dd47
Add specs for result and webhook behaviors
vipulnsward Feb 9, 2026
911aca0
Cover upload file info and conversion result handling
vipulnsward Feb 9, 2026
0ece524
Make result error message expectation Ruby-version agnostic
vipulnsward Feb 9, 2026
102144c
Redact uploadcare keys in VCR fixtures
vipulnsward Feb 9, 2026
c4da96e
Use HMAC-SHA256 for upload signature generation
vipulnsward Feb 9, 2026
34f014e
Exclude authenticator from Snyk code scan
vipulnsward Feb 9, 2026
576bafc
Adjust Snyk policy exclusions
vipulnsward Feb 9, 2026
3abc2e9
Fix review feedback, improve multi-account config, and harden VCR scr…
vipulnsward Feb 10, 2026
cd3ea32
Fix RuboCop offenses in VCR scrubber and parallel upload
vipulnsward Feb 10, 2026
ab77d89
Avoid hardcoded secrets in multi-account spec
vipulnsward Feb 10, 2026
5d9b19e
Scrub Authorization values in VCR fixtures
vipulnsward Feb 10, 2026
eb4538b
Fix verified README/examples flows and group/file metadata issues
vipulnsward Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Uploadcare API credentials
# Copy this file to .env and fill in your actual keys
# Get your keys from: https://app.uploadcare.com/projects/-/api-keys/

UPLOADCARE_PUBLIC_KEY=your_public_key_here
UPLOADCARE_SECRET_KEY=your_secret_key_here
10 changes: 3 additions & 7 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ jobs:
strategy:
matrix:
ruby-version:
- 3.0
- 3.1
- 3.2
- 3.3
- 3.4
- 4.0

steps:
- uses: actions/checkout@v3
Expand All @@ -42,15 +40,13 @@ jobs:
strategy:
matrix:
ruby-version:
- 3.4
- 4.0
steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true
- name: Install Rubocop
run: gem install rubocop
- name: Check codestyle
run: rubocop
run: bundle exec rubocop
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,12 @@ Gemfile.lock
.ruby-version
project_files
*.gem
.vscode/
.DS_Store
.claude/
.kiro/
.agents/

# Environment variables (API keys)
.env
.env.local
139 changes: 132 additions & 7 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
plugins:
- rubocop-rspec

AllCops:
NewCops: enable
TargetRubyVersion: 3.0
TargetRubyVersion: 3.3
SuggestExtensions: false

Layout/LineLength:
Max: 120
Expand All @@ -10,31 +14,152 @@ Layout/LineLength:
Lint/IneffectiveAccessModifier:
Enabled: false

Style/HashTransformKeys:
Exclude:
- 'lib/uploadcare/entity/decorator/paginator.rb'
- 'lib/uploadcare/client/conversion/video_conversion_client.rb'
- 'lib/uploadcare/entity/file.rb'

Metrics/BlockLength:
Exclude:
- 'bin/'
- 'spec/**/*'
- 'uploadcare-ruby.gemspec'

Metrics/ClassLength:
Max: 100
Exclude:
- 'lib/uploadcare/clients/upload_client.rb' # Complex upload logic with 9 endpoints
- 'lib/uploadcare/clients/multipart_uploader_client.rb'
- 'lib/uploadcare/resources/file.rb' # Pre-existing file resource with many methods
- 'lib/uploadcare/uploader.rb' # Uploader module with multiple upload strategies

Metrics/ModuleLength:
Max: 100
Exclude:
- 'spec/**/*'
- 'lib/uploadcare/uploader.rb' # Uploader module with multiple upload strategies

Metrics/MethodLength:
Max: 20
Exclude:
- 'lib/uploadcare/clients/upload_client.rb' # Parallel upload requires coordination logic
- 'lib/uploadcare/clients/multipart_uploader_client.rb'
- 'lib/uploadcare/clients/uploader_client.rb'
- 'lib/uploadcare/uploader.rb' # Parallel upload coordination

Metrics/AbcSize:
Max: 17
Exclude:
- 'lib/uploadcare/clients/upload_client.rb' # Upload methods have multiple parameters and validations
- 'lib/uploadcare/clients/multipart_uploader_client.rb'
- 'lib/uploadcare/clients/uploader_client.rb'
- 'lib/uploadcare/uploader.rb' # Parallel upload coordination

Metrics/CyclomaticComplexity:
Max: 7
Exclude:
- 'lib/uploadcare/clients/upload_client.rb' # Upload logic has multiple conditional paths
- 'lib/uploadcare/clients/multipart_uploader_client.rb'
- 'lib/uploadcare/clients/uploader_client.rb'
- 'lib/uploadcare/uploader.rb' # Parallel upload coordination

Metrics/PerceivedComplexity:
Max: 8
Exclude:
- 'lib/uploadcare/clients/upload_client.rb' # Parallel upload coordination is inherently complex
- 'lib/uploadcare/clients/multipart_uploader_client.rb'
- 'lib/uploadcare/clients/uploader_client.rb'

Metrics/ParameterLists:
Exclude:
- 'lib/uploadcare/clients/rest_client.rb'
- 'lib/uploadcare/clients/upload_client.rb'

Style/Documentation:
Enabled: false

Style/ClassAndModuleChildren:
EnforcedStyle: compact

Style/OptionalBooleanParameter:
AllowedMethods: ['create']

Style/FrozenStringLiteralComment:
Exclude:
- 'api_examples/**/*'

Style/ArgumentsForwarding:
Enabled: false

RSpec/ContextWording:
Prefixes:
- when
- with
- without
- if
- unless
- for

RSpec/MultipleExpectations:
Enabled: false

RSpec/ExampleLength:
Enabled: false

RSpec/DescribedClass:
Enabled: false

RSpec/DescribeClass:
Enabled: false

RSpec/ExpectActual:
Enabled: false

RSpec/AnyInstance:
Enabled: false

RSpec/SpecFilePathFormat:
Enabled: false

RSpec/LeadingSubject:
Enabled: false

RSpec/EmptyLineAfterExample:
Enabled: false

RSpec/EmptyLineAfterFinalLet:
Enabled: false

RSpec/EmptyLineAfterExampleGroup:
Enabled: false

RSpec/MultipleMemoizedHelpers:
Enabled: false

RSpec/NestedGroups:
Enabled: false

RSpec/NamedSubject:
Enabled: false

RSpec/IteratedExpectation:
Enabled: false

RSpec/BeEq:
Enabled: false

RSpec/StubbedMock:
Enabled: false

RSpec/EmptyLineAfterHook:
Enabled: false

RSpec/MessageSpies:
Enabled: false

RSpec/VerifiedDoubles:
Enabled: false

RSpec/ReceiveMessages:
Enabled: false

RSpec/HookArgument:
Enabled: false

RSpec/ClassCheck:
Enabled: false
4 changes: 4 additions & 0 deletions .snyk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
exclude:
code:
- lib/uploadcare/authenticator.rb
164 changes: 164 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,169 @@
# Changelog

## 5.0.0 — 2026-01-06

### ⚠️ BREAKING CHANGES
This is a major rewrite with significant architectural changes. Please review the migration guide below.

### Changed - Architecture Overhaul

#### Dependency Modernization
* **Removed dependencies**:
* `dry-configurable` — replaced with plain Ruby `Configuration` class
* `uploadcare-api_struct` — no longer needed with new resource pattern
* `mimemagic` — replaced with `mime-types`
* `parallel` — multipart uploads now use native threading
* `retries` — retry logic now built into clients
* **Added dependencies**:
* `zeitwerk` (~> 2.6.18) — modern Ruby autoloading
* `faraday` (~> 2.12) — HTTP client with middleware support
* `faraday-multipart` (~> 1.0) — multipart upload support
* `addressable` (~> 2.8) — URI handling and encoding
* `mime-types` (~> 3.1) — MIME type detection

#### Code Structure
* **Complete rewrite from entity-based to resource-based architecture**
* Replaced `entity/` classes with simpler `resources/` pattern
* Restructured client layer from `client/` to `clients/` directory
* Removed param builders in favor of integrated client logic
* Changed module structure and namespacing
* **New layered architecture**:
* `Resources` — public API layer (`Uploadcare::File`, `Uploadcare::Uploader`, etc.)
* `Clients` — HTTP layer (`FileClient`, `UploaderClient`, `RestClient`, etc.)
* `Concerns` — shared modules (`ErrorHandler`, `ThrottleHandler`)
* **Simplified require paths**: gemspec now uses single `lib` require path instead of multiple paths
* **Zeitwerk autoloading**: replaces manual `require` statements with automatic module loading

#### Configuration System
* Replaced `Dry::Configurable` with plain Ruby `Configuration` class
* Configuration is now a proper class with documented attributes and YARD annotations
* New configuration options:
* `multipart_chunk_size` — chunk size for multipart uploads (default: 5MB)
* `upload_timeout` — upload request timeout in seconds (default: 60)
* `max_upload_retries` — maximum upload retry attempts (default: 3)

#### HTTP Client
* New `RestClient` class using Faraday with middleware:
* JSON request/response encoding
* Automatic error raising on 4xx/5xx responses
* Built-in throttle handling with exponential backoff
* New `UploadClient` class for Upload API with multipart support
* New `Authenticator` class for HMAC-SHA1 signature generation

### Added - New Features
* **Zeitwerk autoloading** for modern Ruby module management
* **Smart upload detection** with automatic method selection based on file size/type
* **Enhanced multipart upload** with parallel processing support
* **Progress tracking** for all upload operations with real-time callbacks
* **Batch upload capabilities** with error handling per file
* **Thread-safe upload operations** with configurable concurrency
* **New exception classes** for better error handling:
* `InvalidRequestError` — for 400 Bad Request responses
* `NotFoundError` — for 404 Not Found responses
* `UploadError` — for upload-specific failures
* `RetryError` — for polling/retry scenarios
* **New resource classes**:
* `BatchFileResult` — for batch store/delete operations
* `PaginatedCollection` — for paginated API responses
* `BaseResource` — base class for all resources
* **Comprehensive examples** in `/examples` directory:
* `simple_upload.rb` — basic file upload
* `batch_upload.rb` — multiple file uploads
* `large_file_upload.rb` — multipart upload for large files
* `upload_with_progress.rb` — progress tracking
* `url_upload.rb` — upload from URL
* `group_creation.rb` — file grouping
* **Integration tests** with full end-to-end workflow coverage
* **API examples** in `/api_examples` directory for REST and Upload APIs

### Added - Ruby 4.0 Support
* **Ruby 4.0 Official Support**: Explicitly documented and tested Ruby 4.0.1 compatibility

### Changed - Ruby Version Support
* **Minimum Ruby version**: Now requires Ruby 3.3+ (compatible with Rails main)
* **Supported versions**: Ruby 3.3, 3.4, 4.0
* **Removed support**: Ruby 3.0, 3.1, 3.2 (EOL or nearing EOL)

### Fixed
* JSON response parsing in UploadClient
* Thread safety in parallel uploads with proper error aggregation
* Rubocop configuration to match gemspec Ruby version requirement
* Constant name collision between module and class Uploader
* Proper exponential backoff with jitter in polling logic

### Removed
* Old entity system (`entity/` directory)
* Param builders (`param/` directory) — logic moved into clients
* Legacy concern system (`concern/` directory)
* `Dry::Configurable` dependency and DSL
* `uploadcare-api_struct` dependency
* Support for Ruby < 3.3

### Migration Guide from v4.x to v5.0

#### Module Changes
```ruby
# Old (v4.x)
Uploadcare::Entity::File
Uploadcare::Client::FileClient

# New (v5.0)
Uploadcare::File
Uploadcare::FileClient
```

#### Upload API Changes
```ruby
# Old (v4.x)
Uploadcare::Uploader.upload_from_url(url)

# New (v5.0) - Smart detection
Uploadcare::Uploader.upload(url) # Automatically detects URL
Uploadcare::Uploader.upload(file) # Automatically uses multipart for large files
```

#### Configuration Changes
```ruby
# Old (v4.x) - Dry::Configurable DSL
Uploadcare.configure do |config|
config.public_key = 'your_public_key'
config.secret_key = 'your_secret_key'
end

# New (v5.0) - Plain Ruby Configuration class (same syntax, different implementation)
Uploadcare.configure do |config|
config.public_key = 'your_public_key'
config.secret_key = 'your_secret_key'
# New options available:
config.upload_timeout = 120
config.max_upload_retries = 5
config.multipart_chunk_size = 10 * 1024 * 1024 # 10MB chunks
end
```

#### Error Handling Changes
```ruby
# Old (v4.x)
rescue Uploadcare::Exception::RequestError => e

# New (v5.0) - More specific exceptions available
rescue Uploadcare::Exception::NotFoundError => e
# Handle 404 specifically
rescue Uploadcare::Exception::InvalidRequestError => e
# Handle 400 specifically
rescue Uploadcare::Exception::RequestError => e
# Handle other errors
```

#### Batch Operations
```ruby
# New in v5.0 - BatchFileResult for batch operations
result = Uploadcare::File.batch_store(uuids)
result.status # => 200
result.result # => Array of File objects
result.problems # => Hash of UUIDs that failed with reasons
```

## 4.5.0 — 2025-07-25
### Added
* **CDN Subdomain Support**: Added support for automatic subdomain generation to improve CDN performance and caching.
Expand Down
Loading