-
Notifications
You must be signed in to change notification settings - Fork 378
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4315 from DataDog/tonycthsu/trusted-publishing
Publish via Trusted Publishing
- Loading branch information
Showing
2 changed files
with
151 additions
and
4 deletions.
There are no files selected for viewing
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
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 | ||
# 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 | ||
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 |
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