Skip to content

Commit 44bd17f

Browse files
perryqhclaude
andauthored
Auto-trigger CD when CI passes and the gem version is bumped (#171)
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 6cd5c42 commit 44bd17f

1 file changed

Lines changed: 67 additions & 2 deletions

File tree

.github/workflows/cd.yml

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,60 @@
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+
with:
34+
sparse-checkout: lib/code_ownership/version.rb
35+
sparse-checkout-cone-mode: false
36+
fetch-depth: 1
37+
- id: check
38+
run: |
39+
VERSION=$(ruby -r ./lib/code_ownership/version.rb -e "puts CodeOwnership::VERSION")
40+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
41+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
42+
# Manual dispatch always proceeds (dry-run testing / forced release);
43+
# the publish step still skips versions already on RubyGems.
44+
SHOULD_RELEASE=true
45+
REASON="manual dispatch (dry_run=${{ inputs.dry_run }})"
46+
elif curl -sf -o /dev/null "https://rubygems.org/api/v2/rubygems/code_ownership/versions/${VERSION}.json"; then
47+
SHOULD_RELEASE=false
48+
REASON="${VERSION} already on RubyGems — skipping release"
49+
else
50+
SHOULD_RELEASE=true
51+
REASON="${VERSION} not published — will release"
52+
fi
53+
echo "should_release=${SHOULD_RELEASE}" >> "$GITHUB_OUTPUT"
54+
echo "::notice::code_ownership ${REASON}."
55+
1356
ci-data:
57+
needs: check-release
58+
if: needs.check-release.outputs.should_release == 'true'
1459
runs-on: ubuntu-latest
1560
outputs:
1661
result: ${{ steps.fetch.outputs.result }}
@@ -129,6 +174,11 @@
129174
for i in *.gem; do
130175
if [ -f "$i" ]; then
131176
echo "⏳ Attempting to push $i..."
177+
if [ "${{ inputs.dry_run }}" = "true" ]; then
178+
echo "🧪 dry-run: would push $i (skipping)"
179+
SKIPPED_GEMS+=("$i")
180+
continue
181+
fi
132182
if ! gem push "$i" >push.out 2>&1; then
133183
gemerr=$?
134184
if grep -q "Repushing of gem" push.out; then
@@ -179,4 +229,19 @@
179229
--title "v${{ steps.push-gem.outputs.gem_version }}" \
180230
--notes "$RELEASE_NOTES" \
181231
--generate-notes \
182-
pkg/*.gem
232+
pkg/*.gem
233+
234+
notify_on_release:
235+
runs-on: ubuntu-latest
236+
needs: [check-release, release]
237+
if: ${{ needs.release.result == 'success' }}
238+
env:
239+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
240+
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
241+
steps:
242+
- uses: slackapi/slack-github-action@v1.25.0
243+
with:
244+
payload: |
245+
{
246+
"text": "🎉 Released ${{ github.repository }} v${{ needs.check-release.outputs.version }}"
247+
}

0 commit comments

Comments
 (0)