Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Publish via Trusted Publishing #4315

Merged
merged 11 commits into from
Feb 3, 2025
141 changes: 141 additions & 0 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
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
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved
# 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'
- uses: rubygems/release-gem@v1
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved
with:
attestations: false # PENDING decision for attestations

github-release:
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved
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
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved
- name: Attach to existing release draft
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved
run: |
gh release upload "v${GEM_VERSION}" *.gem --clobber
gh release edit "v${GEM_VERSION}" --draft=false
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved

# TODO: Close existing milestone and create next milestone
14 changes: 10 additions & 4 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,22 @@ build-gem:
image: $DOCKER_REGISTRY/images/mirror/ruby:3.2.2
stage: package
script:
- mkdir -p pkg tmp
- |
if [ -z "$CI_COMMIT_TAG" ]; then
if [ -n "$CI_COMMIT_TAG" ]; then
.gitlab/check_gem_presence.sh
VERSION=${CI_COMMIT_TAG#v}
gem fetch datadog --version $VERSION
TonyCTHsu marked this conversation as resolved.
Show resolved Hide resolved
mv datadog-*.gem pkg/
echo $VERSION > tmp/version
else
echo CI_JOB_ID=$CI_JOB_ID
echo CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME
echo CI_COMMIT_SHA=$CI_COMMIT_SHA
.gitlab/patch_gem_version.sh glci $CI_JOB_ID $CI_COMMIT_REF_NAME $CI_COMMIT_SHA
bundle install && chmod go-w -R . && bundle exec rake build
ruby -Ilib -rdatadog/version -e 'puts Gem::Version.new(Datadog::VERSION::STRING).to_s' >> tmp/version
fi
- bundle install && chmod go-w -R . && bundle exec rake build
- mkdir -p tmp && ruby -Ilib -rdatadog/version -e 'puts Gem::Version.new(Datadog::VERSION::STRING).to_s' >> tmp/version
artifacts:
paths:
- pkg
Expand Down
Loading