Is there a way to figure out what file in GiHub causes the build in Jenkins - github

I currently set up Jenkins and GitHub so that when a push is sent to GitHub a build is automatically triggered. Is there a way to get the name of the file that causes the build. For example, if I have a file in GitHub named test.txt in a repo called TestRepo and I commit a change in test.txt, how could I figure out the build was caused by a change in test.txt and not due to another file in the repo.

Assuming you are using the GitHub plugin for polling, the build will be triggered by a commit/s not by a specific file. You can see the changes log directly in Jenkins in 'Changes' tab or if you need to get the list of files in the pipeline you can try to have a step with something like 'git diff --name-only $GIT_PREVIOUS_COMMIT $GIT_COMMIT' after the checkout step.

You can use the following Groovy script to get the files changed. You can simply retrieve the changeset with currentBuild.changeSets and process the changeset as shown below to get the files that changed.
pipeline {
agent any
stages {
stage('Build') {
steps {
git (url: 'https://github.com/xxxx/sample.git', branch: 'main')
script {
def changedFiles = getFilesChanged()
echo "${changedFiles}"
}
}
}
}
}
def getFilesChanged() {
def filesList = []
def changeLogSets = currentBuild.changeSets
for (int i = 0; i < changeLogSets.size(); i++) {
def entries = changeLogSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
def files = new ArrayList(entry.affectedFiles)
for (int k = 0; k < files.size(); k++) {
def file = files[k]
filesList.add(file.path)
}
}
}
return filesList
}

Related

Jenkins checking change in repository before build

I am using a monorepo for my microservices and i have a pipeline for each service.I have a webhook that notifies jenkins whenever a change is made in the repository. So the problem now is i want to check a particular folder in the repository if there is a change before some operations. Thanks
Solution 01 Processing the Webhook Request
When the Webhook notifies Jenkins it will send a bunch of details to Jenkins. Including the change logs. You should be receiving the below details. So as the initial step you can process the details coming from Github and determine whether the folder you are looking for is changed.
"added": [ ],
"removed": [ ],
"modified": ["test/testfile.yaml"]
You can use this as a reference.
Solution 02 without Processng the Webhook
It seems you cannot get this done with a simple pattern matching as directory name checking is not supported at the moment. But as a workaround, you can use something like the below. You can specify the directory name you want to check as folderName = "DIR_NAME"
pipeline {
agent any
stages {
stage('Cloning') {
steps {
// Get some code from a GitHub repository
git branch: 'main', url: 'https://github.com/yasassri/sample.git'
}
}
stage('Example Deploy') {
when { expression {
def changeLogSets = currentBuild.changeSets
def folderName = "testdir2"
for (int i = 0; i < changeLogSets.size(); i++) {
def entries = changeLogSets[i].items
for (int j = 0; j < entries.length; j++) {
def entry = entries[j]
def files = new ArrayList(entry.affectedFiles)
for (int k = 0; k < files.size(); k++) {
def file = files[k]
if(file.path.contains(folderName)){
return true
}
}
}
}
return false
}
}
steps {
echo 'Deploying==================='
}
}
}
}
References: https://support.cloudbees.com/hc/en-us/articles/217630098-How-to-access-Changelogs-in-a-Pipeline-Job-

Defining closures in a loop - how to prevent a variable mutating

I have the following workflow code:
stage "Deploy to Prod Sites"
def branches = [:]
for (i=0; i< sites.size(); i++) {
site=sites[i]
echo "site = $site"
branches[site] = {
buildJob (app, site, revision)
}
}
parallel branches
When I run this, each branch has the same value for site.
How do I ensure that the value of site contains the value from when the closure was defined rather than run?
the answer is def site
so
stage "Deploy to Prod Sites"
def branches = [:]
for (i=0; i< sites.size(); i++) {
def site=sites[i]
echo "site = $site"
branches[site] = {
buildJob (app, site, revision)
}
}
parallel branches
This now works as expected.

finding "active" branch in EGIT repository

I have to modify a faulty program/feature, which is an extension to org.eclipse.jgit
the program overrides the close method of the PushResultDialog and passes the Repository to an method.
Here i want to find the branch which was actually pushed/checked out. I am only interested if its the master, if not i don't wanna do anything.
else i need the list of the pushed files.
First the program looked like this :
head = repo.resolve(Constants.HEAD);
RevCommit commit = rw.parseCommit(head);
PersonIdent committerIdent = commit.getCommitterIdent();
sCommitter = committerIdent.getName();
String sBranch = "?";
for (Map.Entry<String, Ref> e : repo.getAllRefs().entrySet()) {
if (e.getKey().startsWith(Constants.R_HEADS)) {
Ref ref = e.getValue();
if (rw.isMergedInto(commit, rw.parseCommit(ref.getObjectId()))) {
sTemp = ref.getName();
int i = sTemp.lastIndexOf('/');
if (i == -1)
continue;
sBranch = sTemp.substring(i + 1);
System.out.println("Ref " + sBranch
+ " < contains > " + commit);
if (sBranch.equalsIgnoreCase("master")) {
break;
} else {
return;
}
}
}
}
RevCommit parent = rw.parseCommit(commit.getParent(0).getId());
DiffFormatter df = new DiffFormatter(
DisabledOutputStream.INSTANCE);
df.setRepository(repo);
df.setDiffComparator(RawTextComparator.DEFAULT);
df.setDetectRenames(true);
List<DiffEntry> diffs = df.scan(parent.getTree(),
commit.getTree());
for (DiffEntry diff : diffs) {
sTemp = diff.getNewPath();
pushedObjects.add(sTemp);
}
now .. this works as long as the workflow in eclipse is just "checkout master" "pull" "merge branch" "push"
any other order seems to mess with the order of the branches in the set, and it stumbles over this "else" :
if (sBranch.equalsIgnoreCase("master")) {
break;
} else {
return;
}
the question is : is there an eaasy method to pick the right branch?
Ok, i think i can simply look at the HEAD in the set:
e.getKey().startsWith(Constants.HEAD)
and then parse the branchname, that should always be the branch which is checked out, if (in my case),if it is the master, i am happy.

Project Browser not updating with Package Deletion Script

The following method deletes a package. The problem is that the Project Browser is never refreshed. Calling Repository.RefreshModelView(0) forces the update, but it reopens the model and kills script execution.
Here is the method:
function clearPackage( pkg ) {
var parent as EA.Package;
parent = Repository.GetPackageByID(pkg.ParentID);
var pkgList as EA.Collection;
pkgList = parent.Packages;
for (var i = 0; i < pkgList.Count; i++) {
var p as EA.Package;
p = pkgList.GetAt(i);
if (p.PackageGUID == pkg.PackageGUID) {
pkgList.Delete(i);
pkgList.Refresh();
parent.Update(); // have tried with and without
return;
}
}
}
Inspecting pkgList.Count before and after pkgList.Refresh does show a change in size. Again, the problem seems limited to the Project Browser.
Any ideas on how to refresh the Project Browser?
Cross posted on Sparx Forums.
To delete a package you just need to delete the package itself. Sorry for the Perl, but thats my donkey :-)
my $p = $rep->GetTreeSelectedObject();
my $par = $rep->GetPackageByID ($p->ParentID);
my $idx = 0;
for my $sp (in $par->Packages) {
if ($sp->PackageID == $p->PackageID) {
$par->Packages->DeleteAt ($idx, 1);
last;
}
$idx++;
}
$rep->RefreshModelView ($par->PackageID);
Try
Repository.RefreshModelView(parent.PackageID);
That will refresh only the contents of the parent package, not the whole model.

Clearing special permissions from folders in a branch

We're a fairly large project with a single trunk branch. Most of it uses the default permissions, but a few folders have custom permissions - say, only "Builders" group is allowed to check-in.
We want to allow people to create their own private branches out of trunk, where they can freely check-in and merge later (hopefully often). However, creating a branch, the special permissions are copied along with the folders, meaning that people can't freely check-in into their branch.
Is there a way to clear special permissions from a branch, or a folder?
Is there a way to do so automatically, so anyone creating a branch under /private/** will not encounter this problem?
I found out about tf permission (Example: tf permission /inherit:yes itemSpec). However, the /recursive switch doesn't work with it. I guess I could write something that runs it recursively...
Edit: I finally got around to writing a tool for it:
static int Main(string[] args)
{
if (args.Length == 0 || args.Any(a => !a.StartsWith("$/")))
{
Console.WriteLine("Removes all explicit permissions and enables inheritance for a subtree.\n"
+ "Example: " + Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().Location) + " $/project/path1 $/project/path2");
return 3;
}
WorkspaceInfo wi = Workstation.Current.GetLocalWorkspaceInfo(Environment.CurrentDirectory);
if (wi == null)
{
Console.WriteLine("Can't determine workspace for current directory: " + Environment.CurrentDirectory);
return 2;
}
var Tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(wi.ServerUri);
VersionControlServer VersionControlServer = Tfs.GetService<VersionControlServer>();
Console.WriteLine("Server: {0} Getting permissions...", wi.ServerUri);
ItemSecurity[] perms = VersionControlServer.GetPermissions(args, RecursionType.Full);
Console.WriteLine("Will remove explicit permissions from the following items:");
var changes = new List<SecurityChange>();
foreach (ItemSecurity perm in perms)
{
Console.WriteLine(" " + perm.ServerItem);
changes.Add(new InheritanceChange(perm.ServerItem, inherit: true));
foreach (AccessEntry e in perm.Entries)
{
changes.Add(new PermissionChange(perm.ServerItem, e.IdentityName, null, null, PermissionChange.AllItemPermissions));
}
}
Console.WriteLine("Enter to confirm:");
Console.ReadLine();
var successfulchanges = VersionControlServer.SetPermissions(changes.ToArray());
if (successfulchanges.Length == changes.Count)
{
Console.WriteLine("Explicit permissions removed from all items");
return 0;
}
else
{
Console.WriteLine("Explicit permissions removed only from:");
foreach (var c in successfulchanges)
{
Console.WriteLine(" " + c.Item);
}
return 1;
}
}