Operations 26 min read

Release Engineering Best Practices: Branching Models, CI/CD Guidelines, and Deployment Strategies

This article provides a comprehensive overview of release engineering, covering branch models, naming conventions, merge processes, Git commit standards, CI/CD stage design, environment isolation, artifact management, product delivery steps, deployment strategies, and rollback procedures to ensure reliable software releases.

DevOps Cloud Academy
DevOps Cloud Academy
DevOps Cloud Academy
Release Engineering Best Practices: Branching Models, CI/CD Guidelines, and Deployment Strategies

What is Release Engineering?

Release engineering is an emerging and fast‑growing discipline in software engineering that defines standards for application development and enforces strict processes to ensure reliability at product release. Release engineers are proficient in source‑code management, configuration management, development workflows, and customer support, adapting flexible processes to product needs.

Development Guidelines for Release Engineering

Branch Model

The development guidelines require the use of the git-flow branching model.

Main Branch

The main branch represents production‑ready code, contains the most stable version, and all commits must be tagged with a version number. Direct commits are prohibited; merges require QA approval.

Develop Branch

The develop branch integrates feature branches. Developers and maintainers may merge feature branches into develop, providing brief descriptions of the added functionality.

Feature Branch

Feature branches are children of develop, allowing parallel development of multiple features. Once a feature is designed and tested, the branch is merged back into develop.

Each new feature's code resides in its own feature branch, which can be pushed to the central repository for backup and collaboration.

Feature branches exist only in the developer's repository, not in the origin.

Feature branches never merge directly into main; they merge back into develop after completion.

UAT Branch

The User Acceptance Testing (UAT) branch is a pre‑production branch. After code is developed and tested in develop, it is merged into UAT.

The UAT branch is locked so developers cannot push directly; only maintainers may accept merge/pull requests.

After all tests pass, a release branch is created from UAT. Bug fixes are merged first into develop, not directly into UAT.

Release Branch

A release branch is derived from UAT to start a new release cycle. No new features are added; only documentation, bug fixes, and release‑related tasks occur. Version tags are created here, and after release the branch merges back into main and develop.

Hotfix/Bugfix Branch

Hotfix branches are created from main to quickly patch production issues. After fixing, the hotfix merges into both main and develop, then into the ongoing release branch, and the main branch receives a new version tag.

Branch Naming Conventions

Feature Branch

Feature branch names may use slashes or hyphens as separators and must match the regex /[a-z0-9-]+/ . Examples include feature/* , feature/gitlab-integration , feature/ticket_id , feature-* , feature-slack-integration .

Release Branch

Names follow the pattern release/* , e.g., release-1.0.0 .

Hotfix Branch

Names follow hotfix/* , e.g., hotfix/broken-link .

Merge Process

Developers should follow a proper merge workflow: confirm the target branch, fetch the latest remote commits, and apply the merge. The typical flow is feature/branch_name → develop → UAT → Release → Master .

Git Commit Guidelines

Commit messages should be concise (≤50 characters, ≤72 characters for the body), descriptive, and start with a capitalized subject that does not end with a period. Include issue numbers when relevant. Examples of good messages: "Add Dockerfile" , "Fix github integration error." , "Add Hindi & English translation." .

CI/CD Guidelines for Release Engineering

CI/CD Stages

Each branch defined in the development guidelines must have a strict CI/CD pipeline composed of the stages listed below.

Feature/Hotfix Branch

Unit Testing

Integration Testing

Build

Push

Deploy code (if required)

Develop Branch

Code Quality Check

Unit Testing

Integration Testing

Functional Testing

Build

Push

Deploy to Dev

UAT Branch

SAST

DAST

Browser Performance Testing

Load Testing

Fuzz Testing

Build

Push

Deploy to UAT

Release branches contain only release‑ready code and focus on documentation, final polishing, and minor bug fixes. They may also run a CI/CD pipeline for final verification before merging into main, which then serves only as a mirror of production.

Main (master) branch pipeline includes Build, Push, and Deploy to Prod.

Stage Definitions

Code Quality Check: Automated analysis of source code to ensure simplicity, readability, and contribution friendliness.

Unit Testing: Tests individual units or components at the source‑code level to verify correct behavior.

Integration Testing: Tests combined units to uncover faults in their interactions.

Functional Testing: Black‑box testing that validates the system against functional requirements.

SAST: Static Application Security Testing scans source code and binaries for vulnerabilities before deployment.

DAST: Dynamic Application Security Testing evaluates a running web application for known runtime vulnerabilities.

Browser Performance Testing: Automated testing of web performance, generating artifact reports.

Load Testing: Measures system response under load to inform performance decisions.

Fuzz Testing: Supplies unexpected or random inputs to uncover stability issues and hidden bugs.

Build: Packages source code and dependencies into a Docker image.

Push: Pushes the built Docker image to a private Harbor registry with appropriate tags.

Deploy: Deploys the artifact to the environment associated with the branch (dev, UAT, or prod).

Best Practices for CI/CD Stage Design

All non‑release branches must include Build and Push stages.

Deploy stages are added only when testing requires them; develop deploys to a dedicated dev environment, UAT deploys to a UAT environment, and production deploys from the main branch.

Release branches should not have any pipeline stages; they focus on documentation and final polishing.

Feature/Hotfix pipelines run only unit and integration tests.

Develop pipelines run unit, integration, and functional tests.

UAT pipelines run all security and performance tests (SAST, DAST, browser performance, load, fuzz).

After UAT testing, the main branch pipeline can skip tests and deploy directly.

Environment Definition

Separate isolated environments are required for DEV, UAT, and PROD. Ideally each environment runs on its own Kubernetes cluster; alternatively, a single cluster with distinct namespaces and network policies can be used.

Based on Environment Naming Conventions

Hostnames should follow the pattern: dev.example.com for DEV, uat.example.com for UAT, and example.com for PROD.

Artifact Management

All deliverables—source code, meeting notes, workflow diagrams, data models, risk assessments, use cases, prototypes, and compiled applications—are considered artifacts. They must be versioned and stored in an artifact repository such as Artifactory. Docker images should be tagged with project, repository, branch, and pipeline identifiers (e.g., life-data/stt-server:develop123456 ).

How to Deliver Your Product to End Users?

Product Delivery to End Users

Developers create a Changelog file for each microservice.

The production code must include a README.

QA signs off; without QA approval, code cannot be merged to production.

Product team prepares user and reference documentation.

Sales and marketing obtain a basic understanding of the product before client discussions.

Support team receives training to handle user issues.

Release engineers compile a release checklist covering all necessary items.

After checklist completion, developers create a release branch for version control and tagging, following semantic versioning.

The release branch is merged into the production branch.

How to Choose the Right Deployment Strategy?

Recreate: Terminate all old pods, then start new ones (downtime).

Ramped (Rolling Update): Gradually replace old pods with new ones.

Blue/Green: Deploy new version alongside old, switch traffic after validation.

Canary: Release new version to a subset of users before full rollout.

A/B Testing: Direct a portion of traffic to the new version under specific conditions.

Shadow: Run new version in parallel, mirroring traffic without affecting responses.

Recreate

All existing pods are terminated at once and replaced by new pods, causing downtime. Use when the application cannot tolerate multiple versions or when you need to stop processing old data before starting new workloads.

Rolling Update

Kubernetes default strategy; new pods replace old pods gradually without downtime. The update can be aborted if issues arise. Configuration includes max surge and max unavailable settings.

Blue‑Green

Both old and new versions are deployed simultaneously; QA tests the new version, then traffic is switched. Benefits include zero‑downtime rollbacks and quick disaster recovery, but it incurs higher cost due to duplicate environments.

Canary

A portion of user traffic is routed to the new version to observe behavior before full rollout. Useful for early detection of issues and gathering feedback.

A/B Testing

Routes a subset of users to the new version to evaluate business impact. Provides full control over traffic allocation but requires a costly setup.

Shadow

New version receives a copy of production traffic for testing without affecting real users. Allows performance testing with real load but adds complexity and cost.

What Is a Rollback? Its Role in Release Management

A rollback restores an object to a previous stable state when a deployment is unstable or produces unexpected results.

Identify the cause of the failure via pod logs and status (e.g., CrashLoopBackOff, ImagePullBackOff).

If the issue cannot be fixed, initiate a rollback.

Inspect the rollout history with kubectl rollout history deployment.v1.apps/<deployment-name> to find a stable revision.

Undo to the chosen revision using kubectl rollout undo deployment.v1.apps/<deployment-name> --to-revision=<revision-number> .

Describe the deployment to verify the configuration with kubectl describe deployment <deployment-name> .

By default, Kubernetes retains the last 10 ReplicaSets; this limit can be adjusted via spec.revisionHistoryLimit in the deployment manifest.

Conclusion

Release engineering is a rapidly evolving field that provides a systematic approach from development to reliable product delivery. Organizations must establish robust release engineering processes to ship high‑quality products quickly and safely.

CI/CDoperationsDeploymentKubernetesrelease engineeringbranching
DevOps Cloud Academy
Written by

DevOps Cloud Academy

Exploring industry DevOps practices and technical expertise.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.