Context
I want to run a bash script during the building stage of my CI.
So far, MacOS building works fine and Unix is in progress but I cannot execute the scripts in my Windows building stage.
Runner
We run a local gitlab runner on Windows 10 home where WSL is configured, Bash for Windows installed and working :
Bash executing in Windows powershell
Gitlab CI
Here is a small example that highlights the issue.
gitlab-ci.yml
stages:
- test
- build
build-test-win:
stage: build
tags:
- runner-qt-windows
script:
- ./test.sh
test.sh
#!/bin/bash
echo "test OK"
Job
Running with gitlab-runner 13.4.1 (e95f89a0)
on runner qt on windows 8KwtBu6r
Resolving secrets 00:00
Preparing the "shell" executor 00:00
Using Shell executor...
Preparing environment 00:01
Running on DESKTOP-5LUC498...
Getting source from Git repository
Fetching changes with git depth set to 50...
Reinitialized existing Git repository in C:/Gitlab-Ci/builds/8KwtBu6r/0/<company>/projects/player-desktop/.git/
Checking out f8de4545 as 70-pld-demo-player-ecran-player...
Removing .qmake.stash
Removing Makefile
Removing app/
Removing business/
Removing <company>player/
git-lfs/2.11.0 (GitHub; windows amd64; go 1.14.2; git 48b28d97)
Skipping Git submodules setup
Executing "step_script" stage of the job script 00:02
$ ./test.sh
Cleaning up file based variables 00:01
Job succeeded
Issue
As you can see, the echo message "test OK" is not visible in the job output.
Nothing seems to be executed but no error is shown and running the script on the Windows device directly works fine.
In case you are wondering, this is a Qt application built via qmake, make and deployed using windeployqt in a bash script (where the issue is).
Any tips or help would be appreciated.
edit : Deploy script contains ~30 lines which would make the gitlab-ci yaml file hard to read if the commands are put directly in the yaml instead of an external shell executed during the CI.
Executing the script from the Windows env
It may be due to gitlab opened a new window to execute bash so stdout not captured.
You can try use file system based methods to check the execution results, such as echo to files. The artifact can be specified with wildcard for example **/*.zip.
I also tested on my windows machine. First if i run ./test.sh in powershell, it will prompt dialog to let me select which program to execute. the default is git bash. That means on your machine you may have configured one executable (you'd better find it out)
I also tried in powershell:
bash -c "mnt/c/test.sh"
and it gives me test OK as expected, without new window.
So I suggest you try bash -c "some/path/test.sh" on your gitlab.
Related
I'm running CI jobs on a self-hosted GitLab instance plus 10 GitLab Runners.
For this minimal example, two Runners are needed:
Admin-01
A shell runner with Docker installed.
It can execute e.g. docker build ... to create new images, which are then pushed to the private Docker registry (also self-hosted / part of the GitLab installation)
Docker-01
A docker runner, which executes the previously build image.
On a normal bare-metal, virtual machine or shell runner, I would modify e.g. ~/.profile to execute commands before before_script or script sections are executed. In my use case I need to set new environment variables and source some configuration files provided by the tools I want to run in an image. Yes, environment variables could be set differently, but there seams to be no way to source Bash scripts automatically before before_script or script sections are executed.
When sourcing the Bash source file manually, it works. I also notice, that I have to source it again in script block. So I assume the Bash session is ended between before_script block to script block. Of cause, it's no nice solution to manually source the tools Bash configuration script in every .gitlab-ci.yml file manually by the image users.
myjobn:
# ...
before_script:
- source /root/profile.additions
- echo "PATH=${PATH}"
# ...
script:
- source /root/profile.additions
- echo "PATH=${PATH}"
# ...
The mentioned modifications for e.g. shell runners does not work in images executed by GitLab Runner. It feels like the Bash in the container is not started as login shell.
The minimal example image is build as follows:
fetch debian:bullseye-slim from Docker Hub
use RUN commands in Dockerfile to modify with some echo outputs
/etc/profile
/root/.bashrc
/root/.profile
# ...
RUN echo "echo GREETINGS FROM /ROOT/PROFILE" >> /root/.profile \
&& echo "echo GREETINGS FROM /ETC/PROFILE" >> /etc/profile \
&& echo "echo GREETINGS FROM /ROOT/BASH_RC" >> /root/.bashrc
When the job starts, non of the echos is printing messages, while a cat shows, the echo commands have been put at the right places while building the image.
At next I tried to modify
SHELL ["/bin/bash", "-l", "-c"]
But I assume, this has only effects in RUN commands in the Dockerfile, but not on an executed container.
CMD ["/bin/bash", "-l"]
I see no behavior changes.
Question:
How to start the Bash in the Docker image managed by GitLab Runner as login shell so it ready configuration scripts?
How to modify the environment in a container before before_script or script runs. Modifying means environment variables and execution / sourcing a configuration script or patched default script like ~/.profile.
How does GitLab Runner execute a job with Docker?
This is not documented by GitLab in the official documentation ...
What I know so far, it jumps between Docker images specified by GitLab and user defined images and shares some directories/volumes or so.
Note:
Yes, the behavior can be achieved with some Docker arguments in docker run, but as I wrote GitLab Runner is managing the container. Alternatively, how to configure, how GitLab Runner launches the images? To my knowledge, there is no configuration option available / documented for this situation.
A shell runner with Docker installed. It can execute e.g. docker build ...
Use docker-in-docker or use kaniko. https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
Shell executor is like "the last resort", where you want specifically to make changes to the server, or you are deploying your application "into" this server.
How to start the Bash in the Docker image managed by GitLab Runner as login shell so it ready configuration scripts?
Add ENTRYPOING bash -l to your image. Or set the entrypoint from gitlab-ci.yml. See docker documentation on ENTRYPOINT and gitlab-ci.yml documentation on image: entrypoint: .
How to modify the environment in a container before before_script or script runs.
Build the image with modified environment. Consult Dockerfile documentation on ENV statements.
Or set the environment from gitlab-ci.yml file. Read documentation on variables: in gitlab-ci.
How to prepare the shell environment in an image executed by GitLab Runner?
Don't. The idea is that the environment is reproducible, ergo, there should be no changes beforehand. Add variables: in gitlab-ci file and use base images if possible.
How does GitLab Runner execute a job with Docker?
This is not documented by GitLab in the official documentation ...
Gitlab is open-source.
What I know so far, it jumps between Docker images specified by GitLab and user defined images and shares some directories/volumes or so.
Yes, first a gitlab-runner-helper is executed - it has git and git-lfs and basically clones the repository and downloads and uploads the artifacts. Then the container specified with image: is run, cloned repository is copied into it and a specially prepared shell script is executed in it.
I got a job to compile 32bit and 64bit version of the code,then get the package to the central server,to compile the code,I have to run a shell script and will call another script,due to the two scripts have nearly 1k lines,I don't want to meger to one script.
I have see the answer,and It just sovle parts of the problem
run shell on remote-machine,Jason R. Coombs's anwser was great,when I run a shell scripts on local machine,In fact it runs in remote,what's most the output just shows in local machine,that's what's I want.for example when compile 32bit version failed ,I can see what's wrong on local machine and no need to ssh to the remote machine to compile again.
there two questions:
1.how to run two scripts in local machine I just dont't want to merge nearly 1k shell scripts together.
2.when I run the scripts,how to change the working dictory,example,I want the code run in /root/compile32 ,the shell scripts will git clone the code and compile && install using make and other actions.
I'm trying to use bash as the shell on Windows for a GitLab CI Runner.
concurrent = 1
check_interval = 0
[[runners]]
name = "DESKTOP-RQTQ13S"
url = "https://example.org/ci"
token = "fooooooooooooooooooobaaaaaaaar"
executor = "shell"
shell = "bash"
[runners.cache]
Unfortunately I can not find an option to specify the actual shell program that the CI Runner should use. By default, it just tries to run bash which it can not find. I don't know why, because when I open up a Windows command line and enter bash it works.
Running with gitlab-ci-multi-runner 1.9.4 (8ce22bd)
Using Shell executor...
ERROR: Build failed (system failure): Failed to start process: exec: "bash": executable file not found in %PATH%
I tried adding a file bash.cmd to my user directory containing
#"C:\Program Files\Git\usr\bin\bash.exe" -l
That gives me this strange error:
Running with gitlab-ci-multi-runner 1.9.4 (8ce22bd)
Using Shell executor...
Running on DESKTOP-RQTQ13S...
/usr/bin/bash: line 43: /c/Users/niklas/C:/Users/niklas/builds/aeb38de4/0/niklas/ci-test.tmp/GIT_SSL_CAINFO: No such file or directory
ERROR: Build failed: exit status 1
Is there a way to properly configure this?
There are two issues going on here, and both can probably be solved.
gitlab-runner cannot find bash
gitlab-runner doesn't combine unix-style and Windows-style paths very well.
You have essentially succeeded in solving the first one by creating the bash.cmd file. But if you're curious about why it didn't work without it, my guess is that bash runs in your command prompt because the directory that contains it (e.g. in your case "C:\Program Files\Git\usr\bin") is included in the PATH environment variable for your user account. But perhaps you are running the gitlab-runner in the system account, which might not have the same PATH.
So the first thing to do is just check your system's PATH variable and add the bin directory if necessary (i.e. using the System applet in the Control Panel as described here or here). Just make sure you restart your machine after you make the change, because the change isn't applied until after you restart. That should make bash work, even when called from a service running in the system or admin account.
As for the strange error you got after creating bash.cmd, that was due to the second issue. Paths are often really hard to get right when combining bash and Windows. Gitlab-runner is probably trying to determine whether the build path is relative or absolute, and ends up prepending the windows path with what it thinks is the working directory ($PWD). This looks like a bug, but gitlab still has not fixed it (as of version 9.0 of the runner!!) and probably never will. Maybe they have decided it is not a bug or that it is due to bugs in underlying software or tools that they can't fix or that it would be too difficult to fix. Anyway, I've discovered a work-around. You can specify the base path for builds in the config.toml file. If you use a unix-style path, it fixes the problem.
On windows, config.toml is usually in the same folder as your gitlab-runner.exe (or gitlab-multi-runner-amd64.exe etc). Open that file in your favorite text editor. Then find the [[runners]] section and add two lines similar to the following.
builds_dir="/c/gitlab-runner/builds/"
cache_dir="/c/gitlab-runner/cache/"
The path you use should be the "bash version" of whatever directory you want gitlab-runner to use for storing builds etc. Importantly if you are using cygwin, you would use a path similar to /cygdrive/c/... instead of just /c/... (which is appropriate for msys-git or standalone MSYS2 etc).
Here's an example of a config.toml file:
[[runners]]
name = "windows"
url = "https://your.server.name"
token = "YOUR_SECRET_TOKEN"
executor = "shell"
shell = "bash"
builds_dir="/c/gitlab-runner/builds/"
cache_dir="/c/gitlab-runner/cache/"
It looks like you're attempting to link gitlab-ci up with the Windows Subsystem for Linux (which can be accessed by typing bash at the Windows command prompt)? I doubt that this is supported directly by Gitlab's runner configuration.
Instead, I would suggest using Powershell with your shell executor.
Executor = 'shell'
Shell = 'powershell'
You can then drop down into Bash in the scripts you call from .gitlab-ci.yml.
Given that it's bad practice to execute more than very trivial shell scripts within the .gitlab-ci.yml itself (as opposed to calling out to an external script), you lose little by being forced to use a native Windows shell.
We use a official Windows runner from Gitlab-ci. We want to upload artifacts.
We use the 'artifact' keyword in our yaml file to define the artefacts that need to be uploaded. When we commit this is the message we are getting:
gitlab-ci-multi-runner 0.7.2 (998cf5d)
WARNING: artifacts is not supported by selected executor and shell
Using Shell executor...
So is this because it is using a Windows machine? What is the deal here?
Uploading artifacts from the windows shells cmd and powershell are currently not supported. After a while of digging the source I found that according to gitlab-ci-multi-runner\shells\bash.go bash does support it.
The working solution for me is:
install Bash (already included with Git-SCM)
add the bash directory (C:\Program Files (x86)\Git\bin) to your PATH
make sure bash starts if you type bash in the cmd
find your config.toml and modify/add:
executor = "shell"
shell = "bash"
restart your git-runner service
make sure your build scripts are in bash-syntax
(for example run windows commands from bash with cmd.exe /c "dir")
I have Jenkins running on Windows, and I have a build that works fine under CygWin bash from the CygWin terminal, so I now want to automate it. However, using this script:
#!C:\cygwin\bin\bash.exe
whoami
make
The system reports me as nt authority\system, not the ken that I get when using an interactive shell. Is there an easy way to persuade Jenkins or CygWin to run as me?
Most likely you are running jenkins with default installation. You have two options. First is mentioned in the comment. Change the "Service account" to be same as yours.
Second option is derived from best practices. Run the jenkins master on a system with backup etc. Configure slave node with your account credentials. Change the project configuration to build on the specific node.
(It is possible to run slave and master on same machine with different credentials - just in case you want to try out things)
The real problem I was having was not that the shell script was running as the wrong user, but that the shell script was not executing the default /etc/profile. So, the solution was simply:
#!C:\cygwin\bin\bash.exe -l
whoami
make
I was still nt authority\system, but now I had the correct environment set up and could run make successfully.
Note also that if I create a /home/system directory I can add .bash_profile, etc, to that directory to further customise the build environment.