Groovy script to list Jenkins projects and TFS project path - groovy

I am new to Jenkins, TFS and Groovy Script, but I have been researching and not found the exact way to do the following:
I would like to generate a list of all the Jenkins CI projects along with their TFS Project Path since the naming at my current company has been very inconsistent and I can't find which project in Jenkins CI correlates to which project in TFS without manually examining the project path in Jenkins.
I tried this, but it blows up since getProjectPath() isn't a method in Hudson.model.*
import hudson.model.*
jenkins = Hudson.instance
for (item in jenkins.items)
{
println item.getFullDisplayName()
println item.getProjectPath()
}
Any guidance would be appreciated. Thanks!

TFS's configuration located under SCM (Source Control Management) configuration section. To access it at first you need to get SCM with getScm() method:
import hudson.model.*
import hudson.plugins.tfs.TeamFoundationServerScm
jenkins = Hudson.instance
for (item in jenkins.items)
{
scm = item.getScm()
if (scm instanceof TeamFoundationServerScm) {
println item.getFullDisplayName()
println scm.getProjectPath()
}
}

Related

Azure function: Could not load file or assembly Microsoft.IdentityModel.Tokens, Version=5.2.1.0

Im writing an azure function to generate a JWT token and return it to the client. The code is tested locally in a console app and all seems to work fine. This is the package reference included in the working console app, and in my functions app:
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="5.2.1" />
When running the function host locally with func host start and executing the code it results in the error:
Could not load file or assembly 'Microsoft.IdentityModel.Tokens, Version=5.2.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'."
I don't understand why this is happening, the dll is laying in the output folder along with my application dll. The only other thing I can think of is that the function host has its own set of packages that it sources from and this one is not available yet, having been only released 12 days ago.
I'm not sure. Any help on why this is happening or how to get around it?
Details:
Azure Functions Core Tools (2.0.1-beta.22)
Function Runtime Version: 2.0.11415.0
I got this issue and it seems to be related to some kind of bug in the Azure function SDK. the fix was to add:
<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
to your csproj file. As documented here
I had installed this package Microsoft.AspNetCore.Authentication.JwtBearer
And for me, the issue was resolved.
You can uninstall System.IdentityModel.Tokens.Jwt
Because the Microsoft package depends on the system package, so it gets installed automatically.
I was able to solve this exact issue by using an older version of the nuget package. My starting point was that I had copied a class file from an old project to a new one. The class file referenced JwtSecurityToken. This did not compile in the new project, so I added Security.IdentityModel.Tokens.Jwt from nuget package manager. I just added latest version. This worked fine locally, but just like you, it failed when published to azure. I then looked at the old project and noticed that it was using 5.1.4 of that Security.IdentityModel.Tokens.Jwt. So, I downgraded to that version and it now works when published.
fwiw: this is the v2 preview runtime version at the time I did this.
https://<mysite>.azurewebsites.net/admin/host/status?code=<myadminkey>
{
"id": "<mysite>",
"state": "Running",
"version": "2.0.11587.0",
"versionDetails": "2.0.11587.0-beta1 Commit hash: 1e9e7a8dc8a68a3eff63ee8604926a8d3d1902d6"
}
tl;dr
None of the above worked for me and this would randomly happen from time to time until today it happened all the time. The only reason I could see was that Microsoft.IdentityModel.Tokens was not directly referenced in the executing project, but was on a referenced project. The library was sitting in the bin folder, it just wouldn't load.
Reference
Taking a clue from this solution to another problem I was able to resolve it like so:
Solution
Create a static constructor in the app's entry point class
static MainClass()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
Add the handler
private static System.Reflection.Assembly? CurrentDomain_AssemblyResolve(object? sender, ResolveEventArgs args)
{
var domain = sender as AppDomain;
var assemblies = domain.GetAssemblies();
foreach(var assembly in assemblies)
{
if (assembly.FullName.IsEqualTo(args.Name))
{
return assembly;
}
}
var folder = AppDomain.CurrentDomain.BaseDirectory;
var name = args.GetLibraryName().Name.Split(Symbols.Comma).FirstOrDefault();
var library = $"{name}.dll";
var file = Path.Combine(folder, library);
if (File.Exists(file))
{
return Assembly.LoadFrom(file);
}
return null;
}

Deploying to a private IIS server from a build in Visual Studio Team Services

Having done what is suggested here: Deploy from Visual Studio Online build to private IIS server
... how do I setup automatic deploys as part of my build when I build a whole branch **/*.sln?
What I have tried ...
In VS I can get the latest version of the code, open a solution and then ...
right click > publish > pick publish profile > deploy
I have named my publish profiles things like "dev", "qa", "production", these refer to the environments into which the project will be deployed and the profiles contain all of the configuration information needed for VS to deploy (via webdeploy / msdeploy) using "one click deploy" that application.
I want to have Team Services on the build server do the exact same thing for projects that have publish profiles defined after it's built the code.
My understanding was that I could just add the msbuild args like this ...
this results in the deployment part of the build throwing the following exception in to the build log ...
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets(4288,5):
Error ERROR_USER_NOT_ADMIN: Web deployment task failed.
(Connected to 'server' using the Web Deployment Agent Service, but could not authorize. Make sure you are an administrator on 'server'.
Learn more at: http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_USER_NOT_ADMIN.)
What user is this using if not the user defined in the publish profile?
Related issues:
Publishing via TFS Build Service fails with "User not Admin"
TFS Builds: Running the builds as administrator
I added an account to the server in question (since the build and server to be deployed to are the same server it made things easier), I also added a group to the server called "MSDepSvcUsers" and added the new account in question to it and the admins group on the box.
I then told both the Web Deployment Agent service and the Team Services Agent service to run under this account (and restarted them).
Unfortunately the result is the same ... I now really want to know how I go about ensuring the account that is used for the msdeploy command is something I expect without relying on loads of scripting ... or maybe that's why Microsoft haven't set this up as a default deploy step option in Team Services already!
Ok so I had some long conversations with the VSTS team over at Microsoft about this and the long and short of it is ...
Microsoft:
We understand your frustration with this area and a big project is
about to spin up to resolve this issue
...
Me being me, came up with some "trick to make it happen".
I managed to figure out that the build box for some odd reason can't be the same server that you are deploying too (no idea why) but having figured that out I wrote a simple console app that with some additional feedback from Microsoft came out pretty good.
It even reports progress back to the process and can log exceptions in the deployment as exceptions in order to fail the build by calling up "internal commands" (neat how this works by the way kudos to the team for that).
There are some hacks in here and it's not perfect but hopefully it'll help someone else, I call this because it's part of the code that gets built in my repo so I am able to add a step in to the build process to call this from within the build output passing the environment name I want to deploy to.
This in tern grabs all the packages (as per the settings above) and uses their publish profiles to figure out where the packages need to go and sends them to the right servers to be deployed ...
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
namespace Deploy
{
class Program
{
static string msDeployExe = #"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe";
static void Main(string[] args)
{
var env = args[0];
var buildRoot = Path.Combine(Assembly.GetExecutingAssembly().Location.Replace("Deploy.exe", ""), env);
//var commands = GetCommands(buildRoot);
var packages = new DirectoryInfo(buildRoot).GetFiles("*.zip", SearchOption.AllDirectories);
bool success = true;
for (int i = 0; i < packages.Length; i++)
{
if (!Deploy(packages[i], env)) success = false;
Console.WriteLine("##vso[task.setprogress]" + (int)(((decimal)i / (decimal)packages.Length) * 100m));
}
Console.WriteLine("##vso[task.setprogress]100");
if(success) Console.WriteLine("##vso[task.complete result=Succeeded]");
else Console.WriteLine("##vso[task.complete result=SucceededWithIssues]");
}
static bool Deploy(FileInfo package, string environment)
{
bool succeeded = true;
Console.WriteLine("Deploying " + package.FullName);
var procArgs = new ProcessStartInfo
{
FileName = msDeployExe,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
Arguments =
"-source:package='" + package.FullName + "' " +
"-dest:auto,ComputerName='" + environment + ".YourDomain.com',UserName='deployment user',Password='password',AuthType='ntlm',IncludeAcls='False' " +
"-verb:sync " +
"-disableLink:AppPoolExtension " +
"-disableLink:ContentExtension " +
"-disableLink:CertificateExtension " +
"-setParamFile:\"" + package.FullName.Replace("zip", "SetParameters.xml") + "\""
};
try
{
Console.WriteLine(msDeployExe + " " + procArgs.Arguments);
using (var process = Process.Start(procArgs))
{
var result = process.StandardOutput.ReadToEnd().Split('\n');
var error = process.StandardError.ReadToEnd();
process.WaitForExit();
if (!string.IsNullOrEmpty(error))
{
Console.WriteLine("##vso[task.logissue type=error]" + error);
succeeded = false;
}
foreach (var l in result)
if (l.ToLowerInvariant().StartsWith("error"))
{
Console.WriteLine("##vso[task.logissue type=error]" + l);
succeeded = false;
}
else
Console.WriteLine(l);
}
}
catch (Exception ex) {
succeeded = false;
Console.WriteLine("##vso[task.logissue type=error]" + ex.Message);
Console.WriteLine("##vso[task.logissue type=error]" + ex.StackTrace);
}
return succeeded;
}
}
}
No you don't need a ton of PS scripts to achieve this. MSDeploy.exe is an incredibly useful tool that can probably cover your needs. Add the /t:Package build argument to your VS build task to create a package. Then use a Commandline task to deploy the MSDeploy package to your IIS site. Here are more details about out WebDeploy/MSDeploy works:
http://www.dotnetcatch.com/2016/02/25/the-anatomy-of-a-webdeploy-package/
I do this all of the time. What I did was setup a Release in the Release tab and signed up to enable Deployment Groups. Once you have a the Deployment Group enabled on your account (needed contact MS to get this enabled). I could download PS script that I run on each of the machines that I want to deploy to. Then in the Release screen I can setup the steps to run in a Deployment Group and then the various publish tasks run on the local server allowing them to work.
Using the Deployment Groups is an excellent solution because if you have it load balanced it will deploy to only a portion of the load balanced servers at a time. Allowing the app to stay up the whole time.

How to rename a project in SonarQube 5.1?

I can't find how to rename a project in SonarQube 5.1.
Once created, how one can change project name, key, branch, from the web dashboard?
SonarQube's documentation doesn't help.
In SonarQube 5.1 the project name can't be changed from the web dashboard (Probably it will not be possible in the future as well).
I configure my SonarQube projects sonar-project.properties where I only have to change this line:
sonar.projectName=MyNewProjectName
Rerun the analysis to see the result in the web dashboard.
You need to "update the project key" (I always think that the Sonar terminology here isn't very helpful)
https://docs.sonarqube.org/display/SONAR/Project+Settings#ProjectSettings-UpdatingProjectKey
and then re-run the analysis (with the new project key, so having updated your sonar-project.properties or build.xml or pom.xml, etc)
To change the projet name in UI run this SQL query :
UPDATE sonar.projects
SET name = 'NEW_PROJECT_NAME',
long_name = 'NEW_PROJECT_NAME'
WHERE kee = 'PROJECT_KEY'
If you are using jenkins and your sonar build is a post build step. You may add the property mentioned by #adrianko to your goals.
$SONAR_MAVEN_GOAL -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_AUTH_TOKEN -Dsonar.projectName="YOUR PROJECT NAME"
In SonarQube 8.6 (PostgreSQL), execute SQL
UPDATE projects
SET name = 'NEW_PROJECT_NAME'
WHERE kee = 'PROJECT_KEY';
UPDATE components
SET "name" = 'NEW_PROJECT_NAME',
long_name = 'NEW_PROJECT_NAME'
WHERE kee = 'PROJECT_KEY';
CREATE PROCEDURE usp_ChangeProjectName
#CaseSensitiveProjectKeyToChange VARCHAR(300),
#NewProjectName VARCHAR(300)
AS
BEGIN
SET NOCOUNT ON;
IF (SELECT COUNT(*) FROM dbo.projects WHERE kee = #CaseSensitiveProjectKeyToChange and scope = 'PRJ') > 1
BEGIN
RAISERROR ('Operation would affect more than one record, cancelling for safety.', 16, 1)
END
UPDATE
dbo.projects
SET
name = #NewProjectName,
long_name = #NewProjectName
WHERE
kee = #CaseSensitiveProjectKeyToChange and
scope = 'PRJ'
END
GO
Sample Usage usp_ChangeProjectName2 '<project key>', '<new name>'
Just add or edit gradle.properties file as below:
org.gradle.java.home=C\:\\Program Files\\Java\\jdk1.8.0_191
org.gradle.jvmargs=-Xmx1536m
systemProp.sonar.host.url=https://abc.xyz.com
#----- Token generated from an account with 'publish analysis' permission
systemProp.sonar.login=your token goes here
systemProp.sonar.projectName=ProjectName
Please change the path of JDK as per your system configuration, sonarqube server url, access token and finally the name of project that you want to give. By default in android studio project name is app
Just let me know if anybody face any problem while integration of sonarqube.
I tried all the way but it did not work for me . At last my bamboo server gave me some hint .
Instead of using projectName pror you can use "/n:" key..
i.e /n:"your project name".
There is no possibility to rename the project in the web frontend (tested with Sonarqube V 9.3).
But you can change the project name by running the sonar scanner commandline interface locally and passing the new project name (also the sonar token and the project key) as parameter
(If sonar-scanner is started in the same directory in which sonar-project.properties is located, the properties are also read from this file):
sonar-scanner -Dsonar.projectName="enter_new_projectname_here“ -Dsonar.login="your_sonar_token“ -Dsonar.projectKey="your_project_key“
On macOS the sonar scanner can be installed with homebrew:
brew install sonar-scanner
For other platform see https://github.com/SonarSource/sonar-scanner-cli

Jenkins Java: How to get the userid of the user who triggered the build in jenkins

Is there a way to find out who started a build in jenkins using java. I understand that below is the approach for figuring out as to who started a build
import hudson.model.*
import jenkins.security.*
def userBuild
for(hudson.model.Cause cause : build.causes) {
userBuild = cause.getUserName()
}
println "Build Started by: "+userBuild
Likewise, can someone please let me know if there is a similar working way to figure out as to who initiated a jenkins build?
Ther is a Plugin that injects the informations in Build Variables.
https://wiki.jenkins-ci.org/display/JENKINS/Build+User+Vars+Plugin
BUILD_USER – full name of user started build,
BUILD_USER_FIRST_NAME – first name of user started build,
BUILD_USER_LAST_NAME – last name of user started build,
BUILD_USER_ID – id of user started build.
Maybe this is an option for you.
Was able to figure it out on my own. Added the below changes in buildCaption.jelly so that only the user who started the build will be able to abort the build. Mind that this change only gets reflected in the console-output of a build, but there are other places(such as jenkins landing page and job home page) where the abort button gets displayed and will have to make the changes accordingly
<j:forEach var="cause" items="${it.causes}">
<j:if test="${cause.userName == it.currentlyLoggedInUser}">
<l:stopButton href="stop" alt="[${%cancel}]"/>
</j:if>
</j:forEach>

Create #extension class in Groovy on Jenkins?

I'm using the Groovy script screen in jenkins, ie http://localhost:8080/jenkins/script , which is very awesome. I wrote a simple Extension:
jenkins = jenkins.model.Jenkins.getInstance()
#hudson.Extension
public class MyGroovyListener extends hudson.slaves.ComputerListener {
public void onOnline( computer, taskListener ) {
System.out.println("groovy onOnline " + computer + " " + taskListener );
}
}
Now I want to get the extension registered somehow. I tried:
jenkins.refreshExtensions()
... but no joy.
How can I go about registering an extension class from the groovy script webpage?
You need to do a little more to build a Jenkins plugin
You can build them in groovy but it needs to be in a HPI (specialised JAR file) - which you load via the plugin screen. You will need gradle, gent and the example as built by Kiyotaka.
https://github.com/kiy0taka/jenkins-plugin.gent
gent --name=<proj> kiy0taka/jenkins-plugin
cd <proj>
./gradlew server
The gradlew step will run up a local Jenkins server with the plugin ready loaded
There is more as you need to build form components for the configuration and build design step
and also handle serialising config data
This was answered better in the Google Groups post by the same poster, though it may be outdated now. The mentioned issue GROOVY-3361 still exists, and appears to limit how annotations can be processed and scanned for in Groovy classes.
It's a real shame you can't register things against extension points with Groovy code in Jenkins.
I still wonder if it may be possible with a custom hudson.ExtensionFinder, which itself must be written in Java. But I haven't the time to dig that far.

Resources