Currently working to get a new app to deploy using Jenkins and stuck on an issue with package restore.
Please note...my focus is in dev, not DevOps so a lot of this is still pretty foreign to me. So, I apologize in advance if it takes some back and forth for clarification.
The project uses the following files: jenkinsfile, docker-compose.bi.build.yml, build.sh, and nuget.config. Those files are all listed below for reference.
Brief Overview:
I have 2 DLLs that are source controlled in 2 separate VS solutions (and seperate Git repos). Those DLLs are: AN.Infrastructure (infras) and AN.Domain.Core (domain). domain depends on infras. infras is some basic stuff...string extensions, etc. and doesn't have many depenedencies. domain has more dependencies on things like EF, Postgres EF, AutoMapper, etc., but it also pulls in infras during the package restore process. infras and domain are set up the same way as far as source control, jenkins, etc. are concerned (meaning I expect them to build nearly the same minus the extra dependencies).
Currently, infras is building and deploying as it should so i know the process I have is working.
The process goes like this:
The jenkinsfile spins up a container based on the ci.build.yml file.
This container is meant to build the source code and copy the output
to a staged directory so that the rest of the process can
package/deploy it.
The build.sh script is executed inside the running container that is
building the code and is doing the work to restore dependencies, kick
off msbuild, and then package the artifacts.
Problem:
I can't get the domain solution to build thru Jenkins due to what appears to be missing package references. The process throws the following error:
Package Microsoft.EntityFrameworkCore.Analyzers, version 3.1.4 was not
found. It might have been deleted since NuGet restore. Otherwise,
NuGet restore might have only partially completed, which might have
been due to maximum path length restrictions.
What I Know:
I have proven the infras pipeline works end-to-end as I can navigate
to and install the infras assembly via VS nuget UI to the domain
solution on my local machine. The domain solution builds and works
as expected in this manner.
I also know the code for domain is being pulled down to the jenkins
server when the pipeline job is kicked off...I remoted into the
workspace folder in /var/lib/jenkins to confirm.
Also, I see all my echo printouts in the output from the build.sh
script when the domain job runs. So, the process is running like I
expect, it just fails at package restore.
Since infras is hosted on a Linux file share and not directly at
nuget.org, I read that I have to use a nuget.config file next to the
solution in order to configure the package sources so dotnet build
knows where to restore the packages from. I created that file and
it is below. I have tried with and without that file though and it
fails both ways.
I noticed that the MS.EF.Analyzers DLL is being pulled into the
domain project indirectly via npgsql.entityframeworkcore.postgres
dependency. So, I decided to include npgsql in infras solution as
well as I thought this would break that build also. However, that
wasn't the case. infras built in Jenkins even after I pulled in
that depenedency.
What I Have Tried:
You name it....I'm at 45 builds in Jenkins right now...each time trying something new (eg...with nuget.config, without nuget.config, etc.). What I posted in the files below is the current state and what I have described in the question. I am more than happy to answer any question, provide any additional info, or try whatever to get this resolved...just not sure where to go at this point.
Jenkinsfile:
pipeline {
agent any
stages {
stage('Build The Codes') {
steps {
sh '''sudo AN_BUILD_NUMBER=${BUILD_NUMBER} /usr/local/bin/docker-compose -f docker-compose.ci.build.yml up'''
}
}
stage ('Deploy The Codes') {
when {
branch 'main'
}
steps {
sh '''sudo cp ./src/AN.Domain.Core/bin/Release/*${BUILD_NUMBER}.nupkg /opt/nuget/development/'''
}
}
stage ('Deploy The Codes 2.0') {
when {
branch 'release'
}
steps {
sh '''sudo cp ./src/AN.Domain.Core/bin/Release/*${BUILD_NUMBER}.nupkg /opt/nuget/production/'''
}
}
}
}
docker-compose.ci.build.yml:
version: '3.8'
volumes:
nugetdirectory:
services:
ci-build:
image: mcr.microsoft.com/dotnet/sdk:3.1
volumes:
- .:/src:z
- nugetdirectory:/opt/nuget/production
working_dir: /src
environment:
- "AN_BUILD_NUMBER=${AN_BUILD_NUMBER}"
command: /bin/bash -c "sh ./build.sh"
build.sh:
echo '*** Starting build process for AN.Domain project ***'
echo 'Generate New Assembly Version'
year=$(date '+%Y')
month=$(date '+%m')
day=$(date '+%d')
version="${year}.${month}.${day}.${AN_BUILD_NUMBER}"
echo 'New Assembly Version: ' + $version
echo 'Clean previous output directory for AN.Domain project'
echo ' - Remove Docker publish directory'
rm -rf obj/Docker/publish
echo ' - Remove previous nuget packages'
rm /src/src/AN.Domain.Core/bin/Release/*.nupkg
echo 'Clean output directory for AN.Domain project'
dotnet clean
echo 'Publish AN.Domain project'
dotnet msbuild /t:Restore -target:Publish -property:Configuration=Release -property:OutputPath=obj/Docker/publish -property:Version=$version
echo 'Copy NuGet packages to output directory'
cp /src/src/AN.Domain.Core/bin/Release/*.nupkg obj/Docker/publish
echo '*** Finishing build process for AN.Domain project ***'
nuget.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="privateRepo" value="/opt/nuget" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>
UPDATES:
I removed the domain project from the solution and created a brand new console app to test with. This project built as expected when run via Jenkins. I even added the dependency to npgsql which also brought in the MS.EF.Analyzers DLL that is causing the issue.
I just added to the test console app the dependency on infras and
this breaks the build with the same error. So, it is definitely
bringing in that custom nuget package that is causing the build
error.
So, I replaced this line in build.sh:
dotnet msbuild /t:Restore -target:Publish -property:Configuration=Release -property:OutputPath=obj/Docker/publish -property:Version=$version
with this:
dotnet publish -c Release -o obj/Docker/publish /property:Version=$version
Initially I had "dotnet publish", but I had this same error. I got the former idea from the SO question below, but I believe I did this before I learned about nuget.config. So, I think what might have happened is that both were necessary but I didn't have nuget.config when I was using "dotnet publish" and then I switched it over to msbuild and never went back and tested with this combination of dotnet publish and nuget.config.
Jenkins not picking up the nuget restored packages
Related
We have a build pipeline that's been working for a year or two. This builds and creates a few artifacts - ASP.Net web application, windows services, etc. The issue here is with the ASP.Net web application.
We've added some REACT components to the build. There are now an enormous \React\node_modules\ folder with tens of thousands of files. I want to exclude the \React\node_modules folder from the "Publish Artifact" step. I've edited this step, by adding this under the File copy options setting:
/XD react/node_modules
I have a "Publish Artifact" task that has "/XD react/node_modules" set as the File Copy options. However, when I run the build pipeline, it still copies everything in the react/node_modules folder.
When I view the raw logs, I do not see that being passed as an argument in the Robocopy command. I only see this in the logfile for the Publish Artifact step:
2022-04-13T00:24:47.8605686Z ##[command]robocopy.exe /E /COPY:DA /NP /R:3 /MT:8 "C:\agent_agentwork\1\s\Website" "c:\builds\HF\HF_3.8.1.75\Website" "*"
Any idea why it's not working here?
This is a bug in the Publish artifact task. A github issue has been logged for this in 2019 (https://github.com/microsoft/azure-pipelines-tasks/issues/11451). Sadly, it is not fixed yet.
Awaiting a fix, you could work around it by putting a build step that explicitly calls robocopy to copy the build output to a temporary location (with the /XD switch). And then put the 'Publish artifact' step that copies from that temporary location.
I'm attempting to get aws code-pipeline and code-build working for a .Net framework web application.
My buildspec looks like this...
version: 0.2
env:
variables:
PROJECT: TestCodeBuild1
DOTNET_FRAMEWORK: 4.7.2
phases:
build:
commands:
- dir
- nuget restore $env:PROJECT.sln
- msbuild $env:PROJECT.sln /p:TargetFrameworkVersion=v$env:DOTNET_FRAMEWORK /p:Configuration=Release /p:DeployIisAppPath="Default Web Site" /p:PackageAsSingleFile=false /p:OutDir=C:\codebuild\artifacts\ /t:Package
artifacts:
files:
- '**/*'
base-directory: 'C:\codebuild\artifacts\_PublishedWebsites\${env:PROJECT}_Package\Archive\'
The "dir" line in the buildspec was put there just to confirm it's is in the correct directory, and the required folders are there, which they are.
It's using the following image for the build environment...
mcr.microsoft.com/dotnet/framework/sdk:4.7.2
When it runs, I get the following warning, when it gets to the nuget restore...
WARNING: Error reading msbuild project information, ensure that your input solution or project file is valid. NETCore and UAP projects will be skipped, only packages.config files will be restored.
The msbuild then subsequently also fails, but I'm guessing that may be related to the fact that nuget restore hasn't worked correctly.
I've confirmed that the project and solution is correct. If I run "nuget restore" from my local environment it works fine, without any errors or warnings.
I thought perhaps it was something particular to the docker environment, so I tried creating a Dockerfile like so...
FROM mcr.microsoft.com/dotnet/framework/sdk:4.7.2
WORKDIR /app
COPY . .
RUN nuget restore
This also works fine. "docker build ." runs without any warnings.
So I'm not sure why this is failing in code-build. As far as I can see everything is correct, and I haven't found any way to reproduce the issue locally.
Other forum posts just suggest correcting package issues in the project files. However there are no issues as far as I can see with the project packages.
Here is what I did and it seems to have worked:
1.: buildspec.yml
version: 0.2
env:
variables:
SOLUTION: .\MyProject.sln
PACKAGE_DIRECTORY: .\packages
DOTNET_FRAMEWORK: 4.6.2
PROJECT: MyProjectName
phases:
build:
commands:
- .\nuget restore
- >-
msbuild $env:PROJECT.csproj
/p:TargetFrameworkVersion=v$env:DOTNET_FRAMEWORK
/p:Configuration=Release /p:DeployIisAppPath="MySite"
/p:PackageAsSingleFile=false /p:OutDir=C:\codebuild\artifacts\
/t:Package
artifacts:
files:
- '**/*'
base-directory: 'C:\codebuild\artifacts\_PublishedWebsites\${env:PROJECT}_Package\Archive\'
I then downloaded nuget.exe (https://www.nuget.org/downloads) and put it into the root directory (the same directory as the .sln file)
When I pushed my commit to the branch on AWS, ".\nuget.exe" successfully restored all packages. I am using the Docker image "microsoft/aspnet:4.6.2".
Hope it helps someone.
I have a github repository with a declarative pipeline Jenkinsfile.
The workingdirectory on my node contains subdirectories.
The project is a simple empty linkx docker project created with visual studio 2017 and .net core 2.1. It executes on my windows 7 machine normally and has a hello world web page.
I am unable to build the Dockerfile on jenkins.
I can start the Dockerfile build using dir(...){}.
The failing step is always
COPY ["MyProject/MyProject.csproj", "MyProject/"]
This step requires the relative path to be in MySolution.
The file Workspace/MySolution/MyProject/MyProject.csproj exists
The error Message is that Workspace/MyProject/MyProject.csproj does not exist.
I searched exhaustively using google and stackoverflow. Among the things I tries are combinations of sh commands, dir syntax, options on docker build like -f. Some of them were straigth up failures and the best results I had ran into the COPY step issue.
One example of a failing step in the Jenkinsfile would be:
dir("MySolution/MyProject")
{
script
{
docker.build("MyProject", ".")
}
}
This fails with the COPY issue from above.
I have seen questions on so that seem to not quite apply here and which solutions did not transfer to this issue.
It turns out I ended up really close to the solution of my issue.
This fixed my sub folder problem:
dir("MySolution")
{
script
{
docker.build("MyProject", "-f ./MyProject/Dockerfile .")
}
}
I'm trying to get our TFS2015 Build (TFSBuild vnext) going along with VS Team Services.
Thus far most blogs and documentation has been helpful, except for when trying to build a project that uses custom package sources for NuGet automatic package restore.
I've successfully deployed an a Team Services Build Agent (the new mechanism for builds) and all seemed to go well until the build task to Restore NuGet packages failed.
The failure was due to custom/private package source not being picked up from the installed VS configuration, so those packages could not be found. The traditional packages from the default NuGet package feed did restore without issue.
How do I specify the additional package sources for NuGet to use when using an agent?
EDIT: vcastro asked about the NuGet Installer build step and defining paths in the configuration of that build step. The above is using the Visual Studio Build step and the integrated option to have NuGet restore packages. Refer this image for reference:
Alternatively you could also add a NuGet Installer build step before the Visual Studio Build step in your build configuration to restore all NuGet packages.
There you can pass the location of your private repo as argument to nuget.exe:
-source "https://www.nuget.org/api/v2/;http://mynugetserver"
I've scrounged the web with little success, but after fiddling the following will help:
OK It seems that the package sources configured for NuGet.config is stored per user account, e.g.
c:\Users\<<username>>\AppData\Roaming\NuGet\NuGet.config
My issue was harder to resolve, because the build agent was running as a Windows Service under the Local System account. So to get NuGet configuration to for the build, I had to use the following path instead:
64-bit Windows C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config
32-bit Windows C:\Windows\System32\config\systemprofile\AppData\Roaming\NuGet\NuGet.Config
You may need to have elevated permissions in order to create the NuGet subfolder and NuGet.Config file.
Note: I have no solution for using the Local Service account. The above only works for the Local System (or an actual user) account.
Add a NuGet.config to your project that specifies an alternate package location. The rules for resolution are well-defined and explained in the official documentation.
There is a new VSTS Task called "NuGet Installer" this allows you to check in your NuGet.config file and specify the different package sources. Run this task before you run MSBuild.
If you are using the VSTS NuGet Feed you will need to add the build service account to the feed to enable downloading of packages https://www.visualstudio.com/get-started/package/use/common-identities
One solution (works for me) is change account for tfs 2015 build agent service (on my build machine VSO Agent tsf.Agent-PC) to tfsagent, for example, and add Nuget.config to the C:\Users\tfsagent\AppData\Roaming\Nuget. That's all!
Specify your custom NuGet feed URL’s in the solution’s nuget.config file. Do not store any usernames & passwords in this file.
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="MyCompany" value="https://nuget.mycompany.com:443/nuget" />
Create username & password variables in your build definition in VSTS. Variables can be encrypted and will not be displayed in any of the build log outputs. Here I'll create MyCompanyNugetUser and MyCompanyNugetPwd variables.
In our build steps, we add a Powershell script as the first action, this will read the username & password variables and update the user level nuget.config file on the build machine. Below is the code snippet from my inline Powershell script:
Arguments:
$(MyCompanyNugetUser) $(MyCompanyNugetPwd)
Script:
param($user, $pwd)
$nugetFile = "$ENV:AGENT_HOMEDIRECTORY\agent\worker\tools\nuget.exe"
Write-Output "Looking for nuget.exe in $nugetFile"
if (-not (Test-Path $nugetFile))
{
Write-Error "nuget.exe could not be located."
return
}
Write-Output "nuget.exe located"
$cmd = "$nugetFile sources add -name MyCompany -source https://nuget.mycompany.com:443/nuget -username $user -password $pwd -StorePasswordInClearText"
Write-Output $cmd
iex $cmd
Next, we just continue to execute the default NuGet Restore step from Microsoft’s templates
More here: https://codingcase.com/2016/07/27/vsts-build-setup-custom-nuget-feeds-with-authentication/
HTH
In the RTM of Team Foundation Server 2015 you have to add a build step of the type "NuGet Installer", and restore the packages of the Solution file before you run the actual build process. In this task you can pass the argument -ConfigFile path/to/nuget.config which contains your repository path.
For Example:
<configuration>
<packageSources>
<add key="Internal Nuget" value="\\srv-nuget\Repo" />
</packageSources>
</configuration>
If you are having trouble getting this to work on UWP ONLY, then ensure that you have the CASE of the package name spelt correctly. If the case is wrong, then (for UWP only) our build server fails the build.
for instance, if you have a package called Com.Company.Components and update the package using "install-package com.company.components" (note the case of the initial letter) then the UWP build on the build server may fail to find the package in your local store.
I've installed the Gradle plugin for Jenkins. When I try to build the project I get the following error:
[workspace] $ gradle clean -b build/build.gradle
FATAL: command execution failed
java.io.IOException: Cannot run program "gradle" (in directory "/Users/Shared/Jenkins/Home/jobs/test/workspace"): error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:460)
at hudson.Proc$LocalProc.<init>(Proc.java:244)
at hudson.Proc$LocalProc.<init>(Proc.java:216)
at hudson.Launcher$LocalLauncher.launch(Launcher.java:707)
at hudson.Launcher$ProcStarter.start(Launcher.java:338)
at hudson.Launcher$ProcStarter.join(Launcher.java:345)
at hudson.plugins.gradle.Gradle.performTask(Gradle.java:201)
at hudson.plugins.gradle.Gradle.perform(Gradle.java:97)
at hudson.tasks.BuildStepMonitor$1.perform(BuildStepMonitor.java:19)
at hudson.model.AbstractBuild$AbstractRunner.perform(AbstractBuild.java:695)
at hudson.model.Build$RunnerImpl.build(Build.java:178)
at hudson.model.Build$RunnerImpl.doRun(Build.java:139)
at hudson.model.AbstractBuild$AbstractRunner.run(AbstractBuild.java:465)
at hudson.model.Run.run(Run.java:1404)
at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:46)
at hudson.model.ResourceController.execute(ResourceController.java:88)
at hudson.model.Executor.run(Executor.java:238)
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)
at java.lang.ProcessImpl.start(ProcessImpl.java:91)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:453)
... 16 more
Build step 'Invoke Gradle script' changed build result to FAILURE
Build step 'Invoke Gradle script' marked build as failure
Finished: FAILURE
Running the task $ gradle clean -b build/build.gradle from the command line works as expected.
I had the same issue and found that the problem for me was the gradle version in the project configuration. It was set to Default and when I set it to the gradle version I was pointing to in the plugin configuration in the Manage Jenkins > Configuration Options, It found gradle and worked properly.
This is a difficult issue to debug and I hope this saves someone else some time.
Solution Mastering_the_Object pointed out worked form me too, just to clarify steps there:
just installing Gradle plugin in Jenkins is not enough, you must also go to:
Jenkins->Manage Jenkins->Configure Jenkins->Configure system.
Under "Gradle Installations" type in name (it appears as version in project configuration), check "Install automatically" and select version. Then you can select that "Gradle version" in project configuration.
I was getting this error using the Gradle wrapper, was able to fix my broken build as follows:
Go to Manage Jenkins -> Global Tool Configuration -> Gradle -> Add Gradle, give it a name
Go to Jenkins -> (your job) -> Configure -> Build, choose "Invoke Gradle" and change the Gradle version from (Default) to the named version
When running Gradle on a CI machine such as Jenkins, it's most convenient to use the Gradle Wrapper.
On your development machine, stand in your root project directory and run
gradle wrapper
Then, check in the resulting files into your source control system. After that, you don't have to install anything on your Jenkins server if you need to change Gradle versions. Just configure your Jenkins job like this:
Quoting from the Gradle User Guide:
By distributing the wrapper with your project, anyone can work with it
without needing to install Gradle beforehand. Even better, users of
the build are guaranteed to use the version of Gradle that the build
was designed to work with. Of course, this is also great for
continuous integration servers (i.e. servers that regularly build your
project) as it requires no configuration on the server.
The jenkins can not find the gradle executable. I have never made gradle wrapper to work. Please follow the following steps:
Download gradle ( http://gradle.org/downloads),
unpack it to, e.g., /usr/local/lib/gradle ,
open /etc/profile and add the following two lines:
export GRADLE_HOME=/usr/local/lib/gradle
export PATH=$PATH:$GRADLE_HOME/bin
It works for my jenkins installation.
ps. I answer this old question, because it is a common issue when setting up gradle with jenkins. I have spent some time trying to make the gradle wrapper work without success before.
Used both #Skarab & a number of other solutions here to get it to work.
Download gradle ( http://gradle.org/downloads),
unpack it to, e.g., /usr/local/lib/gradle ,
open /etc/profile and add the following two lines:
export GRADLE_HOME=/usr/local/lib/gradle
export PATH=$PATH:$GRADLE_HOME/bin
Then under Manage Jenkins > Configure system > Gradle, defined GRADLE_HOME and gave that gradle installation a name
Then, {this could be a bug} for the project, change gradle version from Default to the one I defined above
As others have noted, this is because Jenkins can't find the gradle executable.
None of the published solutions worked for me, but I was able to fix the problem by adding the gradle bin dir to the path set in the .bashrc for the build account on the build slave. Modifying the .profile failed, and setting PATH in the jenkins node configuration also failed.
Some posts will suggest setting the gradle path in the tools menu, but no gradle entry was available there either (perhaps due to regressions / design changes in the gradle plugin?).
In any case, the best test I found (short of running the build again and watching for failure) was to run env over ssh:
ssh <host> env
and check the PATH variable defined that way; if gradle isn't in that path, you probably won't be able to run it from jenkins.