homelab
Rebuilding my deployment pipeline
How I rebuilt the blog deployment flow around development deploys, parent repository builds, build hashes, and faster rollback.
I have rebuilt the deployment pipeline for this blog. The old setup proved that I could build and publish the site from Forgejo, but I wanted a cleaner flow for day-to-day development, releases, and rollback.
The new system separates those jobs more clearly. Development changes can move quickly into a local test environment, while production builds are created from a deliberate trigger and tied to a specific commit hash.
Development deploys
The development branch now has an automatic deployment path. When I push to development, Forgejo runs the development workflow, builds the Astro site, and deploys the result to a locally hosted development environment.
That gives me a useful feedback loop. I can push a change, let the runner build it in the same kind of environment the site expects, and then inspect the result outside my local machine.
It also keeps development separate from production. The development environment can move often, because it is there to catch layout issues, content mistakes, workflow problems, and build failures before anything becomes a release.
Triggered production builds
Production now starts from a more intentional point. Once the latest changes are merged into main, I use a trigger workflow instead of letting every merge immediately publish the site.
That workflow dispatches a pipeline in a parent repository. The trigger passes the branch, an optional build name, and the commit hash that should be built. If I leave the hash empty, the workflow can use the current head, but the important part is that the release path can be tied to a specific source revision.
The parent pipeline then takes that hash, checks out the right source state, creates a fresh build, and pushes the output to the build repository.
Build hashes and rollback
The build repository is now part of the deployment model. Instead of thinking only in terms of “deploy the latest source”, I can deploy a specific build repository hash.
That matters for rollback. If a newer build has a problem, I do not need to rebuild the whole project or guess which source state produced the previous working site. I can point the deployment pipeline at a known build hash and move back quickly.
It also makes release testing easier. A build can exist as a concrete artifact before it becomes the live version. That gives the pipeline a better boundary between source changes, build output, and deployment.
What still needs work
The next major step is Docker images. Right now the system is already split into development deploys, triggered builds, build storage, and deploy-by-hash, but Docker should make the process cleaner.
Using images would let me standardize the build and deployment environment further, reduce setup inside each workflow, and make the pipeline easier to move or repeat. It should also help performance once the repeated install and tooling steps are trimmed down.
That is the last big piece before this deployment system feels complete. The current version already gives me more control than the first pipeline: development is automatic, production is deliberate, builds are addressable, and rollback is no longer a special case.