Ask
27
@runner_rauf ·

How does a pipeline job push a commit back to its own repository without causing chaos?

I want a job to commit something back — a regenerated file, a version bump, updated documentation. Inside the job, git is authenticated for reading but not for pushing, and my first attempt at adding a token worked and then triggered the pipeline again, which committed again.

So I have two problems: getting the credential in safely, and not creating a loop.

What does a correct version of this look like?

4 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @runner_rauf · 2d ago

    Both problems are well known and both have standard answers. Take the loop first, because it is the one that will page somebody.

    Break the loop. Two mechanisms, and use both:

    • Skip on the commit message. Most CI systems honour a marker in the commit message that suppresses a pipeline. Put it in the message your job creates. This is the belt.
    • Guard in the pipeline rules. A condition so the job cannot run on a commit authored by the automation, or only runs on the events you intend. This is the braces.

    Relying only on the message marker is how people end up with a loop when somebody changes the message template.

    And make the commit idempotent: if nothing changed, do not commit. A job that commits an identical file every run creates noise and, combined with any gap in the loop guard, creates the loop.

    30
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @reverse_proxy_reyhan · 2d ago

    The mechanics that trip people up once the credential exists:

    The checkout is detached and shallow. CI checks out a commit, not a branch, so committing puts you on no branch and pushing fails confusingly. Check out the branch explicitly first, and fetch enough history.

    Identity is unset. Set a name and email for the automation. Use an address that makes it obvious this was a machine.

    The remote uses the read-only credential. Setting the token in a variable is not enough; the remote URL or the credential helper has to actually use it.

    And write the whole thing so a failure to push fails the job loudly. A silently swallowed push error means the generated file is correct in the pipeline and never lands, which takes a surprisingly long time to notice.

    22
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @vram_vural · 2d ago

    Worth asking whether the commit needs to happen at all, because for a good share of these cases it does not.

    Generated files that are only consumed by the build can be artefacts rather than commits. Documentation can be published from the build to wherever it is served, without going back into the repository. A version number can be derived from a tag at build time rather than written into a file.

    Every one of those removes the credential, the loop and the noisy history at once. Committing back is occasionally the right answer and it is worth being sure it is one of those cases first.

    15
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @runner_rauf · 3d ago

    The credential. The read-only token the job gets by default is deliberate — a build should not be able to rewrite its own source, because anybody who can change the pipeline could then rewrite history or push to protected branches.

    So you are widening a boundary on purpose, and the way to do it safely:

    • Use a project-scoped deploy key or token with write access to this repository only. Not a personal access token belonging to a human, which is the shortcut everybody takes and which means the automation acts as that person forever, including after they leave.
    • Do not let it push to protected branches. If the change needs to land on the main branch, open a merge request instead of pushing. That keeps review in the loop and is a much smaller privilege.
    • Store it as a protected, masked variable, available only to runs on protected refs.

    Opening a merge request rather than pushing directly solves the loop problem as a side effect, which is a good sign it is the right shape.

    26
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report