Thanks for helping improve the Transloadit Ruby SDK! This guide covers local development, testing, and publishing new releases.
After cloning the repository, install dependencies and run the test suite:
bundle install
bundle exec rake testTo exercise the signature parity suite against the Node.js CLI, make sure npx transloadit is available and run:
TEST_NODE_PARITY=1 bundle exec rake testYou can warm the CLI cache ahead of time:
TRANSLOADIT_KEY=... TRANSLOADIT_SECRET=... \
npx --yes transloadit smart_sig --help
TRANSLOADIT_KEY=... TRANSLOADIT_SECRET=... \
npx --yes transloadit sig --algorithm sha384 --helpSet COVERAGE=0 to skip coverage instrumentation if desired:
COVERAGE=0 bundle exec rake testThe repository ships with a helper that runs tests inside a reproducible Docker image:
./scripts/test-in-docker.shPass a custom command to run alternatives (Bundler still installs first):
./scripts/test-in-docker.sh bundle exec ruby -Itest test/unit/transloadit/test_request.rbThe script forwards environment variables such as TEST_NODE_PARITY and credentials from .env, so you can combine parity checks and integration tests. End-to-end uploads are enabled by default; unset them by running:
RUBY_SDK_E2E=0 ./scripts/test-in-docker.shTo exercise the optional live upload:
RUBY_SDK_E2E=1 TRANSLOADIT_KEY=... TRANSLOADIT_SECRET=... \
./scripts/test-in-docker.sh bundle exec ruby -Itest test/integration/test_e2e_upload.rbThe test uploads chameleon.jpg, resizes it, and asserts on a real assembly response.
Publishing is manual: scripts/notify-registry.sh builds and pushes the gem through Docker. Pushing a tag or creating a GitHub release does not publish to RubyGems; .github/workflows/ci.yml only runs checks.
Before changing the version, have Docker running, Ruby 3.1+ (for the release notes and install check), Git, and an authenticated GitHub CLI (gh). Confirm you can push signed commits to main and push tags. Load GEM_HOST_API_KEY as described under RubyGems Credentials before committing or tagging, and configure TRANSLOADIT_KEY and TRANSLOADIT_SECRET for the live test (the Docker test helper also reads .env).
Run the following steps from the repository root, in the same shell:
- Start with a clean checkout (
git status --shortmust be empty), then updatemain:git switch main git pull --ff-only origin main
- Update the version and changelog:
- Use semantic versioning: patch for fixes, minor for backward-compatible additions or deprecations, major for breaking changes or removals.
- Bump
lib/transloadit/version.rb. - Move the
CHANGELOG.mdUnreleased bullets under### X.Y.Z / YYYY-MM-DD, leaving an empty### Unreleasedheading above them. Use those bullets for the release notes. - Read the chosen version for the remaining commands, and confirm it has not already been tagged or published:
version=$(ruby -Ilib -rtransloadit/version -e 'puts Transloadit::VERSION') git ls-remote --tags origin "refs/tags/v$version" gem list transloadit --remote --exact --all --clear-sources --source https://rubygems.org
- Run the full Docker suite with Node signature parity and the live upload, then lint:
Confirm the parity and live tests ran rather than skipped. The live test uploads a fixture to Transloadit and requires working credentials.
TEST_NODE_PARITY=1 RUBY_SDK_E2E=1 ./scripts/test-in-docker.sh RUBY_SDK_E2E=0 ./scripts/test-in-docker.sh bundle exec standardrb - Commit only the release files with a signed commit, and create the annotated tag:
git add lib/transloadit/version.rb CHANGELOG.md git commit -S -m "Release v$version" git tag -a "v$version" -m "Release v$version"
- Push the commit and tag:
Wait for CI on this exact
git push origin main git push origin "v$version"maincommit to pass, including all supported Ruby versions and the e2e job. - Publish the gem using the helper script with the already-exported key:
If authentication or push permissions fail, stop and obtain the required access. If the version is already published, verify it before retrying; RubyGems versions cannot be overwritten.
./scripts/notify-registry.sh
- Publish the GitHub release notes from the version's changelog entry. This fails before creating a release if the entry is missing or empty, and requires the pushed tag:
( set -eu notes_file=$(mktemp) trap 'rm -f "$notes_file"' EXIT ruby -e ' version = ARGV.fetch(0) entry = File.read("CHANGELOG.md").split(/^### /).find { |section| section.start_with?("#{version} / ") } abort "No changelog entry for #{version}" unless entry notes = entry.lines.drop(1).join.strip abort "Empty changelog entry for #{version}" if notes.empty? puts notes ' "$version" > "$notes_file" gh release create "v$version" --verify-tag --title "v$version" --notes-file "$notes_file" )
- Verify the remote listing, then install the published gem in a scratch directory and check
uploads:without an API call:gem list transloadit --remote --exact --clear-sources --source https://rubygems.org ( set -eu scratch_dir=$(mktemp -d) trap 'rm -rf "$scratch_dir"' EXIT gem install transloadit --remote --clear-sources --source https://rubygems.org --version "$version" --no-document --install-dir "$scratch_dir/gems" GEM_HOME="$scratch_dir/gems" GEM_PATH="$scratch_dir/gems" ruby -rtransloadit -rstringio -e ' abort "Unexpected gem version" unless Transloadit::VERSION == ARGV.fetch(0) fields = {count: 2, enabled: false} assembly = Transloadit.new(key: "offline-smoke").assembly(uploads: {photo: StringIO.new("photo")}, fields: fields) instructions = assembly.to_hash abort "Upload leaked into JSON" if instructions.key?(:uploads) abort "Custom fields changed" unless instructions[:fields] == fields puts "transloadit #{Transloadit::VERSION}: uploads smoke passed" ' "$version" )
--remoteavoids a leftover local.gem, and--clear-sources --sourceselects rubygems.org even when other gem sources are configured. The smoke check builds Instructions without creating an Assembly; step 3 exercises multipart requests. Allow time for RubyGems indexing if the new version is not visible immediately.
- Use a RubyGems account authorized to push the
transloaditgem, with an API key granting Push rubygems permissions (and access totransloaditif the key is gem-scoped). - Export the key as
GEM_HOST_API_KEYthrough your secret manager or a separate credential file outside the checkout. Do not put the token in shell commands or logs. The publish helper requires this environment variable; it does not load.envor use the host's~/.gem/credentials. - Keep the publishing key out of the test
.env:scripts/test-in-docker.shpasses that entire file to the container running dependency installation, tests, and Node tooling. An exported hostGEM_HOST_API_KEYis not forwarded by the test helper. - Confirm the key is loaded without displaying it:
test -n "${GEM_HOST_API_KEY:-}"
That’s it! Thank you for contributing.