How do you version shared CI steps and handle breaking changes?

This tests CI hygiene and consumer safety. Pin shared steps to immutable tags or SHAs, use semantic versioning, and force consumers to opt into breaking changes. Red flag: referencing a mutable branch like main for reusable workflows.
WHAT THIS TESTS: This question evaluates whether you understand reproducibility and blast-radius control in shared CI infrastructure. Interviewers want to know if you treat pipeline code like production code, using explicit versioning rather than mutable references that can inject failures into dozens of teams overnight.
A GOOD ANSWER COVERS: First, immutable references. Tag every release with a semantic version such as v1.2.3 and optionally provide a floating major tag like v1 that moves only for backward-compatible fixes. Second, consumer pinning. Every calling workflow should reference the exact tag or commit SHA so the build behavior is deterministic. Third, breaking-change discipline. When you introduce a breaking change, you cut a new major version tag like v2.0.0 and update documentation; you do not overwrite an existing tag. Fourth, migration path. Support the old major version for a deprecation window so teams are not forced to migrate during a critical release. Fifth, communication. Publish changelogs and use automated deprecation warnings inside the old action or workflow so consumers know the sunset date.
COMMON WRONG ANSWERS: Saying everyone should point to the main branch to get the latest features immediately. This is a red flag because branch references are mutable; a push to main can break every consuming pipeline instantly. Another mistake is claiming that semantic versioning alone is enough without explaining that consumers must actually pin to a specific version in their YAML. A third error is ignoring the social side: releasing v2 without a migration guide or deprecation period will stall adoption and frustrate teams.
LIKELY FOLLOW-UPS: How would you roll out a critical security patch that affects all versions? Would you ever use a floating tag like v1, and how do you update it safely? How do you test a reusable workflow before tagging it? What is the difference between a reusable workflow and a composite action, and does that change your versioning strategy?
ONE CONCRETE EXAMPLE: Suppose you maintain a shared deploy-to-staging action. You tag the current stable release as v1.0.0. A team references it as uses: org/actions/deploy-to-staging@v1.0.0. Later you need to change the required input from cluster-name to environment-name. You create a release branch, make the change, test it thoroughly, then tag it v2.0.0. You update the README with a migration snippet showing how to change the input key. You leave v1.0.0 untouched, so existing pipelines keep working. After 90 days you announce v1 deprecation but do not delete the tag, preserving old build reproducibility.
Source: docs.github.com
Read the original → docs.github.com
- #ci/cd
- #github actions
- #versioning
- #reusable workflows
- #devops
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.