Back openDesk Edu for a sovereign, open-source education — every vote counts.
Vote nowSave products you love by clicking the heart icon.
Traditional CI/CD pipelines are evolving into AI/CD systems where agentic workflows handle testing, deployment, rollback, and optimization autonomously. This article explores the architecture, benefits, and implementation patterns for bringing intelligence to your delivery pipelines.
The workflow was almost perfect: it validated, transformed, optimized, and
then — the part everyone expects to be magic — pushed the optimized output
back to main. The collector's last step died with two cryptic lines:
remote: Permission to owner/repo.git denied to github-actions[bot].
fatal: unable to access 'https://github.com/...': The requested URL returned error: 403
Error: Invalid status code: 128
The optimization actually did its job — the check:palette and asset steps
ran fine. What failed was the final auto-commit push. The cause is
boring, predictable, and fixable in two lines.
GitHub injects a GITHUB_TOKEN into every workflow run. For newer
repositories the default this token grants is read for contents — enough
to check out the repo, not enough to push back. So any step that commits and
pushes falls over at the moment of truth with 403 / exit 128.
The telltale sign that you're hitting this and not an auth misconfiguration:
the 403 names github-actions[bot] specifically. It's not that your login
is wrong — it's that the token has no room to write.
At the top of the workflow, before any job, declare the permission you actually need:
permissions:
contents: write
That single block grants the workflow's GITHUB_TOKEN write access to repo
contents, which is exactly what an auto-commit needs. (Use the principle of
least privilege: give it contents: write only when a job genuinely commits
and pushes; workflows that only read should not carry it.)
The result is immediate and boring: the auto-commit pushes, the pipeline
completes, and the generated changes land on main as a real commit.
While diagnosing, the logs also showed two non-fatal warnings that pointed in the wrong direction if you don't know what they mean:
Unexpected inputs 'commit_if_no_changes', 'skip_check_run'
lint-staged could not find any staged files matching configured tasks.
commit_if_no_changes and skip_check_run are inputs the action
version you're using doesn't declare — harmless "unexpected input"
warnings, not the cause.lint-staged message is the action's pre-commit hook failing to find
staged files matching its tasks. It's a warning; the action proceeds.
It can make you chase a lint-staged config that isn't the problem.Neither causes the 403. Be suspicious of both but don't fix them first.
The clean diagnostic order:
github-actions[bot] — that pins it to token scope.permissions: contents: write at the workflow root.main is your proof.A self-sustaining artifact pipeline — optimize assets, push the result, let CI revalidate — is powerful. But it quietly depends on the token having write access, and the default no longer grants it. Two lines of YAML turn a failing auto-commit into the boring background machinery it was always meant to be.