Skip to content

Latest commit

 

History

History
116 lines (77 loc) · 15.5 KB

release.md

File metadata and controls

116 lines (77 loc) · 15.5 KB

GitHub Actions Release Workflow

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.

Inputs

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.

Release Validation

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.

Release Version

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.

Timezone

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.

Success and Failure Callbacks

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.

Permissions and Authentication

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.

Execution

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.

Command Environment

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.

Recovery Artifacts

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.