Skip to content

Auto-trigger CD when CI passes and the gem version is bumped#171

Merged
perryqh merged 1 commit into
mainfrom
auto-cd-on-version-bump
Jul 1, 2026
Merged

Auto-trigger CD when CI passes and the gem version is bumped#171
perryqh merged 1 commit into
mainfrom
auto-cd-on-version-bump

Conversation

@perryqh

@perryqh perryqh commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

What & why

Today cd.yml only runs via workflow_dispatch (manual). This wires it to fire automatically after CI succeeds on main, when the version in lib/code_ownership/version.rb isn't already on RubyGems.

It follows the rubyatscale shared-config convention — a workflow_run trigger, with CD reading its secrets directly — the same pattern used by code_teams, packs-specification, rubocop-packs, etc.

We can't simply call shared-config's reusable cd.yml, because this gem builds cross-platform native binaries (the oxidize-rb matrix) rather than a pure-Ruby gem. So CD stays bespoke — but the trigger shape now matches the ecosystem.

Changes (all in cd.yml; ci.yml untouched)

  • Trigger on workflow_run (workflows: [CI], types: [completed], branches: [main]) instead of workflow_call; keep workflow_dispatch.
  • check-release gate job — reads CodeOwnership::VERSION and asks the RubyGems API whether it's published (curl -sf), proceeding only when the version is unpublished. This is our one deliberate 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. Uses a sparse, shallow checkout (only version.rb).
  • Gate ci-data/build/release on check-release and on the triggering CI run's conclusion == 'success'.
  • dry_run input on 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.
  • notify_on_release — Slack "Released v" on success.

Consistency with shared-config

Aspect shared-config convention This PR
CI->CD trigger on: workflow_run same
Secrets read directly via secrets.* same (read directly; no inherit)
Version-bump gate none (publish action no-ops) check-release -- justified by binary build cost
Build internals discourse/publish-rubygems-action oxidize-rb matrix -- the binary special case

Secrets note: both workflows read secrets.RUBYGEMS_API_KEY / GITHUB_TOKEN / SLACK_WEBHOOK_URL directly. secrets: inherit only applies when one workflow calls another via uses: -- which this approach doesn't do -- so there's nothing to inherit or declare.

Testing (no real publish required)

  1. Gate, locally -- curl -sf the RubyGems API: 2.1.3 succeeds (published), 99.99.99 fails (unpublished).
  2. Full chain, dry-run -- dispatch cd.yml with dry_run: true: builds the gem matrix and runs the whole job graph without publishing.
  3. First real release -- happens on the first version-bump merge to main; idempotent (skip-if-exists), with workflow_dispatch as fallback.

Known follow-up (not in this PR)

notify_on_release fires whenever the release job succeeds, including a manual dry_run dispatch where nothing was actually published (spurious "Released" ping). Gating it on the push step's new_version would require exposing that as a job output -- left for a follow-up.

🤖 Generated with Claude Code

@perryqh perryqh requested a review from a team as a code owner June 18, 2026 16:12
@github-project-automation github-project-automation Bot moved this to Triage in Modularity Jun 18, 2026
@perryqh perryqh force-pushed the auto-cd-on-version-bump branch from 4a7d6f8 to 7934e58 Compare June 18, 2026 16:30
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>
@perryqh perryqh force-pushed the auto-cd-on-version-bump branch from 7934e58 to a94c2dd Compare June 18, 2026 17:07
@perryqh perryqh merged commit 44bd17f into main Jul 1, 2026
10 checks passed
@perryqh perryqh deleted the auto-cd-on-version-bump branch July 1, 2026 20:42
@github-project-automation github-project-automation Bot moved this from Triage to Done in Modularity Jul 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants