Publish gem #3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Publish gem | |
# TODO: Implement a dry-run mode to verify the checks without publishing | |
on: workflow_dispatch | |
concurrency: "rubygems" # Only one publish job at a time | |
jobs: | |
verify-checks: | |
name: Verify commit status checks | |
runs-on: ubuntu-24.04 | |
permissions: | |
checks: read | |
outputs: | |
version: ${{ steps.version.outputs.version }} | |
steps: | |
- uses: actions/checkout@v4 | |
- uses: ruby/setup-ruby@v1 | |
with: | |
ruby-version: '3.3.7' | |
- id: version | |
run: echo "version=$(ruby -e 'puts Gem::Specification::load(Dir.glob("*.gemspec").first).version')" >> $GITHUB_OUTPUT | |
# Check if the gem version is already published | |
- name: Verify gem version | |
env: | |
GEM_VERSION: ${{ steps.version.outputs.version }} | |
run: | | |
if gem search datadog --exact --remote --version "$GEM_VERSION" | grep -q "($GEM_VERSION)"; then | |
echo "::error::Version $GEM_VERSION is already published" | |
exit 1 | |
else | |
echo "Version $GEM_VERSION is not published yet" | |
fi | |
# TODO: Verify draft release | |
# TODO: Verify milestone | |
# Check if the commit has passed all Github checks | |
# API: https://docs.github.com/en/rest/checks/runs?apiVersion=2022-11-28#list-check-runs-for-a-git-reference | |
- name: Verify check runs | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const checkRuns = await github.paginate(github.rest.checks.listForRef, { | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
ref: context.sha, | |
per_page: 100 | |
}); | |
const failedChecks = checkRuns.filter(check => | |
check.status === 'completed' && | |
check.conclusion !== 'success' && | |
check.conclusion !== 'skipped' | |
); | |
if (failedChecks.length > 0) { | |
const failedNames = failedChecks.map(c => c.name).join(', '); | |
core.setFailed(`Check runs failed: ${failedNames}`); | |
} | |
# Check if the commit has passed external CI checks | |
# API: https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#get-the-combined-status-for-a-specific-reference | |
- name: Verify commit status | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const { data: status } = await github.rest.repos.getCombinedStatusForRef({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
ref: context.sha | |
}); | |
if (status.state !== 'success') { | |
core.setFailed(`Commit status is ${status.state}`); | |
} | |
# Check if the commit has all the checks passed | |
- name: Verify deferred commit data | |
# NOTE: | |
# | |
# This step uses Github's internal API (for rendering the status of the checks in UI), | |
# which includes Github check runs and external CI statuses and possibly more. | |
# | |
# Although Github check runs and external CI statuses are already covered by the previous steps, | |
# it is still useful to have a double-check and also possibly unearth missing validations. | |
# | |
# However, not depending on Github's public API (REST/GraphQL) suggested that this might change in the future. | |
run: | | |
COMMIT_URL="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/commit/$GITHUB_SHA" | |
STATUS=$(curl -sS --fail --retry 3 --retry-delay 5 "$COMMIT_URL/deferred_commit_data" | jq -r ".data.statusCheckStatus.state") | |
if [ "$STATUS" != "success" ]; then | |
echo "::error::Status check state is '$STATUS'. See: $COMMIT_URL" | |
exit 1 | |
fi | |
rubygems-release: | |
name: Build and push gem to RubyGems.org | |
runs-on: ubuntu-24.04 | |
environment: "rubygems.org" # see: https://github.com/DataDog/dd-trace-rb/settings/environments | |
needs: verify-checks # Make sure to release from a healthy commit | |
permissions: | |
id-token: write | |
contents: write | |
env: | |
SKIP_SIMPLECOV: 1 | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Set up Ruby | |
uses: ruby/setup-ruby@v1 | |
with: | |
ruby-version: '3.3.7' | |
- run: bundle install | |
- uses: rubygems/release-gem@v1 | |
with: | |
attestations: false # PENDING decision for attestations | |
github-release: | |
name: Attach gem to GitHub release and publish | |
runs-on: ubuntu-24.04 | |
needs: | |
- verify-checks | |
- rubygems-release | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
GH_REPO: ${{ github.repository }} | |
GEM_VERSION: ${{ needs.verify-checks.outputs.version }} | |
permissions: | |
contents: write | |
steps: | |
- name: Download from RubyGems | |
run: | | |
gem fetch datadog --version ${GEM_VERSION} --verbose | |
- name: Attach to existing release draft | |
run: | | |
gh release upload "v${GEM_VERSION}" *.gem --clobber | |
gh release edit "v${GEM_VERSION}" --draft=false | |
# TODO: Close existing milestone and create next milestone |