Testing a Deploy Job Before It's Allowed to Run
The chicken-and-egg problem in every deploy pipeline, why a POC doesn't need branch protection yet, and the org-level secrets gotcha that can quietly change what your pipeline actually tests.
The deploy job only fires on a push to main. That's the whole point of it. It's also exactly what makes it impossible to test in the normal way.
You can't merge something to main to test it, because merging to main is the thing you're trying to verify works safely. That's a real chicken-and-egg problem, and every deploy pipeline runs into it once.
Build one job, verify it, then add the next
Before getting to that problem, one habit makes everything downstream easier: commit and push the build job by itself first, confirm it goes green, and only then add the deploy job on top of it.
Pushing both at once means a red check could be either one's fault, and now you're debugging two unproven things at the same time. This is the same reasoning behind committing source before wiring up CI at all: the smaller the unproven surface, the faster you find out what actually broke.
Two real ways to test a deploy job
The cleaner option is workflow_dispatch, the manual trigger button. Wire it up alongside your normal trigger, and you can run the deploy job on demand from the GitHub UI without needing a push to main at all.
The blunter option: temporarily change on: push: branches: [main] to your working branch name while you're still building the job out, then change it back before merging. It works, and for a solo POC it's genuinely fine.
Neither option is risk-free if your deploy job holds real credentials. Depending on how your secrets and environments are scoped, a job triggered from a feature branch may or may not have access to the same values it would on main. Know which one you're testing against before you trust a green check.
A POC doesn't need branch protection yet
If you're the only person working on a proof-of-concept, branch protection, required reviewers, and merge gates aren't protecting you from anyone. You're the only one who can approve anything, which means you're just adding steps between yourself and yourself.
This is exactly the stage-one judgment call from earlier in this series: those controls earn their place the moment a second person can touch the pipeline, not before. Setting them up for a solo project isn't caution, it's friction with no one on the other side of it.
The secret that isn't actually yours
That matters more than it sounds like it should. A deploy job can succeed in one environment and fail in another with the exact same workflow file, because one of them had an org-level secret quietly filling in a value the other one never had. The workflow file alone doesn't tell you the whole story of what a job actually has access to.
If a pipeline behaves differently than you expect and the YAML looks identical, checking organization-level secrets is worth doing before you assume the bug is in your code.
Branch patterns, and the negation that isn't there
The on: push: branches: list accepts patterns, not just exact names. branches: ['feature/**'] runs on any branch starting with feature/, the same way any other branch name is just a string you're allowed to pattern-match against.
What it doesn't support directly is negation, a trigger for "every branch except this one." Getting that requires a different layer: match everything with a wildcard, then use an if condition inside the job to skip execution when the branch is the one you actually want to exclude.
on:
push:
branches: ['**']
jobs:
build:
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latestIt's a small distinction, but it's the difference between a workflow that silently never has the option you assumed it had, and one that actually does what you meant.
The Essentials
- A deploy job that only triggers on main can't be tested by merging to main. That's the chicken-and-egg problem every real pipeline hits once.
workflow_dispatchor a temporary branch retarget are the two real ways around it. Know which secrets and environment values each option actually has access to before trusting a green result.- A solo POC doesn't need branch protection yet. Those controls exist to protect you from someone else, and there's no one else yet.
- Organization-level secrets can change what a workflow does without changing the workflow file. A pipeline that behaves differently across environments isn't always a code problem.
on: push: branches:has no built-in negation. Excluding one branch means matching everything and filtering with anifinside the job instead.
Further Reading and Watching
Keep reading