Code in a job
Clone a GitHub or GitLab repository in a job with plain git, through the git credential helper and a connector of the owner.
Last updated
On this page
Description and operation
General
A pipeline has no repository of its own. A job gets code the same way that you do: a step runs git clone. A job that asks for permissions.git: read gets a short-lived, read-only credential for GitHub and GitLab. Kloudlite does not record which repositories a job reads. This page holds every rule about code in a job.
To do these tasks with an AI agent, see Agentic workflows – General.
How it works
Each time git needs a credential for an HTTPS remote, it runs the Kloudlite git credential helper. The helper sends the host and the path of the repository to Kloudlite. Kloudlite makes a read-only credential from a connector of the pipeline owner, and git uses it for that one command.
The job asks for git access with
"permissions": { "git": "read" }.A step runs
git clone https://github.com/acme/payments, orgit fetchin a clone.The step starts in the home directory, so the files are in
~/payments. A later step reads them with"cwd": "payments".
A job without git: read gets no credential. A public repository needs no credential, so a job clones it without git: read.
What a credential reads
| Host | Connector that answers | Credential | Life |
|---|---|---|---|
github.com | The GitHub connector whose account is the first part of the path, acme in acme/payments. | A token with read access to the contents of every repository that the GitHub App is installed on. | 1 hour. |
gitlab.com | The GitLab connector that picked the project. See GitLab. | A read-only deploy token on that one project. | 1 hour at most, or until the job token ends if that is earlier. |
A pipeline of a team uses the connectors of the team. It never uses the connector of a member. A personal pipeline uses your own connectors.
A job with git: read can read every repository that the GitHub App is installed on, a webhook run included. The caller of a webhook controls webhook.body. Do not clone a URL that comes from webhook.body. Install the app only on the repositories that pipelines need.
Rules
- HTTPS only. A
[email protected]:orssh://URL gets no credential. - Read only. A
git pushwith the credential fails. - Only
github.comandgitlab.com. For another host, see Other git hosts. - A URL that holds a user name, such as
https://[email protected]/acme/payments, gets no credential. Git uses the credential of the URL. - A credential is given only while that job is running. A request after the job or the run ends gets none. A credential that was already given keeps working until it expires, up to 1 hour. Nothing revokes it.
- A job token makes at most 60 credential requests in one minute. See Limits.
- The platform sets
GIT_CONFIG_COUNTand theGIT_CONFIG_KEY_*andGIT_CONFIG_VALUE_*variables. A job or stepenvthat setsGIT_CONFIG_COUNTreplaces the credential helper. - The platform sets
GIT_TERMINAL_PROMPT=0, so a clone with no credential fails at once and does not wait for a password.
When the helper gets no credential, it writes kl git-credential: and the reason to the log of the step. Git then fails the command.
Git in the job
The helper needs git 2.31 or later. A job with no runtime gets git from the platform. A job with packages must list git. A job with image must use an image that contains git 2.31 or later.
Other git hosts
Kloudlite makes no credential for other hosts, such as Bitbucket or your own GitLab. Use a personal access token of that host instead. Keep the token in a secret, and put it in the clone URL. The user name in the URL depends on the host.
A token that you paste is static. Kloudlite cannot make it read-only or short-lived, so the job can do what the token permits. A log line that holds the token shows *** in its place. Git keeps the URL, and the token in it, in the .git/config of the clone.
Tasks
Clone a repository in a job
Reason for the task: Run the tests or the scripts of a private GitHub or GitLab repository in a job.
Job set-up
- Access: you. For a team, an admin.
- Conditions: a connector of the owner covers the repository
acme/payments. See Connectors. - References: Pipeline definition – jobs.
Procedure
Add
"permissions": { "git": "read" }to the job, and add agit clonestep before the steps that use the code.{ "name": "payments-tests", "jobs": { "test": { "packages": ["git", "nodejs"], "permissions": { "git": "read" }, "steps": [ { "name": "clone", "run": "git clone https://github.com/acme/payments" }, { "name": "test", "run": "npm ci && npm test", "cwd": "payments" } ] } }}Use
https://gitlab.com/acme/payments.gitas the URL for a GitLab project.Create the pipeline from the file, and start a run. See Start a run and follow it.
Close-out
- Read the log of
test. Make sure that the stepcloneshowsCloning into 'payments'and nokl git-credential:line. - Make sure that the run ends in
success.
Choose the branch at the start of a run
Reason for the task: Run the same pipeline on another branch, without a new version.
Job set-up
- Access: you. For a team, an admin to change the definition, and an active member to start the run.
- Conditions: you have the definition of task 001.
- References: Inputs.
Procedure
Add the input
branch. Put it in the stepenv, and read it in the script as"$BRANCH".{ "name": "payments-tests", "inputs": { "branch": { "default": "main" } }, "jobs": { "test": { "packages": ["git", "nodejs"], "permissions": { "git": "read" }, "steps": [ { "name": "clone", "run": "git clone --branch \"$BRANCH\" https://github.com/acme/payments", "env": { "BRANCH": "${{ inputs.branch }}" } }, { "name": "test", "run": "npm ci && npm test", "cwd": "payments" } ] } }}Send the definition as the next version. See Save a new version.
Start a run with the branch
fix-rounding.run = kl.pipelines.run(owner="acme", pipeline="payments-tests", inputs={"branch": "fix-rounding"})print(run.wait())const run = await kl.pipelines.run({ owner: "acme", pipeline: "payments-tests", inputs: { branch: "fix-rounding" } });console.log(await run.wait());run, err := kl.Pipelines.Run(kloudlite.RunPipeline{Owner: "acme", Pipeline: "payments-tests", Inputs: map[string]string{"branch": "fix-rounding"}})if err != nil { log.Fatal(err)}state, err := run.Wait(kloudlite.WaitRun{})if err != nil { log.Fatal(err)}fmt.Println(state)run = kl.pipelines.run(owner: "acme", pipeline: "payments-tests", inputs: { "branch" => "fix-rounding" })puts run.waitvar run = kl.pipelines().run(new Kloudlite.RunPipeline().owner("acme").pipeline("payments-tests").input("branch", "fix-rounding"));System.out.println(run.waitFor());RUN=$(kloudlite pipelines run acme/payments-tests --input branch=fix-rounding --json | jq -r .id)kloudlite pipelines wait-run acme payments-tests "$RUN"
Close-out
- Read the log of the step
clone. Make sure that it cloned the branchfix-rounding.
Clone from another git host
Reason for the task: Get code from a host that Kloudlite makes no credential for, such as Bitbucket or your own GitLab.
Job set-up
- Access: you. For a team, an admin.
- Conditions: you have a read-only personal access token of the host.
- References: Secrets, Other git hosts.
Give the token read access to the repositories that the job needs, and nothing more. The job can do what the token permits.
Procedure
Set the token as the secret
GIT_HOST_TOKENof the owner. See Secrets.Add the secret to the job, and put it in the clone URL.
{ "name": "payments-mirror", "jobs": { "test": { "secrets": ["GIT_HOST_TOKEN"], "steps": [ { "name": "clone", "run": "git clone \"https://oauth2:[email protected]/acme/payments.git\"" } ] } }}Create the pipeline from the file, and start a run. See Start a run and follow it.
Close-out
- Read the log of the step
clone. Make sure that it showsCloning into 'payments'and no token.
Troubleshooting
| Symptom | Possible cause | Corrective action |
|---|---|---|
fatal: could not read Username for 'https://github.com': terminal prompts disabled | The job has no permissions.git: read, or the URL is not on github.com or gitlab.com. | Add "permissions": { "git": "read" } to the job. For another host, see task 003. |
kl git-credential: no git credential is available here | The job has no permissions.git: read. | Add "permissions": { "git": "read" } to the job. |
kl git-credential: no git connector of acme covers github.com/acme/payments | No connected connector of the owner has the account acme, or no GitLab connector picked the project. | Connect the account, or pick the project. See Connectors. |
remote: Repository not found. from github.com | The GitHub App is not installed on that repository. | Add the repository to the installation in the settings of the GitHub account. |
kl git-credential: path is not a repository path | The URL has more than owner/name after github.com, or has a character that a repository name cannot have. | Use the URL https://github.com/OWNER/NAME. |
kl git-credential: too many git credential requests; retry in a minute | The job made more than 60 git requests in one minute. | Clone once, and run later commands in the clone. |
kl git-credential: the provider refused the credential | The GitLab account lost the Maintainer role on the project. | Give the account the Maintainer role, or pick the project from an account that has it. |
kl git-credential: connector NAME is expired | The sign-in of the GitLab connector stopped working. | Select Reconnect for the connector. See Connectors. |
kl git-credential: GitHub is not configured | This region has no GitHub App set up. | Ask a superadmin to set up the GitHub App. |
The log of a step shows git: not found | The job lists packages without git, or its image has no git. | Add git to packages, or use an image with git. |
fatal: could not read Username with git older than 2.31 | Git older than 2.31 does not read GIT_CONFIG_COUNT. | Use an image with git 2.31 or later. |