Given the following very simple .gitlab-ci.yml pipeline:
---
variables:
KEYCLOAK_VERSION: 20.0.1 # this should be populated from reading a file from the repo...
stages:
- test
build:
stage: test
script:
- echo "$KEYCLOAK_VERSION"
As you might see, this simply outputs the value of KEYCLOAK_VERSION defined in the variables section.
Now, the Git repository contains a env.properties file with KEYCLOAK_VERSION=20.0.1 as content. How would I read the variable from that file and use it in the GitLab pipeline?
The documentation mentions import but this seems to be using YAML files.
To read variables from a file you can use the source or . command.
script:
- source env.properties
- echo $KEYCLOAK_VERSION
Attention:
One reason why you might not want to do it this way is because whatever is in env.properties will be run in your shell, such as rm -rf /, which could be very dangerous.
Maybe you can take a look here for some other solutions.
Related
I have a simple pipeline with one job to test bash scripts. The pipeline as follow:
image: alpine/git
stages:
- test_branching
test_branch:
stage: test_branching
before_script:
- mkdir -p .common
- wget https://x.x.x.x/branching.sh > .common/test.sh && chmod +x .common/test.sh
- source .common/test.sh
script:
- test_pipe
- echo "app version is ${app_version}"
The bash script as follow:
#!/bin/sh
function test_pipe () {
app_version="1.0.0.0-SNAPSHOT"
}
The problem is that the pipeline for whatever reason does not recognize the function inside the script. The logs are:
...
$ test_pipe
/scripts-1050-417479/step_script: eval: line 180: test_pipe: not found
Does anybody know what happend with this?? I miss a lot Jenkins shared libraries, gitlab does not have it, also gitlab does not have the function to include scripts inside yml files.
I dont want to use multiproject pipeline, I need to do it at this way. This is only an example of a more complicated pipeline logic.
Thanks in advance
As the documentation states before_script is just concatenated together with script and run on a single shell. The script you are downloading does not define test_pipe.
... gitlab does not have the function to include scripts inside yml
files.
It does, just use the YAML multiline literal syntax with |, e.g.:
script:
- |
echo "this"
echo "is"
echo "an \
example"
I have a gitlab yaml file for running certain jobs. In the variables part, I have declared certain variables with values and when I try to use it in another variable formation, it is actually generating but not fetching in the later part of job execution.
Code tried is as below:
variables:
env: "prod"
user: "test"
region: "us-east"
var1: '$env-$user-$region'
As suggested in one forum to include var1 formation in before_script script part. I tried it, but it was also not returning the var1 value correctly.
Any help will be appreciated.
At the bottom of this section of the official documentation, they describe using variables within variables:
You can use variables to help define other variables. Use $$ to ignore a variable name inside another variable:
variables:
FLAGS: '-al'
LS_CMD: 'ls $FLAGS $$TMP_DIR'
script:
- 'eval $LS_CMD' # Executes 'ls -al $TMP_DIR'
I was able to follow this pattern, and additionally I was combining variables in the script: step with a command such as:
script:
- APP_NAME=$APP_NAME-$VERSION
I am converting my project from Jenkins to GitLab CI. There is a .sh file which I am executing from .gitlab-ci.yml file where I am extracting the version from the project file using following statement:
VERSION=$(grep -oPm1 "(?<=)[^<]+" /Service.csproj
I am getting the project version and this is working fine.
How can I run the above statement in .gitlab-ci.yml file and assign the version value to a variable?
I tried running statement but I am getting error like invalid option "P"
I use in my example the sed command
stages:
- test
test:
stage: test
script:
- VERSION=$(sed -n "s/<Version>\(.*\)<\/Version>/\1/p" Service.csproj)
- echo $VERSION
Somehow above grep didn't work for me. Below works for me.
$VERSION=[regex]::match((Get-Content .\AssemblyFileVersion.cs), "AssemblyFileVersion\(`"(.*)`"\)").Groups[1].Value'
You need to execute the command in a script block, so your gitlab-ci.yml could look like this:
stages:
- test
test:
stage: test
script:
- VERSION=$(grep -oPm1 "(?<=)[^<]+" Service.csproj | xargs)
- echo $VERSION
I have a folder structure like
foo/bar/lorem/a.txt
foo/bar/lorem/b.txt
foo/bar/lorem/c.ext
foo/bar/ipsum/p.txt
foo/bar/ipsum/q.ext
In GitLab CI's yml artifacts I want to include everything in foo/bar, exclude *.txt but include b.txt
The GitLab CI reference for artifacts says that:
Wildcards can be used that follow the glob patterns and golang's filepath.Match.
Try 1:
job1:
artifacts:
paths:
- foo/bar/
- foo/bar/lorem/b.txt
exclude:
- foo/bar/**/*.txt
Try 2:
job1:
artifacts:
paths:
- foo/bar/
exclude:
- foo/bar/**/!(b).txt
Expected output:
foo/bar/lorem/b.txt
foo/bar/lorem/c.ext
foo/bar/ipsum/q.ext
What paths and exclude combination do I use to achieve this?
You can do this:
job1:
artifacts:
paths:
- foo/bar/lorem/b.txt
- foo/bar/*/*.ext
Although the previous answer is good and correct, it relies on a particular case where there are only two types of files. Having a whole hierarchy with multiple file types, that could possibly be different for each job, makes it very hard to apply to other cases.
Here is an answer, a bit more difficult to set up, but that covers more cases, if someone else is looking for an answer:
At the end of your script section, delete the files you don't want. For example:
job1:
script:
- # Perform the actions you already do
- mkdir keep # Create a place to temporarly keep your files
- mv foo/bar/lorem/b.txt keep/ # Move the file to the safe place
- rm foo/bar/*.txt # Delete all files you want to delete
- mv keep/b.txt foo/bar/lorem/ # Put back the file you want to keep
artifacts:
paths:
- foo/bar/ # Save everything, the *.txt are already removed
Note for the anxious: CI jobs are run in a container (at least it's the default behavious), and the files you work on are a copy of your project. You can delete whatever you want, nothing will be lost outside the container.
I'm working on a Java app that uses multiple APIs and would like to keep the API tokens out of the public GitLab repository. The app is packaged and deployed to a remote server and I don't know how to make the tokens available without including them in the GitLab repository otherwise.
Is there a way I can restrict the viewing of a file (or part of it) to sort of "redact" these tokens? Or should I go about it a different way?
Don't put API keys in your repo. Inject them into your use of the repo via environment variables which are maintained by your deployment system. If you deployment system doesn't have that ability, you probably need to change it. It doesn't need to be too complicated - for example change it to deploying your code from git, then copying a .env file into place separately. If your deployment mechanism only lets you use git repos, you could put your env vars into a separate repo that is kept private.
I have a similar situation with injecting google-services.json file into an Android application. Long story short we have multiple environments our app targets, and the production environment file must, somehow, reside in the build pipelines (either, committed or something).
As pointed by the previous response having this information committed in the main repo is not ideal. Developers could accidentally use the production environment while testing for example.
How we solved this
First, documentation. All those files (google-services.json and similar others) are ignored in git and the developer documentation states you must add your own.
Second, the CI build pipelines. We are also using GitLab, and we store those files as base64 encoded strings in CI variables, controlling then access to those variables via the protected tags/branches mechanism GitLab offers.
Serializing the files
There are two steps involved in here. First serialize an actual file in base64. Second, de-serialize the file from base64 into its appropriate location.
base64 --wraps=0 google-services.json (wraps option prevents line wrapping if done in console directly.). Then store the output in a GitLab CI variable.
In the .gitlab-ci.yml file do the inverse to inject the file.
echo $VAR_NAME | base64 -d > where/you/need/the/file.
You then control the appropriate environment to use via the $VAR_NAME variable.
An example of this an be found at https://gitlab.com/snippets/1926611. This case is for an xml file with the Google Maps API key, but the process is identical.
You can create a variable in you GitLab project settings. The variable can be used in your .gitlab-ci.yml file.
For example,
create a variable named GOOGLE_SERVICE_JSON and set the value to the base64 format of the file content. You can get it by command base64 google-services.json
update your .gitlab-ci.yml file, decode the GOOGLE_SERVICE_JSON value to google-services.json file like this
assembleDebug:
stage: build
script:
- echo ${GOOGLE_SERVICE_JSON} | base64 -d > app/google-services.json
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
You can also use this method to encode the keystore file to a variant and decode it to a file in pipeline build.
Here is a full example
image: openjdk:8-jdk
variables:
ANDROID_COMPILE_SDK: "28"
ANDROID_BUILD_TOOLS: "28.0.3"
ANDROID_SDK_TOOLS: "6609375_latest"
before_script:
- echo ANDROID_COMPILE_SDK ${ANDROID_COMPILE_SDK}
- echo ANDROID_BUILD_TOOLS ${ANDROID_BUILD_TOOLS}
- echo ANDROID_SDK_TOOLS ${ANDROID_SDK_TOOLS}
- apt-get --quiet update --yes
- apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1
- wget --quiet --output-document=android-sdk.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}.zip
- unzip -d android-sdk-linux android-sdk.zip
- export ANDROID_SDK_ROOT=$PWD/android-sdk-linux
- export SDK_MANAGER="${ANDROID_SDK_ROOT}/tools/bin/sdkmanager --sdk_root=${ANDROID_SDK_ROOT}"
- echo y | ${SDK_MANAGER} "platforms;android-${ANDROID_COMPILE_SDK}" >/dev/null
- echo y | ${SDK_MANAGER} "platform-tools" >/dev/null
- echo y | ${SDK_MANAGER} "build-tools;${ANDROID_BUILD_TOOLS}" >/dev/null
- export PATH=$PATH:${ANDROID_SDK_ROOT}/platform-tools/
- chmod +x ./gradlew
# temporarily disable checking for EPIPE error and use yes to accept all licenses
- set +o pipefail
- echo y | ${SDK_MANAGER} --licenses
- set -o pipefail
stages:
- build
assembleDebug:
stage: build
script:
- echo ${GOOGLE_SERVICE_JSON} | base64 -d > app/google-services.json
- echo ${KEY_STORE_PROP} | base64 -d > app/keystore.properties
- echo ${STORE_FILE} | base64 -d > app/keystore.jks
- ./gradlew assembleDebug
artifacts:
paths:
- app/build/outputs/
assembleRelease:
stage: build
script:
- echo ${GOOGLE_SERVICE_JSON} | base64 -d > app/google-services.json
- echo ${KEY_STORE_PROP} | base64 -d > app/keystore.properties
- echo ${STORE_FILE} | base64 -d > app/keystore.jks
- ./gradlew assembleRelease
artifacts:
paths:
- app/build/outputs/