Jenkins checking change in repository before build - github

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-

Related

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

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
}

How to add a line to a google spreadsheet via email?

I need a google apps script which can do the following:
if I send an email to my alias email, say to myemail+expenses#gmail.com, it adds a line in a specific google spreadsheet with data from that email. E.g. timestamp, subject, the first line of a body - whatever.
I found interesting article describing similar process of sending data to google spreadsheet.
May be there is no any direct way of doing that, however, it should exist some workaround.
P.S. It should be done only by using a google echosystem. No php, servers etc.
There are two step for this.
#1
At first create a trigger to run the mail checker.
function switchTrigger() {
var isExist = false;
var triggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < triggers.length; i++) {
if ( /*<CONDITION>*/ ) {
isExist = true;
ScriptApp.deleteTrigger(triggers[i]);
}
}
if (!isExist) {
ScriptApp.newTrigger( /*<CONDITION>*/ ).create();
Logger.log('create');
}
}
#2
Then you have to check emails. Something like that
function checkMail() {
var sh = SpreadsheetApp.openById(properties.targetSheetId).getSheets()[0];
var query = /* properties.queryString */ ;
var threads = GmailApp.search(query);
if (threads.length < 1) return;
for (var i = 0; i < threads.length; i++) {
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
if (messages[j].isStarred()) {
sh.appendRow([
new Date(),
messages[j].getFrom(),
messages[j].getPlainBody()
]);
messages[j].unstar();
}
}
}
}
Be careful. You have to set up Gmail filters so that all incoming to myemail+expenses#gmail.com would be marked with an star at the beginning.
Working Example

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.