Closed pstephenson02 closed 6 years ago
I would like to clarify my question:
In order for nvm to work when running a build, the shell which runs the builds must first run $NVM_DIR/nvm.sh
. However, I would like to avoid having to execute this nvm startup script in every build configuration I setup in TeamCity projects. Is there a way that I can force the agent to run this script each time it starts up? Thanks again.
Thing is nvm does not provide any binary that could be added into PATH, so some script should run . "$NVM_DIR/nvm.sh"
or alternatively you could create some script and place it into PATH using for example Script 1 (see below).
Another alternative is to use next hack in Dockerfile - replace origin run-agent.sh with modified one:
RUN mv /run-agent.sh /run-agent.origin.sh && \
echo -e '#!/bin/bash\nexport NVM_DIR="$HOME/.nvm"\n. "$NVM_DIR/nvm.sh"\n./run-agent.origin.sh' >/run-agent.sh && \
chmod +x /run-agent.sh
Script 1:
tee nvm-wrapper.sh <<EOF
#!/bin/bash
set -e
if [ "\$NW_DEBUG" = "true" ]; then
set -x
fi
NVM_DIR=\${NVM_DIR:-$DIR}
command_to_execute=\$(basename \$0)
source "\$NVM_DIR/nvm.sh"
nvmrc_path="\$(nvm_find_nvmrc)"
if [ -e "\$nvmrc_path" ]; then
nvm use >&2 || nvm install >&2
else
echo ".nvmrc is not found, using default version" >&2
nvm use default >&2
fi
version=\$(nvm version)
exec "\$NVM_DIR/versions/node/\$version/bin/\$command_to_execute" "\$@"
EOF
chmod 755 nvm-wrapper.sh
ln -s nvm-wrapper.sh node
ln -s nvm-wrapper.sh npm
Thanks for your response. I tried both of your methods and neither of them worked for me. I also tried a number of other ideas as well. I was able to get more information by running ps -aux
in the build and see how the build actually gets invoked:
[15:21:13][Step 1/1] Starting: /opt/buildagent/temp/agentTmp/custom_script7525124466095535933
[15:21:13][Step 1/1] in directory: /opt/buildagent/work/f4281a9c3a55712f
[15:21:13][Step 1/1] USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
[15:21:13][Step 1/1] root 1 0.0 0.1 19744 3320 pts/0 Ss+ 22:08 0:00 /bin/bash /run-agent.sh
[15:21:13][Step 1/1] root 1267 0.0 0.0 6036 688 pts/0 S+ 22:09 0:00 tail -qF /opt/buildagent/logs/teamcity-agent.log /root/anchor
[15:21:13][Step 1/1] root 1389 0.1 1.9 2825700 40196 pts/0 Sl+ 22:09 0:01 /usr/lib/jvm/oracle-jdk/jre/bin/java -ea -cp ../launcher/lib/launcher.jar jetbrains.buildServer.agent.Launcher -ea -Xmx384m -Dteamcity_logs=../logs/ jetbrains.buildServer.agent.AgentMain -file /data/teamcity_agent/conf/buildAgent.properties
[15:21:13][Step 1/1] root 1402 4.8 14.6 2896684 296420 pts/0 Sl+ 22:09 0:32 /usr/lib/jvm/oracle-jdk/jre/bin/java -ea -Xmx384m -Dteamcity_logs=../logs/ ...
[15:21:13][Step 1/1] root 1983 0.0 0.1 19700 3176 pts/0 S+ 22:21 0:00 /bin/sh /opt/buildagent/temp/agentTmp/custom_script7525124466095535933
[15:21:13][Step 1/1] root 1984 0.0 0.1 36080 3200 pts/0 R+ 22:21 0:00 ps -aux
[15:21:13][Step 1/1] Process exited with code 0
From here I noticed that the builds get invoked like this:
/bin/sh /opt/buildagent/temp/agentTmp/custom_script7525124466095535933
Seeing as how there are no arguments, the shell runs as non-interactive and non-login modes. Without either of these modes, the shell will not try to read any of the various /etc/profile
, ~/.profile~
, or ~/.bashrc
files. By default, Ubuntu actually uses the dash shell for /bin/sh
and there is limited functionality there.
I also tried just restoring the fully-featured bash shell (rather than dash) by using the methods described here: https://superuser.com/a/1064247. Now, when teamcity invokes /bin/sh
at least it should be a bash shell now. According to the bash documentation, I thought I could pass in an environment variable $ENV and it would run scripts defined, so I tried in my docker file:
ENV ENV="$HOME/.nvm/nvm.sh"
RUN echo "dash dash/sh boolean false" | debconf-set-selections && \
DEBIAN_FRONTEND=noninteractive dpkg-reconfigure dash
But this still did not work.
I have spent quite a few hours trying to get something to work. This is quite frustrating as a developer. Having spent the time to setup custom build agents, it would be great if there were better ways to hook into the build lifecycle. And using teamcity "templates" is unnacceptable I think. I want my build agent setup to be declarative, and defined in code - not stored as some template in TeamCity.
Anyway, thank you for your help. I would like to leave this issue open for a little bit in case anyone else runs into this problem and has other ideas.
Closing this issue. For anyone reading this, I ended up switching to the windows server core 2016 container.
@ @ @
I know this is closed already but what ended up working is using the linux source
command to update the bash profile during CI. It is likely that TC was running under a different bash profile and we had to switch to a specific one.
I know this is closed already but what ended up working is using the linux
source
command to update the bash profile during CI. It is likely that TC was running under a different bash profile and we had to switch to a specific one.
oh yeah, and I totally forgot that the env was not a docker container...it was a linux host. So maybe the above doesn't apply anyway 🤔
In case anyone else arrives at this thread and is stuck:
My problem was that nvm installs, by default on the currently running user. But my teamcity agent was running as a different user!
I eventually noticed that the NVM_HOME folder was pointing to a specific user's profile. I could then fix this by changing the TeamCity agent to run as that specific user, or by installing NVM on the correct user.
Hello! I am having a really hard time setting up my docker build agent to build projects that use nvm/node/npm. I have created a Dockerfile like this:
When I build a new image using this dockerfile, it seems to install nvm correctly:
The agent connects to teamcity correctly, and I have authorized the agent from the TeamCity admin UI. However, when I go to build a project, the build always fails:
The agent process appears to be running as root in the container, but do the individual builds get kicked off with the
buildagent
user? In which case, does nvm need to be installed as thebuildagent
user? (I tried this in the Dockerfile by placingUSER buildagent
before the nvm install, but it still did not work).For what it's worth, when I log into the container, it appears to pick up the .bashrc and finds nvm in the path:
Thank you in advance