Jenkins PER USER default parameter values? - jenkins

We are using a parameterized Jenkins build job, and I would like to have default values for some parameters specific for myself, e.g. the dev branch name I mostly use. Is it possible? We do have personal users in Jenkins.

You could do it by:
Create a scriptler which checks the current user and returns the appropriate value:
def user = jenkins.model.Jenkins.getAuthentication().getName();
def returnValue
switch (user) {
case ['user1','user2']:
returnValue = 'xyz'
break;
case ['user3']:
returnValue = 'abc'
break;
default:
returnValue = '00'
break;
}
return returnValue
If you want to use the Active Choices Plugin your script will need to return a list:
def user = jenkins.model.Jenkins.getAuthentication().getName();
def returnValue = [];
switch (user) {
case ['user1','user2']:
returnValue << 'xyz'
break;
case ['mtlelj']:
returnValue << 'abc'
break;
default:
returnValue << '00'
break;
}
return returnValue
Configure your parameterized build to have a Dynamic Parameter (Scriptler) or an Active Choices parameter and reference the script you created as it's source.
If you don't want a script centrally managed by admins, the Active Choices Parameter allows you to use the code within the parameter definition. I'm using:
Jenkins ver 2.32.3
Scriptler Plugin ver 2.9
Dynamic Parameter Plugin ver 2.9
Active Choices Plugin ver 2.9

Related

Custom Groovy function with arguments doesn't work in Jenkins pipeline

I'm using a function to set environment variables in Jenkins pipeline. I've noticed that if I declare function without argument, it works, but if I declare function that accepts 1 string argument, Jenkins throws error No such DSL method 'get_metadata' found among steps while running my pipeline.
def get_metadata(String type) {
switch(type) {
case "env":
return "environment name";
break;
case "domain":
return "domain name";
break;
case "cloud":
return "cloud name";
break;
default:
return "none";
break;
}
}
pipeline {
environment {
PROJECT=get_metadata()
CLOUD=get_metadata(type: "cloud")
DOMAIN=get_metadata(type: "domain")
ENVIRONMENT=get_metadata(type: "env")
}
}
Function without argument works when I call it like get_metadata()
def get_metadata() {
<...>
}
Jenkins version is 2.289.2.
Your get_metadata does not define a default value for type and therefore the call to PROJECT=get_metadata() throws an error, as you can't use it as is without passing the type parameter.
To solve it you can just add a default value to your function:
def get_metadata(String type = '') {
switch(type) {
case "env":
return "environment name";
case "domain":
return "domain name";
case "cloud":
return "cloud name";
default:
return "none";
}
}

Azure DevOps Server 2019 Programmatially copy test case error Exception: 'TF237124: Work Item is not ready to save'."

I'm able to copy most test cases with this code (trying to copy shared steps to be part of the test case itself) but this one will not copy but I can not see any error message as to why - could anyone suggest anything else to try. See output from Immediate windows. Thanks John.
?targetTestCase.Error
null
?targetTestCase.InvalidProperties
Count = 0
?targetTestCase.IsDirty
true
?targetTestCase.State
"Ready"
?targetTestCase.Reason
"New"
foreach (ITestAction step in testSteps)
{
if (step is ITestStep)
{
ITestStep sourceStep = (ITestStep)step;
ITestStep targetStep = targetTestCase.CreateTestStep();
targetStep.Title = sourceStep.Title;
targetStep.Description = sourceStep.Description;
targetStep.ExpectedResult = sourceStep.ExpectedResult;
//Copy Attachments
if (sourceStep.Attachments.Count > 0)
{
string attachmentRootFolder = _tfsServiceUtilities.GetAttachmentsFolderPath();
string testCaseFolder = _tfsServiceUtilities.CreateDirectory(attachmentRootFolder, "TestCase_" + targetTestCase.Id);
//Unique folder path for test step
string TestStepAttachementFolder = _tfsServiceUtilities.CreateDirectory(testCaseFolder, "TestStep_" + sourceStep.Id);
using (var client = new WebClient())
{
client.UseDefaultCredentials = true;
foreach (ITestAttachment attachment in sourceStep.Attachments)
{
string attachmentPath = TestStepAttachementFolder + "\\" + attachment.Name;
client.DownloadFile(attachment.Uri, attachmentPath);
ITestAttachment newAttachment = targetTestCase.CreateAttachment(attachmentPath);
newAttachment.Comment = attachment.Comment;
targetStep.Attachments.Add(newAttachment);
}
}
}
targetTestCase.Actions.Add(targetStep);
targetTestCase.Save();
}
Since this code works for most test cases, this issue may come from the particular test case. In order to narrow down the issue, please try the following items:
Run the code on another client machine to see whether it works.
Try to modify this particular test case using the account API uses, to see whether it can be saved successfully.
Try validate the WorkItem prior to save. The validate() method will return an arraylist of invalid fields.

Can admin role get other users permissions in Spring-security ACL Grails

I am trying to make a proof of concept application that allows the user with administration permission to grant and revoke permissions of other users. While granting and revoking works with only username (unique identifier) getting the permission to display in the UI proves to be out of my reach. Is it possible to get a list of other user's permissions from within a service method?
I've tried to search the web but I couldn't find any solution that would apply to my problem. I have tried using SwitchUserAuthorityChanger, RunAsManager and aclService.readAclsById. None of those worked.
I am using Grails 3.3.2 with Spring-Security 3.2.0 and ACL 3.2.0.
Cheers folks!
I ended up solving this myself. I'll post the answer here in case some poor soul would run into a similar problem.
After digging a bit in the ACL database tables, I created a separate service in which I get AclObjectIdentity by its id, I get users sid. Using these variables I find all related variables from AclEntry. After that its just a matter of getting permissions by their mask.
Here is the method in case it might help anyone:
def getPermissions(Object domainObject, String sid) {
Map<String, String> returnValue = [
"status": "success"
]
def aclObject = AclObjectIdentity.findByObjectId(domainObject.id)
def userAclSid = AclSid.findBySid(sid)
if (null == userAclSid || null == aclObject) {
returnValue["status"] = "failed"
return returnValue
}
def aclEntries = AclEntry.findAllBySidAndAclObjectIdentity(userAclSid, aclObject)
returnValue["permissions"] = []
def tempMap = [:]
if (null == aclEntries) {
returnValue["permissions"] = "null"
return returnValue
}
def counter = 0
for (entry in aclEntries) {
int mask = entry.mask
BasePermission permission
for (BasePermission perm in PermissionEnum.toList()) {
int test = 1 << mask
if (perm.getMask() == test) {
permission = perm
break;
}
}
def permString = PermissionEnum.getPermission(permission)
tempMap["$counter"] = permString
counter++
}
returnValue["permissions"] = tempMap
return returnValue
}

extract parameters from a jenkins previous build

I am working on Jenkins version 2.32.1 pipeline. I want to extract the parameters that were chosen in the previous build of my job.
In our previous Jenkins instance ( 1.627 ) we were using jenkins.model.Jenkins.instance.getItem(job).lastBuild.getBuildVariables().get(param);
For some reason this is not working in this version (I also tried disabling the sandbox).
Any pointers on how to accomplish it?
Simplified version of the previous script:
def build = Jenkins.get().getItems(org.jenkinsci.plugins.workflow.job.WorkflowJob).find {it.displayName == 'YOUR_JOB_NAME_HERE'}?.getLastBuild()
build.actions.find{ it instanceof ParametersAction }?.parameters.each {echo "${it.name}=${it.value}"}
Actually a little bit shorter version for those who want to get the params for the current build from the previous run and is working on new 2+ Jenkins versions.
To get 1 particular parameter:
def cls = currentBuild.getPreviousBuild().getRawBuild().actions.find{ it instanceof ParametersAction }?.parameters.find{it.name == 'cls'}?.value
Get all params respectfully:
def cls = currentBuild.getPreviousBuild().getRawBuild().actions.find{ it instanceof ParametersAction }?.parameters
Something like this might work, based on https://stackoverflow.com/a/19564602/3920342:
def h = hudson.model.Hudson.instance
def r = null
h.getItems(org.jenkinsci.plugins.workflow.job.WorkflowJob).each {project ->
if (project.displayName.equals('YOUR_JOB_NAME')) {
r = project
}
}
r.getBuilds().findAll { b -> // here we loop over all past builds, apply some filter if necessary
def p = b?.actions.find{ it instanceof ParametersAction }?.parameters
p.each {
echo "parameter ${it.name}: ${it.value}"
}
}
For those who are not able to access getActions() due to admin permissions i.e. facing the following error:
Scripts not permitted to use method hudson.model.Actionable getActions
They can copy the parameter variables to the env and get them using build.previousBuild.buildVariables
stage('Prepare environment') {
steps {
script {
env.MY_PARAM_COPY = "${MY_PARAM}"
}
}
}
println("MY_PARAM in previous build: ${currentBuild.previousBuild.buildVariables["MY_PARAM_COPY"]}")
That's how I made it works, answer from #dan.goriaynov and #jherb caused some CPS closure issues for me.
(the gist of the code is to allow only greater TAG number than the previous one to be deployed)
stage('Validate build number') {
def previous_build = currentBuild.getPreviousBuild().getRawBuild();
def PREVIOUS_TAG = '';
for (int i = 0; i < previous_build.allActions.size(); i++) {
if (previous_build.allActions[i] in hudson.model.ParametersAction) {
PREVIOUS_TAG = previous_build.allActions[i].getParameter("TAG").value
}
}
if (PREVIOUS_TAG.toInteger() > TAG.toInteger()) {
echo PREVIOUS_TAG
error('TAG number needs to be greater than the previous one')
}
}

Trigger Automated Test from Testrail to Ranorex

Anyone had also worked with TestRail(maybe by a click of a button) trigger automated test run in Ranorex and return the result/s back to testrail.
Would it be possible to share to us the steps you made and maybe a sample code.
Can you highlight how you run multiple test case in Ranorex.
Thanks!
I have used TestRails API binding for .NET (http://docs.gurock.com/testrail-api2/bindings-dotnet) for writing a simple C# file in Ranorex.
The idea is to have a test run with tests in TestRail and Ranorex posting to TestRail about the success of the test execution of these tests.
var testCase = TestCase.Current.Parameters["test_case"];
var runID = TestSuite.Current.Parameters["run_id"];
if (String.IsNullOrEmpty(testCase))
{
Report.Failure("Test case '" + TestCase.Current.Name + "' has no test case id defined !");
return;
}
if (String.IsNullOrEmpty(runID))
{
Report.Failure("Test suite '" + TestSuite.Current.Name + "' has no run id defined !");
return;
}
APIClient client = new APIClient("https://<your_server>");
client.User = "<user>";
client.Password = "<api_key>";
var data = new Dictionary<string, object>
{
{ "status_id", 1 }, // 1 = successful
{ "comment", "test case executed in Ranorex" }
};
JObject r = (JObject) client.SendPost("add_result_for_case/" + runID + "/" + testCase, data);
Ranorex.Report.Info(r.ToString());
This posts the result for one case to Ranorex (therefore the add_result_for_case method. The runID is a parameter I give in command line when I execute the suite and each test case in Ranorex corresponds to one test case in TestRail and must hold the test case id.
Take a look at http://docs.gurock.com/testrail-api2/start about what possibilities the TestRail api offers

Resources