DEV Community

Jiahui Miao
Jiahui Miao

Posted on

Your Deploy Can Be Blocked by Who Wrote the Commit, Not What It Contains

This week, identical code deployed or did not deploy depending on the name in the author field. My production platform was not judging the diff. It was judging identity: whether the GitHub account attached to the head commit was recognized as belonging to the team that owned the project. The code was fine. The tests were fine. The binding between two accounts was wrong, and that invisible layer sat in front of the build, vetoing it before a single line compiled.

Here is how we found out, because guessing would have taken weeks. We ran the experiment a scientist would run: same content, different authors, controlled one variable at a time. Commits authored by me, a real human, were blocked. A commit with identical content authored by an automated app identity went through. Then the sharper test: a merge whose head commit carried the app identity, with my human-authored commit as its second parent. It deployed. The gate, it turned out, reads only the commit being deployed — the head, the merge — and does not prosecute its ancestors. The pipeline had an immigration officer, and he only checks the last passport stamp.

The root cause, when we finally dragged it into the light, was embarrassingly administrative. My GitHub login was linked to the wrong account on the platform — an older account of mine, attached to a different team. The projects lived under the owner account. So every human-authored deploy arrived, as far as the platform was concerned, as a stranger asking to ship to someone else's team. The fix was not code, not config, not an upgrade, and not money. It was relinking the login to the correct account. The blocked deployments were then redeployed and went ready within minutes, and human-authored commits deploy normally again.

Every pipeline has an identity layer. Most teams never draw it.

We draw architecture diagrams with boxes for source, build, test, and deploy. Nobody draws the box that asks: is this identity allowed to deploy to this team? Yet that box exists in every hosted platform, and it fails differently from every other box. A code failure gives you a stack trace. A config failure gives you a log. An identity failure gives you a sentence about access that looks, at a glance, like a permissions errand — easy to misread as "upgrade your plan" or "add a seat," both of which would have cost money and fixed nothing. We almost paid to solve an account-linking problem.

There is a second lesson in the probe itself. When a system blocks you opaquely, do not argue with the error message. Bisect the identity space the way you would bisect a code regression: one variable, both outcomes, written down. Author A versus author B. Head commit versus parent. Linked account versus owner account. Three small experiments replaced days of folklore, including our own confidently wrong earlier theories about who was and was not allowed through — theories that were true on Tuesday and false by Thursday, because a binding changed underneath them and nothing announced it.

The rule for anyone who ships alone

A one-person company has no platform team to absorb this. So the discipline has to be procedural. First: for every production project, write down which identity the platform thinks you are — which login is linked to which account and which team — and re-verify it after any rename, re-login, or account change, because bindings rot silently. Second: when a deploy is blocked, test identity before you test code, and before you test your wallet. Third: never accept a blocked deploy at face value from a dashboard color. Redeploy, read the exact reason, and keep the probe results — the next binding failure will not announce itself either.

I used to think deployment was a property of my code: if it builds and the tests pass, it ships. It is not. Deployment is a property of a relationship between identities, and code merely gets a vote. Check who the platform believes you are, or one day your best commit will go nowhere — correctly built, fully tested, and stopped at the door for carrying the wrong name.

— Jiahui Miao, founder of vertciti, building a personal AI operating system for one.

Top comments (1)

Collapse
 
launchgatecheck profile image
Launch Gate •

The head-only finding deserves to be underlined twice, because it cuts in both directions. The same shallowness that blocked you - the gate reads the deploy's head commit and never prosecutes ancestors - is also a smuggling route: a merge with an app-authored head and a stranger's branch as its second parent carries the stranger's code through the same door that stopped your own. Your probe series mapped the exploit while diagnosing the outage. If the policy is "team members deploy", a head-author check implements a different policy - "the last passport stamp belongs to a member" - and the two diverge exactly at merges.

The other transferable piece is that identity bindings are state with no anchor. Code and config fail loudly because something evaluates them every run; the login-to-account binding is evaluated only when it vetoes something, so it rots silently until it does. Your re-verify-after-rename rule is the manual version of what the pipeline could assert itself: one cheap check at deploy time that prints which identity the platform believes you are, next to the diff it is about to ship. The three experiments you ran by hand would then be the first lines of every blocked-deploy log, instead of a diagnosis you have to rediscover under pressure.