Fixing refused to display URL in a frame because it set X-Frame-Options to SAMEORIGIN – Jenkins

If you are trying to embed Jenkins page in another page then you might get following exception:

Refused to display http://localhost:8080/jenkins in a frame because it set ‘X-Frame-Options’ to ‘SAMEORIGIN’

It’s refused because X-Frame-Options HTTP response header is set to SAMEORIGIN to avoid clickjacking attacks, by ensuring that content cannot embedded into other sites.

If you are facing the same problem as me then you can fix it restarting the Jenkins setting the system property -Djenkins.security.FrameOptionsPageDecorator.enabled as false from Jenkins 1.581, as follows:


java -Djenkins.security.FrameOptionsPageDecorator.enabled=false -jar jenkins.war

Along with setting the ALLOW-FROM uri in a page where you want to embed Jenkins page.

Permission denied executing shell script on remote host using ssh – Jenkins

Today I was setting up a Jenkins pipeline for one of my project and noticed deploy job fails every time it try to execute the script on a remote Linux machine stating the reason – “Build step ‘Execute shell script on remote host using ssh’ marked build as failure”, as follows:

executing script:

./stage-deployment/scripts/stage-node_deploy.sh
bash: line 1: ./stage-deployment/scripts/stage-node_deploy.sh: Permission denied
[SSH] exit-status: 126
Build step 'Execute shell script on remote host using ssh' marked build as failure

If you are facing the same problem as me then you can fix it after changing the permissions of a directory containing executable, as:

chmod --recursive a+rwx /stage-deployment/scripts/

Writing Post Build Jenkins Plugin

In previous post we learnt how to write Writing Build Phase Jenkins Plugin, now in this article we will learn how to write a Jenkins CI Plugin that executes post build process. The complete source code is hosted on github post-build-jenkins-plugin

Step 1: Edit the settings.xml in .m2 directory or if it is not there create it with below content:

<settings>
 <pluginGroups>
 <pluginGroup>org.jenkins-ci.tools</pluginGroup>
 </pluginGroups>
 <profiles>
 <profile>
 <id>jenkins</id>
 <activation>
 <activeByDefault>true</activeByDefault>
 </activation>
 <repositories>
 <repository>
 <id>repo.jenkins-ci.org</id>
 <url>http://repo.jenkins-ci.org/public/</url>
 </repository>
 </repositories>
 <pluginRepositories>
 <pluginRepository>
 <id>repo.jenkins-ci.org</id>
 <url>http://repo.jenkins-ci.org/public/</url>
 </pluginRepository>
 </pluginRepositories>
 </profile>
 </profiles>
</settings>

Step 2:  Create a Maven project and edit the pom.xml as:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
 <groupId>org.jenkins-ci.plugins</groupId>
 <artifactId>plugin</artifactId>
 <version>1.580.1</version>
 <relativePath />
 </parent>
 <groupId>com.jenkins</groupId>
 <artifactId>post-build-jenkins-plugin</artifactId>
 <packaging>hpi</packaging>
 <version>0.0.1</version>
 <name>Email Plugin</name>
 <url>http://wiki.jenkins-ci.org/display/JENKINS/post-build-jenkins-plugin</url>
 <dependencies>
 </dependencies>
 <build>
 <finalName>post-build-jenkins-plugin</finalName>
 </build>
</project>

Step 3: Create a folder under src/main/java for me it’s com.jenkins.publisher and copy the EmailPublisher java class with below content inside it:

package com.jenkins.publisher;

import hudson.Extension;
import hudson.Launcher;
import hudson.model.BuildListener;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.BuildStepMonitor;
import hudson.tasks.Notifier;
import hudson.tasks.Publisher;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import net.sf.json.JSONObject;

import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

public class EmailPublisher extends Notifier {

 private final String emailId;
 
 private static Properties properties = new Properties();
  static {
   properties.put("mail.smtp.auth", "true");
   properties.put("mail.smtp.starttls.enable", "true");
   properties.put("mail.smtp.host", "smtp.gmail.com");
   properties.put("mail.smtp.port", "587");
  }

 @DataBoundConstructor
 public EmailPublisher(final String emailId) {
  this.emailId = emailId;
 }

 public String getEmailId() {
  return emailId;
 }

 @Override
 public boolean perform(
 @SuppressWarnings("rawtypes") final AbstractBuild build,
 final Launcher launcher, final BuildListener listener) {
 // logic to be executed by plugin
 try {
 // logger which prints on job 'Console Output'
 listener.getLogger().println("Starting Post Build Action");
  sendMail();
 } catch (Exception e) {
 listener.getLogger().printf("Error Occurred : %s ", e);
 }
 listener.getLogger().println("Finished Post Build Action");
  return true;
 }

 @Override
 public DescriptorImpl getDescriptor() {
  return (DescriptorImpl) super.getDescriptor();
 }

 @Extension
 public static class DescriptorImpl extends BuildStepDescriptor<Publisher>   {

 /**
 * Global configuration information variables. If you don't want fields
 * to be persisted, use <tt>transient</tt>.
 */
 private String username;
 private String password;

 public String getUsername() {
  return username;
 }

 public String getPassword() {
  return password;
 }

 /**
 * In order to load the persisted global configuration, you have to call
 * load() in the constructor.
 */
 public DescriptorImpl() {
  load();
 }

 @Override
 public boolean configure(StaplerRequest req, JSONObject formData)
 throws FormException {
 
 // To persist global configuration information, set that to
 // properties and call save().
 username = formData.getString("username");
 password = formData.getString("password");
 save();
  return super.configure(req, formData);
 }

 @Override
 public boolean isApplicable(
 @SuppressWarnings("rawtypes") Class<? extends AbstractProject> jobType) {
  // Indicates that this builder can be used with all kinds of project 
  // types.
  return true;
 }

 @Override
 public String getDisplayName() {
  return "Send Email";
 }
 }

 public BuildStepMonitor getRequiredMonitorService() {
 return BuildStepMonitor.NONE;
 }

 private void sendMail() throws Exception {
  final String username = getDescriptor().getUsername();
  final String password = getDescriptor().getPassword();
 
  Session session = Session.getInstance(properties,
   new javax.mail.Authenticator() {
     protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(username, password);
   }
 });
 
 Message message = new MimeMessage(session);
 
  message.setFrom(new InternetAddress("aggarwalarpit.89@gmail.com"));
  message.setRecipients(Message.RecipientType.TO,
  
  InternetAddress.parse(emailId));
   message.setSubject("Jenkins Post Build Mail");
   message.setText("Jenkins Post Build Mail");

 Transport.send(message);
 }
}

Step 4: Create a index.jelly file under src/main/resources folder and copy the below content to it:

<?jelly escape-by-default='true'?>
<!-- This view is used to render the installed plugins page. -->


<div>
 This plugin send mail post build.
</div>


Step 5: Create a folder with same name as of Java class under src/main/resources/ in my case it’s
com/jenkins/publisher/EmailPublisher and then create config.jelly, global.jelly, help-emailId.html, help-username.html and help-password.html inside it with below content:

config.jelly

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form"> 
 <!-- Creates a text field that shows the value of the "emailId" property. When submitted, it will be passed to the corresponding constructor parameter. -->
 <f:entry title="Email Id" field="emailId">
 <f:textbox />
 </f:entry>
</j:jelly>

global.jelly

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
 <!-- This Jelly script is used to produce the global configuration option. -->
 <f:section title="Email Publisher">
 <f:entry title="Username" field="username">
 <f:textbox />
 </f:entry>
 <f:entry title="Password" field="password">
 <f:textbox />
 </f:entry>
 </f:section>
</j:jelly>

help-emailId.html

<!-- Help file for fields are discovered through a file name convention. This file is help for the "emailId" field. -->


<div>Specify the email id to which mail to be sent. For example,
 you can specify as aggarwalarpit.89@gmail.com
</div>


help-username.html

<!-- This HTML fragment will be injected into the configuration screen when the user clicks the 'help' icon of filed 'username'. -->


<div>Specify the username of gmail account from which mail to be
 sent. For example, you can specify as aggarwalarpit.89@gmail.com
</div>


help-password.html

<!-- This HTML fragment will be injected into the configuration screen when the user clicks the 'help' icon of filed 'password'. -->


<div>Specify the password of gmail account from which mail to be
 sent. For example, you can specify as password@gmail
</div>


After performing all the above steps, your project structure should look like as:

Post Build Jenkins Plugin Project Structure

Step 6: Compile and package the plugin:

$ cd post-build-jenkins-plugin
$ mvn package

After packaging the plugin you should find a .hpi file in the target folder.

Writing Build Phase Jenkins Plugin

While integrating the build process of my project with Jenkins, I was looking for a way to copy the static content from my local directory to job workspace so I can leverage it at time of build process, which I thought of sharing to encourage you as well to write your own Jenkins plugins and share them with the community.

In this article we will learn how to write a Jenkins CI Plugin that executes as part of a Build process. The complete source code is hosted on github build-phase-jenkins-plugin

Step 1: Edit the settings.xml in .m2 directory or if it is not there create it with below content:

<settings>
 <pluginGroups>
 <pluginGroup>org.jenkins-ci.tools</pluginGroup>
 </pluginGroups>
 <profiles>
 <profile>
 <id>jenkins</id>
 <activation>
 <activeByDefault>true</activeByDefault>
 </activation>
 <repositories>
 <repository>
 <id>repo.jenkins-ci.org</id>
 <url>http://repo.jenkins-ci.org/public/</url>
 </repository>
 </repositories>
 <pluginRepositories>
 <pluginRepository>
 <id>repo.jenkins-ci.org</id>
 <url>http://repo.jenkins-ci.org/public/</url>
 </pluginRepository>
 </pluginRepositories>
 </profile>
 </profiles>
</settings>

Step 2: Create a Maven project and edit the pom.xml as:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
 <groupId>org.jenkins-ci.plugins</groupId>
 <artifactId>plugin</artifactId>
 <version>1.580.1</version>
 <relativePath />
 </parent>
 <groupId>com.jenkins</groupId>
 <artifactId>copy-files-jenkins-plugin</artifactId>
 <packaging>hpi</packaging>
 <version>0.0.1</version>
 <name>Copy Files To Workspace Plugin</name>
 <url>http://wiki.jenkins-ci.org/display/JENKINS/copy-files-jenkins-plugin</url>
 <dependencies>
 </dependencies>
 <build>
 <finalName>copy-files-jenkins-plugin</finalName>
 </build>
</project>

Step 3: Create a folder under src/main/java for me it’s com.jenkins.builder and copy the CopyFilesBuilder java class with below content inside it:

package com.jenkins.builder;

import hudson.Extension;
import hudson.Launcher;
import hudson.model.BuildListener;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.FreeStyleProject;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.kohsuke.stapler.DataBoundConstructor;

public class CopyFilesBuilder extends Builder {
private final String path;
 
 @DataBoundConstructor
 public CopyFilesBuilder(final String path) {
  this.path = path;
 }

 public String getPath() {
  return path;
 }

 @Override
 public boolean perform(
 @SuppressWarnings("rawtypes") final AbstractBuild build,
 final Launcher launcher, final BuildListener listener)
 throws IOException {
 
 //logic to be executed by plugin
  final File file = new File(path);
  final File destination = new File(build.getWorkspace().getRemote());
 
  if (file.isDirectory()) {
  FileUtils.copyDirectory(file, destination);
  } else {
  FileUtils.copyFileToDirectory(file, destination);
  }
 
 //logger which prints on job 'Console Output'
  listener.getLogger().printf("Copying files from %s to %s", path,
  build.getWorkspace());
  return true;
 }

 @Override
 public DescriptorImpl getDescriptor() {
  return (DescriptorImpl) super.getDescriptor();
 }

 @Extension
 public static class DescriptorImpl extends BuildStepDescriptor<Builder> {

  @Override
  public boolean isApplicable(
  @SuppressWarnings("rawtypes") Class<? extends AbstractProject> jobType) {
   return FreeStyleProject.class.isAssignableFrom(jobType);
  }

  @Override
  public String getDisplayName() {
   //String to be be displayed in 'Add Build Step' dropdown
   return "Copy Files To Workspace";
  }
 }
}

Step 4: Create a index.jelly file under src/main/resources folder and copy the below content to it:

<?jelly escape-by-default='true'?>
<!-- This view is used to render the installed plugins page. -->




<div>
 This plugin copy files to workspace.
</div>




Step 5: Create a folder with same name as of Java class under src/main/resources/ in my case it’s com/jenkins/builder/CopyFilesBuilder and then create config.jelly and help-path.html inside it with below content:

config.jelly

<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
 <!-- Creates a text field that shows the value of the "path" property. When submitted, it will be passed to the corresponding constructor parameter. -->
 <f:entry title="Path" field="path">
 <f:textbox />
 </f:entry>
</j:jelly>

help-path.html






<div>
<!-- Help file for fields are discovered through a file name convention. This file is help for the "path" field. -->
Specify the path to files or folder. For example, for a particular file
specify as /users/arpitaggarwal/file.txt and for a folder specify as
/users/arpitaggarwal/
</div>






After performing all the above steps, your project structure should look like as:

Jenkins Plugin Project Structure

Step 6: Compile and package the plugin:

$ cd copy-files-jenkins-plugin
$ mvn package

After packaging the plugin you should find a .hpi file in the target folder.