Trying to do an ssh connect to github to download terraform modules in Jenkins . The terraform init below will error
steps {
container('deploy') {
sh "apt-get update && apt-get install ssh -y"
withCredentials([sshUserPrivateKey(credentialsId: 'github-deploy-key', keyFileVariable: 'IDENTITY_FILE')]) {
sh '''
git config core.sshCommand "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${IDENTITY_FILE}"
terraform init //fails here - terraform init references github modules
'''
}
}
}
Then in the jenkins build console log - I get a
..Could not download module "network" source code from "git#github.com:GithubOrg/my-repo.git?ref-c322334..."
Host key verification failed.
fatal: could not read from remote repository.
I would have thought setting 'StrictHostKeyChecking=no` would prevent the host key error.
I am able to run a terraform init locally with the same ssh keypair and it can connect to the Github repo with no problems and download the code. But in Jenkins in this container step it does not work. Any suggestions?
Should I be setting the ssh known_hosts file inside the container somehow ?
I ended up having to set the known_hosts file and use the sshagent plugin in jenkins .
container('deploy') {
sh "apt-get update && apt-get install ssh -y"
sshagent (credentials: ['github-deploy-key']) {
sh '''
mkdir -p ~/.ssh
ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
cd terraform
tfenv use 0.13.7
terraform init
'''
}
}
--
The public deploy key sits on the repo, and the private key is in the Jenkins credential manager.
I have the following CI/CD
build-job:
stage: build
script:
- echo "Hello, $GITLAB_USER_LOGIN!"
- ls -al
- mkdir django_app
- cd django_app
- git clone git#gitlab.com:xxxxxx/yyyyyy.git .
It says
$ git clone git#gitlab.com:xxxxx/yyyyy.git .
Cloning into '.'...
Host key verification failed.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Cleaning up project directory and file based variables
How to clone the repository
You need to add ssh key with access to gitlab.com:xxxxxx/yyyyyy.git to your container before you try to clone.
In my CI pipeline I am generating an artifact public/graph.png that visualises some aspect of my code. In a later step I want to commit that to the repo from within the CI pipeline. Here's the pertinent part of .gitlab-ci.yml:
commit-graph:
stage: pages
script:
- git config user.email "cipipeline#example.com"
- git config user.name "CI Pipeline"
- cd /group/project
- mv public/graph.png .
- git add graph.png
- git commit -m "committing graph.png [ci skip]"
- echo $CI_COMMIT_REF_NAME
- git push origin HEAD:$CI_COMMIT_REF_NAME
When the pipeline runs within gitlab it fails with:
$ git config user.email "cipipeline#dhgitlab.dunnhumby.co.uk"
$ git config user.name "CI Pipeline"
$ cd /group/project
$ mv public/graph.png .
$ git add graph.png
$ git commit -m "committing graph.png [ci skip]"
[detached HEAD 22a50d1] committing graph.png [ci skip]
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 graph.png
$ echo $CI_COMMIT_REF_NAME
jamiet/my-branch
$ git push origin HEAD:$CI_COMMIT_REF_NAME
fatal: unable to access 'https://gitlab-ci-token:xxxxxxxxxxxxxxxxxxxx#example.com/group/project/project.git/': server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
Not sure what I'm doing wrong and don't know enough about SSL to understand that error. Can anyone advise?
We are hosting gitlab ourselves by the way.
Nowadays there is a much cleaner way to solve this without using SSH but using a project scoped access token, also see this answer.
In the GitLab project create an project scoped access token so it is linked to the project, not to an individual. Next store this token as an GitLab CI/CD variable. You can now connect using the following:
push-back-to-remote:
script:
- git config user.email "my-email#email.com"
- git config user.name "ci-bot"
- git remote add gitlab_origin https://oauth2:$ACCESS_TOKEN#gitlab.com/path-to-project.git
- git add .
- git commit -m "push back from pipeline"
- git push gitlab_origin HEAD:main -o ci.skip # prevent triggering pipeline again
Some finger push-ups still required, but here's a less brittle way of pushing to the repository from its own CI, that I use in my daily work. It pushes to master directly from a detached head:
Generate an RSA key and add it as a Project Deploy Key with write access (the public part).
Put the private part into your CI/CD variables from inside of your project settings as SSH_PUSH_KEY. Make sure to set it as protected.
Add a CI_KNOWN_HOSTS variable, with the SSH fingerprint of your GitLab instance (remember that thing ssh asks you about the first time you try to connect to a host? That.).
Use ssh-keyscan <gitlab-host> to get it. It will look similar to this:
my.gitlab.instance.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEArlUMUmNj59PpoLyy4EsKbwhPUfXxuAzFN7dMKDXVvKMmN8344HqQV1tRx6fcmH+0BXK1JAP4f10V0VnYti3e1c5f9dhpl8pIqKLMJgdGDq3MLqjihL3bp5xm8nDsPTm5FoEPPYK1I3M2wr18pBB19evz64NHrK5R/HO5LyTrybVasFumt8cZoH6crnCFgfQWV1mHAG3j41Q0z4yxu6g8zBWESZcVVn90HxQH7+LDHx11122233344491MQGl5fZcKqVWsWQVEssaK87iBsWUxvsuoeVUrj4YRcmbi6F4+ZZZZZZZwwww3ZboWsSWxTk5ESR6WWHccBm8GQflXyY3ZQ==
Set up your job inside .gitlab-ci.yml as follows. Set stage and resource_group options appropriately - without the latter you might run into race conditions. Also, make sure to set only properly, as otherwise your CI might trigger itself:
"This CI job pushes to its own repo":
stage: my_push_stage
resource_group: this_option_comes_handy_when_pushing
only:
- triggers
before_script:
- mkdir ~/.ssh/
- echo "${CI_KNOWN_HOSTS}" > ~/.ssh/known_hosts
- echo "${SSH_PUSH_KEY}" > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- git config user.email "ci#example.com"
- git config user.name "CI"
- git remote remove ssh_origin || true # Local repo state may be cached
- git remote add ssh_origin "git#$CI_SERVER_HOST:$CI_PROJECT_PATH.git"
script:
- touch "xyz" # Make an edit
- git add "xyz"
- git commit -m "My CI commit"
- git push ssh_origin HEAD:master # ❗ this pushes to master,
# use $CI_COMMIT_REF_NAME if you want to push to current branch
- git tag MyCiTag # If you need to add a tag you can do that too
- git push --tags ssh_origin
TL;DR;
If you just want to make a release or version bump commits when stuff is merged to main, there are probably existing CLI tools that you can use in a much more simpler and well documented way.
(See Use the gitlab api for an example)
How to do it
The necessary steps:
commitingJob:
stage: some_stage
script:
# in order to commit we have to have a user set
# this would also make it easy to distinct the CI-made commits
- git config user.name "CI Pipeline"
- git config user.email "cipipeline#example.com"
# stage some changes
- git add src/*
# We can use `-o ci.skip`, but AFAIK it doesn't work for Merge Request pipelines, while having it inside the commit message works there as well
- git commit -m "A commit message [skip ci]"
# we're on a detached head but we can push the commits we made to the remote branch like so:
- git push HEAD:$CI_COMMIT_REF_NAME
One thing missing here is authenticating with the remote. It can be setup in a number of ways (ssh, token, api). Other answers discuss a few different options. My preference would be to use an ACCESS_TOKEN, see how and why bellow
Summary and critique on the available authentication options
Adding or copying an ssh key inside the CI steps
Compared to just using an access token, going for the ssh way seems like too much work, for the same result
generate an ssh key
save the public key as Project deploy token
save the private key as a Project CI variable
dedicate a few CI steps on
adding the private keys
adding known hosts
add/update the ssh remote
Overall it seems like something you'd do for a user and not for a pipeline
You have to add the private key as a Project Level CI variable - due to pattern restrictions the variable can't be masked. It can be added as a file, but then you'd have to chmod for proper permissions...
The positive thing I see here is the ssh key is restricted only to the projects you add it to as deploy token
The easiest option seems to be to use an ACCESS_TOKEN
Using a token to push commits is as easy as updating the push remote like this:
git remote set-url --push origin "https://$TOKEN_NAME:$ACCESS_TOKEN#gitlab.com/<project>.git"
TOKEN_NAME - the name you set for the token in gitlab (preferably pick a name without space characters)
ACCESS_TOKEN - this can be a personal access token (Free Tier) or a project access token (Premium Tier)
It would have to be stored as Project Level CI variable, and it can be masked.
I would just save a variable like CI_COMMITTER_USER_AND_TOKEN containing both <token_name>:<access_token> content
⚠ Warning about Personal Access Tokens
This is too broad permission to give to a CI Runner even if the runner should commit to multiple repositories, I'll prefer separate access tokens per project with only the minimum permissions needed
Keep in mind that if someone takes hold of your personal access token, they can do stuff (like committing in this case) on your behalf. Giving the write_repository permission means you can use the token to write to any repository you're account has access too.
CI_JOB_TOKEN
If you're wondering whether you can use the CI_JOB_TOKEN to push commits - you can't. You can only pull with that thing
(You can also use it to publish packages and images, but not push commits)
Why git remote set-url --push origin
We can add a separate remote for CI made commits, but keep in mind it might get cached, so if we just do
script:
- git remote add ci "https://$TOKEN_NAME:$ACCESS_TOKEN#gitlab.com/<project>.git"
the next time the pipeline runs we'll get an error from git remote add, because the remote we're trying to add is already added
set-url on the existing origin makes sure you use the latest url
To achieve the same with git remote add we'd have to first try to remove the ci remote and then add it back
script:
- git remote remove ci || true
- git remote add ci "https://$TOKEN_NAME:$ACCESS_TOKEN#gitlab.com/<project>.git"
Use the gitlab api to push changes
This works pretty much the same way as the ACCESS_TOKEN way, but instead of the write_repository the token has the api permission
If the reason to commit and push as part of CI is releasing a new version on merge to main then using CLI tools and a guide like this might be a better option than setting up the committing and pushing yourself: https://docs.gitlab.com/ee/ci/examples/semantic-release.html
The above guide setups a version bump, package updates, and release notes.
Note how this step instructs us to create an Access Token with api permission in order for the underlying CLIs to commit the changes: https://docs.gitlab.com/ee/ci/examples/semantic-release.html#set-up-cicd-variables
You can add the CI_SERVER_CLS_CA_FILE to sslCAInfo git config.
checkout alchemy:
stage: prepare
script:
- git config --global "http.${CI_SERVER_URL}.sslCAInfo" "$CI_SERVER_TLS_CA_FILE"
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}#${CI_SERVER_HOST}/sparklemuffin/alchemy.git
#Sjoerd's approach, in the comments, to export GIT_SSL_CAINFO instead, is a bit shorter.
export GIT_SSL_CAINFO=$CI_SERVER_TLS_CA_FILE
Gitlab creates CI_SERVER_TLS_CA_FILE and configures git to use it for initially cloning the repository. For some reason this configuration is no longer available later on.
I found this GitLab forum link helpful
As suggested by the user you need to generate SSH key, associate it with new GitLab user dedicated for this job and add key to the runner. Small drawback is you need to use swap origin in gitlab for original ssh source (instead of sandboxed one used inside the job) which leads to committer being changed to mentioned new account instead of person who triggered pipeline.
Source from link:
# for your information
whoami
printenv
# we need to extract the ssh/git URL as the runner uses a tokenized URL
export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | perl -pe 's#.*#(.+?(\:\d+)?)/#git#\1:#'`
# runner runs on a detached HEAD, create a temporary local branch for editing
git checkout -b ci_processing
git config --global user.name "My Runner"
git config --global user.email "runner#gitlab.example.org"
git remote set-url --push origin "${CI_PUSH_REPO}"
# make your changes
touch test.txt
# push changes
# always return true so that the build does not fail if there are no changes
git push origin ci_processing:${CI_COMMIT_REF_NAME} || true
Just with current version of GitLab you need to change source variable name as follows:
export CI_PUSH_REPO=`echo $CI_REPOSITORY_URL | perl -pe 's#.*#(.+?(\:\d+)?)/#git#\1:#'`
Instead of declaring CI_KNOWN_HOST, you can try get it realtime:
- 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
- ssh-keyscan -t rsa $CI_SERVER_HOST >> ~/.ssh/known_hosts
Solved it. Issuing git config --global http.sslverify "false" prior to the push solved that particular problem (it exposed another problem but that's for another thread :) )
I can commit from Gitlab-CI with a selected user with a minor change based on tsr's answer https://stackoverflow.com/a/57800614/5269825 :
# set remote URL to https://oauth2:<AccessToken>#server.com/project.git
CI_PUSH_REPO=`echo "$CI_REPOSITORY_URL $ACCESS_TOKEN_PARAM" | sed 's/^.*\(#.*\)\s\(.*\)/https:\/\/oauth2:\2\1/g'`
git config http.sslverify false
git remote set-url --push origin "${CI_PUSH_REPO}"
git config user.name "Token Owner"
git config user.email "tokenowner#email.com"
# runner runs on a detached HEAD, create a temporary local branch for editing
git checkout -b ci_processing
# make your changes
# push changes
# always return true so that the build does not fail if there are no changes
git push origin ci_processing:${CI_COMMIT_REF_NAME} || true
The ACCESS_TOKEN_PARAM must be configured at the project's CI/CD Variables configuration.
The idea of using Oauth2 and Access Token was taken from https://stackoverflow.com/a/52074198/5269825 and https://stackoverflow.com/a/52154378/5269825.
Also, pushing changes can trigger a new pipeline!
In my case deploy keys option was optimal (compared to personal tokens or CI token - only supports basic auth) with Gitlab Shell Runner. In case someone is struggling with pushing to from Gitlab CI, this can be done sharing the public key of the runner with the Gitlab server
This is a working example as of today
environment: k8s
gitlab: 13.x
gitlab runner: 13.x
goal of this job named convert:- Converts the excel files to json files and commits and updates the branch of the repo.
convert:
variables:
REPO: "gitlab.com/group/myproject.git" # example
BRANCH: "BRANCHNAME" # example
# recommended to store the following as project variables to hide secrets away from the gitlab ci file.
GITLAB_USER_ID: "gitlab_user" # example
CI_USERNAME: "gitlab_user" # example
CI_PUSH_TOKEN: "<api token from gitlab" # example
GITLAB_USER_EMAIL: "gitlab_user#company.com" # example
stage: convert
image:
name: python:3.7-buster
entrypoint: ["/bin/ash"]
before_script:
- pip3 install openpyxl
- ls -altr
script:
- echo 'converting excel to json'
- python excel2json.py
- git remote set-url origin https://${CI_USERNAME}:${CI_PUSH_TOKEN}#$REPO
- git config --global user.email '${GITLAB_USER_EMAIL}'
- git config --global user.name '${GITLAB_USER_ID}'
- git add -A && git commit -m 'added/updated json files'
- git push origin HEAD:$BRANCH
Note: CI_USERNAME == GITLAB_USER_ID. Both are same in my case.
None of these worked immediately for me but I merged them all together to come up with this:
- git config user.email "example#example.com"
- git config user.name "example"
- git remote remove dev || true
- git remote add dev https://example:$PROJECT_ACCESS_TOKEN#gitlab.com/demo/versioning-test.git
- git remote set-url --push origin "https://example:$PROJECT_ACCESS_TOKEN#gitlab.com/demo/versioning-test.git"
- git pull origin dev
- git checkout dev
- git reset --hard origin/dev
- git rm build_number.json || true
#grabs the build number from tags and pipes it into text file json formatted
- echo "`echo {'"build_number"':` `git describe --tags` `echo }`" | sed -e 's/\s\+/"/g' >> build_number.json
- git add build_number.json
- git commit -m "push back from pipeline [skip ci]"
- git push origin dev
My use case was that we wanted to bump to a version file and push that back into the repo.
Another way:
Create dedicated Gitlab account
Add CI/CD variable GIT_CICDUSER_PASSWORD containing it's password to the project inside the main account running the pipeline
Then a job can look like:
task_requiring_a_push:
stage: some-stage
variables:
GIT_STRATEGY: none
script:
- git config --global user.email "user#mail.com"
- git config --global user.name "CI/CD User"
- git clone https://<dedicated_gitlab_user_username>:$GIT_CICDUSER_PASSWORD#gitlab.com/$CI_PROJECT_PATH .
- git checkout $CI_COMMIT_REF_NAME
- # do something
- git add *
- git commit -m "message"
- git push --push-option=ci.skip origin $CI_COMMIT_REF_NAME
only:
- release-*
I'm trying to configure gitlab-runner for my project (baseProject) using shell executor. My project has two submodules: submoduleOne and submoduleTwo.
This is how my .gitmodules looks like:
[submodule "lib/submoduleOne"]
path = lib/submoduleOne
url = ../submoduleOne.git
[submodule "third_party/submoduleTwo"]
path = third_party/submoduleTwo
url = ../submoduleTwo.git
And this is how relevant part of my .gitlab-ci.yml looks like:
stages:
- preparation
clean:
stage: preparation
script:
- eval $(ssh-agent -s)
- ssh-add ~/.ssh/submoduleOne
- ssh-add -l
- git submodule update --init -- lib/submoduleOne
- ssh-add -D
- ssh-add ~/.ssh/submoduleTwo
- ssh-add -l
- git submodule update --init -- third_party/submoduleTwo
- ./setup_project.sh
Public keys ~/.ssh/submoduleTwo and ~/.ssh/submoduleOne are added to the respective projects in gitlab as "deploy keys" and the fingerprints match. Both projects seem to be configured in the same way.
Yet, the job fails and the output is:
Running with gitlab-runner 11.0.0 (5396d320)
on wawsrvbuild70 3295e1f6
Using Shell executor...
Running on wawsrvbuild70...
Fetching changes...
HEAD is now at 5e3be99 CI test
From https://gitlab01.mydomain.pl/Group/baseProject
5e3be99..0029318 p.czechows2/configure-gitlab-ci#1038 -> origin/p.czechows2/configure-gitlab-ci#1038
Checking out 00293180 as p.czechows2/configure-gitlab-ci#1038...
Skipping Git submodules setup
$ eval $(ssh-agent -s)
Agent pid 18755
$ ssh-add ~/.ssh/submoduleOne
Identity added: /home/gitlab-runner/.ssh/submoduleOne (/home/gitlab-runner/.ssh/submoduleOne)
$ ssh-add -l
4096 27:f5:e5:86:af:a7:7a:aa:52:03:b1:6d:05:72:56:29 /home/gitlab-runner/.ssh/submoduleOne (RSA)
$ git submodule update --init -- lib/submoduleOne
$ ssh-add -D
All identities removed.
$ ssh-add ~/.ssh/submoduleTwo
Identity added: /home/gitlab-runner/.ssh/submoduleTwo (/home/gitlab-runner/.ssh/submoduleTwo)
$ ssh-add -l
4096 89:aa:68:f9:88:72:4c:cf:8a:a3:c7:7e:34:92:91:6b /home/gitlab-runner/.ssh/submoduleTwo (RSA)
$ git submodule update --init -- third_party/submoduleTwo
Cloning into 'third_party/submoduleTwo'...
fatal: Authentication failed for 'https://gitlab-ci-token:yXkvnfXZadABF4FZWTSb#gitlab01.mydomain.pl/Group/submoduleTwo.git/'
Clone of 'https://gitlab-ci-token:yXkvnfXZadABF4FZWTSb#gitlab01.mydomain.pl/Group/submoduleTwo.git' into submodule path 'third_party/submoduleTwo' failed
ERROR: Job failed: exit status 1
This token yXkvnfXZadABF4FZWTSb is I think the token I gave to gitlab-runner while configuring it for the baseProject. But I'm not sure where to check this.
Also, changing the order of submodules initialization won't help: the problem is still with submoduleTwo.
So my question is: why wouldn't gitlab-runner use the private key stored in ssh-agent for cloning this repository? or maybe I've made a mistake somewhere? Suggestions for how to configure submodules initialization in gitlab-runner differently are also welcome.
I am using gitlab CI runner to test my code and generating some files. I just want to push the generated files to gitlab repository via CI runner. Is there any way to do that ?
I have resolved this issue by doing this:
Note: If you want to git push to a non protected branch do not set the runner variable as protected
Generate new gitlab access token with api scope: User Settings > Access Tokens
Add a protected CI variable into your project settings with the new token: Your project > Settings > Secret variable using variable name CI_PUSH_TOKEN
Add another protected CI variable with your username using variable name CI_USERNAME
Then you can use this token instead of the default in you gitlab-ci script. for example:
before_script:
- git remote set-url origin https://${CI_USERNAME}:${CI_PUSH_TOKEN}#gitlab.com/${CI_PROJECT_NAME}.git
- git config --global user.email '${GITLAB_USER_EMAIL}'
- git config --global user.name '${GITLAB_USER_ID}'
...
- git checkout -B branch
- # do the file changes here
- git commit -m '[skip ci] commit from CI runner'
- git push --follow-tags origin branch
Generated a SSH Key in gitlab
--> Profile Settings --> SSH Keys --> Generate It
After generating the SSH Key store that in the gitlab variables named SSH
--> Project Settings --> Variables --> Add Variable
In the .gitlab-ci.yml add the below lines.
before_script:
- mkdir -p ~/.ssh
- echo "$SSH" | tr -d '\r' > ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
- ssh-keyscan -H 'Git_Domain' >> ~/.ssh/known_hosts
After that pushed the files to the repository using this below js code.
var child_process = require("child_process");
child_process.execSync("git checkout -B 'Your_Branch'");
child_process.execSync("git remote set-url origin Your_Repository_Git_Url");
child_process.execSync("git config --global user.email 'Your_Email_ID'");
child_process.execSync("git config --global user.name 'Your_User_Name'");
for (var i=0;i<filesToBeAdded.length;i++) {
child_process.execSync("git add "+filesToBeAdded[i]);
}
var ciLog = child_process.execSync("git commit -m '[skip ci]Automated commit for CI'");
var pushLog = child_process.execSync("git push origin Your_Branch");
[skip ci] is most important in commit message. Otherwise it will start a infinity loop of CI process.
You could use of course SSH keys but you could also provide user and password (user with write access) as secret variables and use them.
Example:
before_script:
- git remote set-url origin https://$GIT_CI_USER:$GIT_CI_PASS#gitlab.com/$CI_PROJECT_PATH.git
- git config --global user.email 'myuser#mydomain.com'
- git config --global user.name 'MyUser'
You have to define GIT_CI_USER and GIT_CI_PASS as secret variables (you could always create dedicated user for this purpose).
With this configuration you could normally work with git. I'm using this approach to push the tags after the release (with Axion Release Gradle Pluing - http://axion-release-plugin.readthedocs.io/en/latest/index.html)
Example release job:
release:
stage: release
script:
- git branch
- gradle release -Prelease.disableChecks -Prelease.pushTagsOnly
- git push --tags
only:
- master
Another solution using Gitlab API to commit back a file .terraform.lock.hcl in terraform/ directory on $CI_COMMIT_BRANCH with [skip ci] :
script:
- 'STATUS=$(curl -Ss --head --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/files/terraform%2F%2Eterraform%2Elock%2Ehcl?ref=$CI_COMMIT_BRANCH" | grep "HTTP/1.1" | cut -d " " -f2)'
- if [[ $STATUS == "404" ]]; then ACTION="create"; else ACTION="update"; fi
- 'curl --request POST --form "branch=$CI_COMMIT_BRANCH" --form "commit_message=[skip ci] terraform.lock.hcl from pipeline" --form "actions[][action]=$ACTION" --form "actions[][file_path]=terraform/.terraform.lock.hcl" --form "actions[][content]=<.terraform.lock.hcl" --header "JOB-TOKEN: $CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits"'
The Feature you are looking for is called Artifacts. Artifacts are files which are attached to a build when they are successful.
To enable an Artifact put this in your .gitlab-ci.yml:
artifacts:
paths:
- dir/
- singlefile
This will upload the dir directory and the file singlefile back to GitLab.