What you push is what production runs: deploying from a git branch
A good deal of hosting still works the simplest way there is. You push to a git branch, the platform notices, and it deploys whatever it finds there. It is a clean model, and it puts an awkward requirement on your repository.
Your repository is not what production needs. It carries the parts a team builds with:
- development tooling
- test suites
- source assets
- build configuration
What it does not carry is the compiled CSS, installed dependencies and vendor code the running site depends on. Something has to bridge that gap, and for most teams that something is a deployment script written once, under time pressure, and then trusted forever.
That step is worth thinking about carefully, because of everything in a pipeline it is the one that can fail quietly.
A build that breaks stops the pipeline and tells you. A deployment that publishes the wrong contents raises nothing at all. It simply goes live.
A deployment step designed to refuse: dry runs, no-change guards and tag collisions
git-artifact(Opens in a new tab/window) builds the deployable artifact inside CI and commits only that to the separate repository your host watches. Development tooling stays out of the deployed package, which keeps the running site lean and narrows what is exposed there.
The part we care about most is what it does when something is not right. It refuses in 3 independent ways, each covering a different way a deployment can go wrong without anyone noticing:
- pushing is a dry run unless you explicitly ask for a deploy, so the default invocation prints what it would do and writes nothing to the remote
- if the artifact it has just built is identical to what is already deployed and no new tags are involved, it stops rather than adding noise to the history
- if a tag would collide with one already on the destination, it stops there too
For a client, that reads as a deployment that stops rather than guesses: when something does not look right, the pipeline says so instead of publishing quietly.
Underneath those refusals sits the ordinary work of getting an artifact right:
- a manifest controls exactly what goes in
- a watermark in each commit message lets the tool find where it left off on a repository it does not own, which is what makes incremental artifact builds possible at all
- tags are carried across with collision detection
- symlinks survive the copy instead of being flattened into broken files
All of it was built test first, against a suite that provisions real throwaway git repositories rather than mocking them. Testing a deployment tool that way is slow and awkward. It is also the only way to know the safety rails actually fire.
Where it came from: a 2017 client audit, extracted as open source
git-artifact started inside client work. In 2017 we were auditing a dual-sector university's TAFE website platform, and we rebuilt its deployment step from the ground up: written test first in PHP, with the refusals above and a test suite that exercised every one of them.
2 years later, we did the part that mattered more. We lifted it out of the client's codebase and published it as a standalone open-source package, so every project after it inherited the same tested deployment step at no cost to anyone.
That is a habit rather than a one-off. When client work produces a piece of engineering that is better than that one project strictly needed, we take it out, publish it and maintain it. git-artifact is the earliest example and still the clearest one.
For a client, that habit reads as inherited engineering: the deployment step on your platform arrives already built, already tested and already maintained, rather than written fresh under time pressure.
Still deploying, 9 years on: Vortex, Acquia Cloud and Lagoon
git-artifact is maintained and in service 9 years after the first version and 7 after it became a package. It ships with Vortex(Opens in a new tab/window), our open-source Drupal(Opens in a new tab/window) project template, and it is the deployment mechanism for Vortex-based projects on git-deployed hosting, including Acquia Cloud and Lagoon.
9 years in service, 7 of them as an open-source package other projects inherit.
For a tool whose whole job is to say no at the right moments, longevity is the measure that counts. It has been doing the same careful thing in other people's pipelines for the better part of a decade, and the teams using it rarely have to think about it.
For pipelines whose deploy step nobody has read
Everything on this page is 4 of our services pointed at our own tooling: the architecture of a deployment step, the development of the package that implements it, the DevOps engineering it exists to protect, and the ongoing support and maintenance that has kept it current since 2017. It is the same rule we apply to AI-assisted delivery: however quickly a change is written, it reaches production through a deployment step that has been tested.
If you run a site deployed from a git branch, on hosting like Acquia Cloud or Lagoon, and the step that gets your build there is a script somebody wrote once, this is the shape the engagement takes. The deploy step becomes a tested, maintained package: a dry run by default, a refusal when something does not look right, and only the built site in front of your visitors.
If nobody on your team can say what your pipeline actually pushes to production, show us your deploy step.