Skip to content

Commit 7934e58

Browse files
perryqhclaude
andcommitted
Auto-trigger CD when CI passes and the gem version is bumped
Previously CD only ran via workflow_dispatch. Wire it to fire automatically after CI succeeds on main, following the rubyatscale shared-config convention (workflow_run trigger, secrets read directly by CD) used by code_teams, packs-specification, rubocop-packs, etc. We can't call shared-config's reusable cd.yml because this gem builds cross-platform native binaries (oxidize-rb matrix) rather than a pure Ruby gem, so CD stays bespoke — but the trigger shape now matches. cd.yml: - Trigger on workflow_run (workflows: [CI], types: [completed], branches: [main]) instead of workflow_call; keep workflow_dispatch. - Add a check-release gate job: reads CodeOwnership::VERSION and queries the RubyGems API, proceeding only when the version is unpublished. This gate is our one deviation from shared-config — it avoids running the expensive cross-compile matrix on every main merge (shared-config doesn't need it because its publish action no-ops cheaply). Manual dispatch bypasses the gate to support dry-run testing / forced runs. - Gate ci-data/build/release on check-release and on the triggering CI run's conclusion == 'success'. - Add a dry_run input to workflow_dispatch that skips the irreversible gem push (logs "would push"), making the full pipeline testable manually without publishing. The Release step is already gated on new_version, so it skips automatically in dry-run. - Add a notify_on_release Slack notification on successful release. ci.yml is left untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent d861735 commit 7934e58

1 file changed

Lines changed: 65 additions & 2 deletions

File tree

.github/workflows/cd.yml

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,58 @@
22
name: CD
33

44
on:
5-
workflow_call:
5+
workflow_run:
6+
workflows: [CI]
7+
types: [completed]
8+
branches: [main]
69
workflow_dispatch:
10+
inputs:
11+
dry_run:
12+
type: boolean
13+
default: false
14+
description: "Build gems but don't publish or release"
715

816
concurrency:
917
group: ${{ github.workflow }}-${{ github.ref }}
1018
cancel-in-progress: true
1119

1220
jobs:
21+
check-release:
22+
name: Check if release needed
23+
runs-on: ubuntu-latest
24+
# Only proceed when the triggering CI run succeeded (auto path) or on manual dispatch.
25+
if: >-
26+
github.event_name == 'workflow_dispatch' ||
27+
github.event.workflow_run.conclusion == 'success'
28+
outputs:
29+
should_release: ${{ steps.check.outputs.should_release }}
30+
version: ${{ steps.check.outputs.version }}
31+
steps:
32+
- uses: actions/checkout@v6
33+
- id: check
34+
run: |
35+
VERSION=$(ruby -r ./lib/code_ownership/version.rb -e "puts CodeOwnership::VERSION")
36+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
37+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
38+
# Manual dispatch always proceeds (supports dry_run testing and forced releases);
39+
# the publish step itself still skips versions already on RubyGems.
40+
echo "should_release=true" >> "$GITHUB_OUTPUT"
41+
echo "::notice::Manual dispatch — proceeding (dry_run=${{ inputs.dry_run }})."
42+
else
43+
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
44+
"https://rubygems.org/api/v2/rubygems/code_ownership/versions/${VERSION}.json")
45+
if [ "$STATUS" = "200" ]; then
46+
echo "should_release=false" >> "$GITHUB_OUTPUT"
47+
echo "::notice::code_ownership ${VERSION} already on RubyGems — skipping release."
48+
else
49+
echo "should_release=true" >> "$GITHUB_OUTPUT"
50+
echo "::notice::code_ownership ${VERSION} not published — will release."
51+
fi
52+
fi
53+
1354
ci-data:
55+
needs: check-release
56+
if: needs.check-release.outputs.should_release == 'true'
1457
runs-on: ubuntu-latest
1558
outputs:
1659
result: ${{ steps.fetch.outputs.result }}
@@ -129,6 +172,11 @@
129172
for i in *.gem; do
130173
if [ -f "$i" ]; then
131174
echo "⏳ Attempting to push $i..."
175+
if [ "${{ inputs.dry_run }}" = "true" ]; then
176+
echo "🧪 dry-run: would push $i (skipping)"
177+
SKIPPED_GEMS+=("$i")
178+
continue
179+
fi
132180
if ! gem push "$i" >push.out 2>&1; then
133181
gemerr=$?
134182
if grep -q "Repushing of gem" push.out; then
@@ -179,4 +227,19 @@
179227
--title "v${{ steps.push-gem.outputs.gem_version }}" \
180228
--notes "$RELEASE_NOTES" \
181229
--generate-notes \
182-
pkg/*.gem
230+
pkg/*.gem
231+
232+
notify_on_release:
233+
runs-on: ubuntu-latest
234+
needs: [check-release, release]
235+
if: ${{ needs.release.result == 'success' }}
236+
env:
237+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
238+
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
239+
steps:
240+
- uses: slackapi/slack-github-action@v1.25.0
241+
with:
242+
payload: |
243+
{
244+
"text": "🎉 Released ${{ github.repository }} v${{ needs.check-release.outputs.version }}"
245+
}

0 commit comments

Comments
 (0)