Reference for .github/workflows/release.yml, invoked with workflow_call. See Usage for a caller example and Detailed Usage for customization. See RELEASING.md for branch permissions. Trusted Publishing is required setup in Usage.
For a step-based interface with caller-owned job settings, see the Composite Action. Both interfaces invoke the same Ruby release tasks; the reusable workflow keeps its own runner, environment, permissions contract, and concurrency group.
Set these under the calling job's with: mapping. Only ruby-version is required.
| Input | Type | Default | Behavior |
|---|---|---|---|
ruby-version |
String | Required | Ruby version used for validation and building. |
version |
String | Empty | Selected numeric MAJOR.MINOR.PATCH release version, without leading zeros. Overrides the checked-in version in standard preparation. |
gemspec |
String | Empty | Specification path, defaulting to the only root gemspec. Missing or ambiguous specifications fail. |
rubygems-owner |
String | Empty | Numeric RubyGems account ID required for a new gem's pending trusted publisher to create it. |
timezone |
String | UTC |
Installed timezone identifier for the release calendar date and Git timestamp offsets. |
validate |
String | bundle exec rake release:validate |
Check release preconditions before edits; exit nonzero on failure. |
prepare |
String | bundle exec rake release:prepare |
Prepare release files before version resolution and testing. |
test |
String | bundle exec rake |
Test prepared release files before publication. |
publish |
String | bundle exec rake release:publish |
Commit, build, tag, publish to RubyGems, push atomically, and create a GitHub Release through the configured callback. |
bump |
String | bundle exec rake release:bump |
Prepare, commit, and push the next development iteration through the configured callback. |
success |
String | bundle exec rake release:success |
Run after publication and the next development iteration succeed. |
failure |
String | bundle exec rake release:failure |
Run after a release job failure, after Ruby setup. |
git-user-name |
String | github-actions[bot] |
Checkout-local author name for release and next development iteration commits. |
git-user-email |
String | github-actions[bot]@users.noreply.github.com |
Checkout-local author email for release and next development iteration commits. |
Identity values must be nonempty and contain no line breaks. They change commit attribution, not authentication or push permissions.
Validation runs after context capture, before preparation edits. Empty pending notes fail unless the selected release already has a changelog heading, allowing repetition. Malformed content also fails. With no changelog, validation passes. Custom changelog objects implement pending? and released?(version) or supply a validate: callback.
A custom validate command must exit nonzero on invalid state; normal completion succeeds. Ruby callbacks raise on failure, and returning false also fails. No output protocol is required.
A validation error fails the job, stops downstream release operations, and invokes failure handling after successful Ruby setup.
Set version: '1.2.3' under with: to select a release version instead of the one checked in. The standard workflow calls the configured version object's set! method before preparing the changelog; an empty input leaves the checked-in version unchanged. The release commit includes the version and changelog changes, and the next development iteration increments from the selected version. The initial gemspec version and captured date remain available to callbacks.
Expose a string version input in the caller's workflow_dispatch form and forward it with version: ${{ inputs.version }}. You can then choose it in GitHub's form or run gh workflow run release.yml -f version=1.2.3. No release is performed by adding this input.
Custom preparation commands and callbacks must honor the selection; resolution rejects a mismatched prepared gemspec before publication. Custom version objects must implement set! when selecting a version. See UPGRADING.md for migrations.
Set timezone: America/New_York under with: to use Eastern Time, including daylight saving changes. UTC remains the default.
The interfaces set TZ and capture the local calendar date once as RELEASE_DATE, preserving it across callbacks even if the release crosses midnight. Git commits retain their actual creation times with offsets in the selected timezone. GitHub and RubyGems generate their own publication timestamps; this input does not change those service timestamps.
Identifiers must resolve to files under the runner's /usr/share/zoneinfo directory. Unknown identifiers, empty values, fixed-offset strings, and traversal paths fail before release preparation or publication. Use a named timezone rather than a fixed offset so daylight saving changes are handled correctly.
To disable only GitHub Release creation, set hosting: nil in the standard workflow or omit github.publish! from manual callbacks rather than disabling publish.
The success command runs after the publication and next development iteration phases succeed. The failure command runs after a failed phase once Ruby setup has completed; its callback receives a RubyGemRelease::ReleaseFailure with the failed phase, an exception captured from a Ruby task when available, and an execution context whose release value is optional. Failures reported only by GitHub Actions have no exception object. Both default to optional Rake callbacks and are no-ops when none are registered. Failure before Ruby setup or a job blocked by environment protection cannot invoke the callback.
Once the repository and gem owners complete setup, collaborators with write access can dispatch the release workflow, including in personal repositories. They do not need repository admin access, RubyGems ownership, or their own RubyGems API key. Dispatch permission is not publication approval: with required maintainer reviewers, publication remains blocked until a designated maintainer approves the release environment.
Environments do not provide a workflow-dispatch allow list, and creating one without protection rules does not restrict release access.
Authentication belongs to release:publish, which invokes the configured destination's authentication hook before its publication callback. Neither YAML interface contains a registry-specific authentication step or condition. The RubyGems destination uses RubyGemsCredentials, requesting a GitHub OIDC token for audience rubygems.org, exchanging it, masking both credentials, and exporting the short-lived key for publication. For a brand-new gem, register a pending trusted publisher and set rubygems-owner to the numeric account ID shown on that page; the helper includes that owner assertion. For existing gems, omit the input and the exchange omits the owner field.
Authentication exports RUBYGEMS_API_KEY, BUNDLE_GEM__PUSH_KEY, and GEM_HOST_API_KEY; it does not create or modify ~/.gem/credentials. Custom publication commands must inherit these variables rather than assume a credentials file or named key exists. See the custom publication contract.
The caller needs contents: write for Git and hosting and id-token: write for RubyGems Trusted Publishing. Configure the release environment and publisher as described in Usage. No stored RubyGems API key is required.
The base destination's authentication hook retains preconfigured credentials. Custom destinations can override it without adding or changing YAML steps. A publish command override that bypasses release:publish must own authentication as well as publication. See Registry Destinations.
The workflow supplies GH_TOKEN during publication. Branch rules must permit fast-forward pushes while retaining force-push and deletion restrictions.
After ruby/setup-ruby installs dependencies, context capture requires a clean checkout before preparation: tracked/index changes and untracked non-ignored files fail with actionable paths. Ignored Bundler output is allowed; tracked dependency artifacts are not. Resolving the prepared version stages the trusted prepare command's outputs and records the index tree before testing. The publication callback refuses later working tree or index changes rather than staging unrelated files. Custom commands own their operations; wrap custom next development iteration edits in git.stage_changes! as shown in Detailed Usage.
The job runs on ubuntu-latest in the release environment. After full checkout and Ruby setup, capture uses the current checkout and inputs. Commands always run and own their idempotence; there is no cross-run artifact discovery or state restoration. A checkpoint commits, builds, and tags locally; artifact preservation must succeed before publish and bump. Failures prevent later phases.
New releases require the current default-branch commit. Reruns can reuse matching release commits and tags without rewinding remote descendants. Git rejects conflicting tags and unrelated advancement. Concurrency is grouped by repository without canceling a running release.
Commands run through bash -euo pipefail. Overrides replace the corresponding phase and must perform its required operations; callback registration alone does not cause an overridden command to invoke a task.
| Variable | Availability | Meaning |
|---|---|---|
INPUT_VERSION |
All phases | Optional selected release version. |
INPUT_GEMSPEC_PATH |
All phases | Optional gemspec path supplied by the caller. |
GEMSPEC_PATH |
After capture | Selected absolute gemspec path. |
GEMSPEC_VERSION |
After capture | Gemspec version captured before preparation, retained across callbacks. |
SOURCE_REF |
Provider-neutral | Source Git ref; GitHub uses GITHUB_REF instead. |
SOURCE_COMMIT |
After capture | Source commit hash captured before release preparation. |
RELEASE_VERSION |
After resolution | Prepared version to publish. |
RELEASE_DATE |
After capture | Date captured once in the configured timezone, as YYYY-MM-DD. |
RELEASE_DATA_DIR |
After capture | Artifacts and private task data; maps to RUNNER_TEMP on Actions, not the checkout. |
RELEASE_STATE_FILE |
After capture | Private invocation-specific JSON file for callback data. |
RELEASE_COMMAND |
Commands | Configured shell command for the current phase. |
RELEASE_STEP_ID |
Commands | Current enclosing Actions step ID. |
RELEASE_STEPS_JSON |
Commands | JSON snapshot of previously observed Actions steps. |
RELEASE_FAILED_STEP_ID |
Failure callback | Failed step or task ID, or unknown. |
RELEASE_AUTH_MODE |
After resolution | Destination authentication strategy, or empty for existing credentials. |
DEFAULT_BRANCH |
All phases | Repository default branch. |
GIT_USER_NAME, GIT_USER_EMAIL |
All phases | Configured checkout-local commit identity. |
RUBYGEMS_OWNER_ID |
All phases | Optional numeric RubyGems account ID for owner-bound authentication. |
TZ |
All phases | Configured timezone; defaults to UTC. |
SOURCE_DATE_EPOCH |
After capture | Source commit timestamp for reproducible packages, unless explicitly supplied. |
GH_TOKEN |
Publish | GitHub Actions token for hosted releases. |
GitHub also supplies standard variables such as GITHUB_REPOSITORY and RUNNER_TEMP. See Execution Context for step, run, and state semantics, Tasks for callbacks, and Workflow::Environment for capture and resolution methods.
The workflow requires release.gem, its name/version/digest manifest release.json, and release.bundle to be uploaded before publication, retained for 30 days under release-gem-VERSION-RUN_ID-RUN_ATTEMPT. These support manual inspection, not automatic restoration. See RELEASING.md.