Skip to content

Environment variables and subprocess behaviour

Which environment variables does rtb-forge set?

Variable Set on Value Why
RTB_VCS_GIT_TOKEN the git subprocess for authenticated clone, fetch, push the resolved secret Carries the password to the inline credential helper without putting it in argv
GIT_TERMINAL_PROMPT the git subprocess for clone, fetch, push 0 Makes an auth failure exit non-zero immediately instead of blocking on a prompt

Both are set on the child process only. Neither is read from or written to the parent process environment.

The name is RTB_VCS_GIT_TOKEN, not RTB_FORGE_GIT_TOKEN

The crate was renamed from rtb-vcs to rtb-forge at extraction from the rust-tool-base monorepo. The variable name was deliberately left alone, because it is part of the runtime contract with anything that inspects the subprocess environment. Do not expect an RTB_FORGE_-prefixed alias; there is none.

You do not set this variable yourself. It is written by rtb-forge onto the child process. Where your token comes from is decided by the CredentialRef you attach to the options struct — see Authenticate git operations.

GIT_TERMINAL_PROMPT is not set for checkout or commit

Only the three network operations set it. Repo::commit and Repo::checkout inherit the parent environment unchanged, so if something in that environment causes git to prompt, those calls can block. In a service, set GIT_TERMINAL_PROMPT=0 process-wide.

What exactly does the credential helper do?

Authenticated operations pass this to git as -c credential.helper=<value>:

!f() { echo username=x-access-token; echo password=$RTB_VCS_GIT_TOKEN; }; f

The snippet contains no secret — it reads one from the environment at the moment git asks. Three properties follow:

  • The secret never appears in argv, so it is not visible in ps output.
  • The secret is never written to a temporary file or to ~/.git-credentials.
  • The helper is scoped to the single invocation via -c; it does not modify any repository or global git config.

The username is hard-coded to x-access-token. That is GitHub's personal-access-token convention, and GitLab and Gitea accept it for token-based auth too. There is no configuration hook to change it. A forge that requires a real username with a token cannot be authenticated through Repo::clone / fetch / push; wrap the operation yourself.

Which git commands are run?

Exactly these, always with the repository directory (Repo::path()) as the working directory, except clone which takes the destination as an argument:

Method Command
clone (anonymous) none — pure gix
clone (authenticated) git -c credential.helper=<helper> clone -- <url> <dst>
fetch (anonymous) git fetch <remote>
fetch (authenticated) git -c credential.helper=<helper> fetch <remote>
checkout git checkout [--force] <revspec>
commit git add -- <paths…>, then git commit -m <message>, then git rev-parse HEAD
push (anonymous) git push <remote> <refspec>
push (authenticated) git -c credential.helper=<helper> push <remote> <refspec>

The -- separators on clone and add stop a URL or path beginning with - being read as a flag.

Nothing runs through a shell — every command is spawned directly with std::process::Command, so shell metacharacters in a URL, path, remote name or refspec are not interpreted. The credential-helper string is a shell snippet, but it is git that evaluates it, not rtb-forge.

stdout is captured and discarded except for git rev-parse HEAD, whose output becomes the commit OID. stderr is captured, trimmed, and placed in the cause field of the corresponding RepoError. A failing git command's stderr can therefore end up in your logs — it will not contain the token, because the token is only ever in the environment, but it may contain a repository URL.

Which HTTP headers do the release backends send?

Every REST backend builds its reqwest client the same way:

Setting Value
https_only true
User-Agent rtb-forge/<crate version> — for example rtb-forge/0.7.1
timeout timeout_seconds seconds, or unset when it is 0

Per-request headers:

Backend Auth header Other
GitHub Authorization: Bearer <token> Accept: application/vnd.github+json, X-GitHub-Api-Version: 2022-11-28; Accept: application/octet-stream on downloads
GitLab PRIVATE-TOKEN: <token> Accept: application/json
Gitea / Codeberg Authorization: token <token> Accept: application/json
Bitbucket HTTP Basic, username + token Accept: application/json
Direct Authorization: Bearer <token>

The auth header is only added when a token was passed to the factory (and, for Bitbucket, only when username is also set). The private config key does not affect this.

Is plain HTTP ever possible?

Not from configuration. Every parameter struct carries an allow_insecure_base_url field, but it is #[serde(skip)], so no config file — YAML, TOML, environment overlay — can set it. It exists so the crate's own tests can point a provider at a local wiremock or testcontainer, and it does two things when set in Rust code: builds the client without https_only, and constructs URLs with the http:// scheme.

The GitHub backend additionally refuses any host that literally begins http://, regardless of the flag.

Does anything read the ambient environment?

The release-provider slice reads nothing — no proxy variables of its own, no token discovery, no config file lookup. reqwest applies its own defaults, which include honouring the system proxy environment.

The git slice reads the environment only through the tools it invokes: gix and git both resolve user.name, user.email, init.defaultBranch, proxy settings and everything else from git's normal configuration cascade. Credential resolution is delegated to rtb-credentials, whose CredentialRef may name environment variables to read — that is your configuration, not this crate's.