← More Software Startup Field Notes

Field Note · Software startup · Japan · Sri Lanka · 2023 · 2024 · Case study

Turning Multiple Daily Deployments into a Controlled Release Pipeline

During peak delivery periods, a small implementation team sometimes had to release the same project to several environments multiple times in one day.

The manual process consumed a large part of the team's time. As pressure and repetition increased, so did the opportunity for missed steps, inconsistent releases, and human error.

The goal was to remove repetitive deployment work while preserving deliberate control over what reached staging and production.

Build one repeatable delivery path

Because the source code was already hosted on GitHub, we selected GitHub Actions as the continuous integration and delivery platform.

We created multi-stage workflows that:

  • Ran the automated tests
  • Built the application
  • Created the Docker image
  • Published the image to the external registry
  • Pulled the approved image into the target environment
  • Deployed it as a container

The same defined sequence replaced environment-specific manual instructions. A release could no longer skip a build or deployment step simply because the team was busy.

Give each environment an appropriate trigger

Development deployments ran when feature or bug-fix branches were merged into the development branch. Staging deployments were triggered from an approved tag.

Production releases used the selected tag but required a deliberate manual workflow trigger. This kept the execution automated while preserving a human decision at the most sensitive point.

Production containers were deployed to Azure App Service. Separating the triggers reduced accidental promotion between environments and made the intended release version explicit.

Protect credentials and permissions

Deployment credentials were stored as GitHub secrets rather than embedded in workflow files or source code. Workflow permissions were restricted according to what each job needed, reducing the reach of a compromised or incorrectly configured action.

Production access remained separate from lower-environment access. The pipeline could use sensitive deployment values only within the relevant workflow context.

Reduce pipeline time and control cost

Automation itself introduced a new cost to manage: GitHub Actions runner minutes.

Docker layer caching was enabled so unchanged dependencies and build layers did not need to be recreated during every run. This shortened repeated builds and reduced avoidable action usage.

Budgets were also configured for usage beyond the included action minutes. This gave the company a defined financial boundary rather than allowing frequent deployments to create an open-ended automation bill.

What changed

The pipeline eliminated the repetitive manual execution steps involved in ordinary deployments. The team no longer had to remember and perform the full test, build, image, transfer, and container-release sequence for each environment.

That did not remove all deployment responsibility. People still decided what should be released, approved production changes, monitored the workflow, verified the deployed service, and responded when a release failed.

The practical lesson is that deployment automation should remove repetition without removing judgment. A useful pipeline makes releases consistent, protects sensitive environments, controls its own operating cost, and leaves people responsible for the decisions that should remain human.