Coder Social home page Coder Social logo

last-changes-plugin's Introduction

Last Changes Plugin

The simplest way to know what has changed on your Jenkins builds!

Build Status (Travis CI) last changes

Last Changes is a Jenkin plugin that shows rich VCS diffs between builds.

Only Git and Svn based projects are supported.

1. Introduction

The plugin uses diff2html to show last changes of a given build, example:

last changes03

Or using side-by-side configuration:

last changes05
ℹ️
Last changes means compare current repository revision with an old revision. By default the plugin will diff current and previous revision.

2. Objectives

The main objective of this plugin is to have fast access to what has changed on a Jenkins build.

Another interesting aspect is that it can easily help to find the root cause of a failing build by highlighting what has changed.

And finally the plugin shines in a continuous delivery environment, where each commit generates a release candidate.

3. How it works?

  1. This plugin expects .git or .svn folders present on your build workspace and will use it to retrieve repository information .

  2. While your job runs the plugin reads your build workspace to retrieve the current VCS revision;

  3. The diff between actual and a previous revision will be stored; Note that the previous revision can be:

    • A provided revision id;

    • Revision of Last successful build;

    • Revision of an specific build;

    • Revision of Last tag;

      ℹ️
      By default previous revision is current revision -1.
      💡
      You can use parameters in specificRevision parameter. In case of git, expressions like HEAD^{tree} or HEAD^^ can be used.
  4. The diff for each build can be viewed later in html format.

To get most from this plugin use periodically SCM polling to trigger your builds, more details here.

4. Usage

After installation just activate the post build action named Publish Last Changes.

  1. Activate build action

    last changes activation

  2. Last changes menu should be available

    last changes01

  3. Build changes history

    last changes02

  4. Last changes menu is available for builds that published changes

    last changes04

💡

Since version 2.3 the commits between revisions are listed as below:

commits

You can also see what has changed on a specific commit by clicking on it:

commit changes

5. Configuration

The setup is done via build configuration:

last changes config

The possible values for Since attribute is Previous revision (the default), Last successful build and Last tag.

If SpecificRevision parameter is provided then Since configuration will be ignored and the diff will be done with provided revision id.

Advanced configuration reflects diff2html options:

last changes config2

6. Jenkins pipeline step

Following is an example of pipeline step using this plugin:

node {
      stage ('Build') {
           svn 'https://subversion.assembla.com/svn/cucumber-json-files/trunk/'
           step([$class: 'LastChangesPublisher', since:'PREVIOUS_REVISION',specificRevision: '', format: 'LINE', matchWordsThreshold: '0.25', matching: 'NONE', matchingMaxComparisons: '1000', showFiles: true, synchronisedScroll: true])

      }

}

6.1. Pipeline DSL

Since version 1.0.10 it is possible to use the lastChanges() shortcut in pipeline DSL:

node {
     git 'https://github.com/jenkinsci/last-changes-plugin.git'
     lastChanges() //will use defaults
}

Parameters should be declared as key: 'value' as example below:

node {
     git 'https://github.com/jenkinsci/last-changes-plugin.git'
     lastChanges format:'SIDE',matching: 'WORD', specificRevision: 'c546ec31e854de3f27755273d3e1db6185aee4b4'
}
pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/jenkinsci/last-changes-plugin.git'
                lastChanges since: 'LAST_SUCCESSFUL_BUILD', format:'SIDE',matching: 'LINE'
            }
        }
    }
}

Or using build params for specificRevision:

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/jenkinsci/last-changes-plugin.git'
                lastChanges format:'SIDE',matching: 'WORD', specificRevision: "${REV}"
            }
        }
    }
}
💡
Refer to parameterized builds to use parameters.

6.2. Pipeline scripting

Since v2.5 is possible to invoke LastChanges inside groovy script, instead of just declaring it as we saw above. See example below:

node {
      stage("checkout") {
        git url: 'https://github.com/jenkinsci/last-changes-plugin.git'
      }

      stage("last-changes") {
        def publisher = LastChanges.getLastChangesPublisher "PREVIOUS_REVISION", "SIDE", "LINE", true, true, "", "", "", "", ""
              publisher.publishLastChanges()
              def changes = publisher.getLastChanges()
              println(changes.getEscapedDiff())
              for (commit in changes.getCommits()) {
                  println(commit)
                  def commitInfo = commit.getCommitInfo()
                  println(commitInfo)
                  println(commitInfo.getCommitMessage())
                  println(commit.getChanges())
              }
      }

}
ℹ️
See model classes to know what can be accessed in pipeline script. Note that only attributes annotated with @Whitelisted are visible to be accessed in pipeline script.
💡
If you use declarative pipeline you can use script section.

7. Download the diff

You can also download the diff as DIFF or HTML. The download links are on the bottom right corner of the page:

diff download

8. Sending the diff as email

Using email ext plugin and Pipeline scripting we can send the diff as an email attachment, see example below:

  1. Diff in plain text

    pipeline {
        agent any
        stages {
            stage('Checkout') {
                steps {
                    git url: 'https://github.com/jenkinsci/last-changes-plugin'
                }
            }
            stage("send diff") {
                steps {
                    script {
                        def publisher = LastChanges.getLastChangesPublisher null, "SIDE", "LINE", true, true, "", "", "", "", ""
                        publisher.publishLastChanges()
                        def diff = publisher.getDiff()
                        writeFile file: 'build.diff', text: diff
                        emailext (
                          subject: "Jenkins - changes of ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                          attachmentsPattern: '**/*.diff',
                          mimeType: 'text/html',
                          body: """<p>See attached diff of <b>${env.JOB_NAME} #${env.BUILD_NUMBER}</b>.</p>
                            <p>Check build changes on Jenkins <b><a href="${env.BUILD_URL}/last-changes">here</a></b>.</p>""",
                          to: "[email protected]"
                        )
    
                   }
    
                }
            }
        }
    }
  2. Diff in Html format

    pipeline {
        agent any
        stages {
            stage('Send html diff') {
                steps {
                    git 'https://github.com/jenkinsci/last-changes-plugin.git'
                    script {
                      def publisher = LastChanges.getLastChangesPublisher "PREVIOUS_REVISION", "SIDE", "LINE", true, true, "", "", "", "", ""
                      publisher.publishLastChanges()
                      def htmlDiff = publisher.getHtmlDiff()
                      writeFile file: 'build-diff.html', text: htmlDiff
                        emailext (
                          subject: "Jenkins - changes of ${env.JOB_NAME} #${env.BUILD_NUMBER}",
                          attachmentsPattern: '**/*build-diff.html',
                          mimeType: 'text/html',
                          body: """<p>See attached diff of build <b>${env.JOB_NAME} #${env.BUILD_NUMBER}</b>.</p>
                            <p>Check build changes on Jenkins <b><a href="${env.BUILD_URL}/last-changes">here</a></b>.</p>""",
                          to: "[email protected]" )
                    } //end script
                }
            }
        }
    }

9. Docker

An easy way to test this plugin is using a docker container, here are the steps (assuming you have docker installed):

  1. Run the image:

    docker run -it -p 8080:8080 rmpestano/jenkins-last-changes
  2. Access localhost:8080/ and create a job

  3. Configure this svn repository: https://subversion.assembla.com/svn/cucumber-json-files/trunk/

  4. Add the Publish last changes post build action;

  5. Just run the job

Job output should look like:

last changes docker

10. Running it locally

Following are the steps to run, debug and test this plugin on your machine:

  1. Clone this repository

    git clone http://github.com/jenkinsci/last-changes-plugin
  2. Import it on your IDE

  3. Run the command mvnDebug hpi:run -DskipTests

  4. Configure the remote debugging on your IDE to use port 8000, as in image below:

    last changes debug

  5. Access http://localhost:8080/jenkins

Now create jobs using last-changes and debug them.

For testing run any class on src/test/java folder as JUnit test.

ℹ️
Tests with IT suffix will start a Jenkins instance before the test.
💡

To generate the binary of the plugin run:

mvn clean package -DskipTests

It will generate last-changes.hpi in target folder. You can install it on jenkins via upload in jenkins/pluginManager.

11. Contributing

12. Change Log

Please follow releases page for details of each release.

last-changes-plugin's People

Contributors

adam-krieg avatar basil avatar capadgett avatar david-mntl avatar jsoref avatar oleg-nenashev avatar rmpestano avatar vkotovv avatar yuri1969 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

last-changes-plugin's Issues

Upgrade Jenkins baseline to 2.x

As most of users (93%) of this plugins are on Jenkins 2.x we'll upgrade the baseline.

NOTE: You can still install the plugin on Jenkins 1.x.

Support for variables in end revision input

We should be able to pass a variable to end revision input, currently the following error is throw:

ERROR: Last Changes NOT published due to the following error: For input string: "${REV}"

Makes LastChanges available in pipeline script

Hi looking in the code for the plugin i notice:

LastChangesBuildAction::public LastChanges getBuildChanges()

Is it possible to access this member function in a the pipeline script like:

def commits = step([$class: 'LastChanges', since:'LAST_SUCCESSFUL']).getBuildChanges():

for i in commits:
    print i.getMessage()

Would be really useful to have this.

Feature Request: Target specific file(s) in repository for diff

I'd really like to be able to specify a single file (or even, series of explicit files?) inside my git repo for diff. The structure of the particular build I'm using contains artifacts by filename and releases them by associated environment in our distribution server.

Is this functionality that can be added?

NullPointerException when using sinceLastSuccessfulBuild

A Nullpointer is raised when there is no successful build when using last changes since last successful build option. The plugin must use previous version instead.

pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git 'https://github.com/jenkinsci/last-changes-plugin.git'
                lastChanges sinceLastSuccessfulBuild: true, format:'SIDE',matching: 'LINE'
            }
        }
    }
}
java.lang.NullPointerException
	at com.github.jenkins.lastchanges.LastChangesPublisher.perform(LastChangesPublisher.java:139)
	at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:69)
	at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:59)

Skip SCM verification for GIT repositories.

When running a pipeline script for the first time the SCM is not found, see JENKINS-45720 for details. Currently last changes does NOT depend on SCM for GIT (only svn does) but we are throwing an exception when SCM is not found.

Do not throw the exception for GIT repositories.

Support parameterized repository url for SVN builds

When using a parameterized repository URL the plugin cannot resolve parameters and the following error is throw:

ERROR: Last Changes NOT published due to the following error: Could not retrieve last changes of svn repository located at /Project/branches/${SVN_Branch} due to the following error: svn: E160013: Diff target 'svn://svnserver/Project/branches/$%7BSVN_Branch%7D' was not found in the repository at revisions '81,828' and '81,829' - org.tmatesoft.svn.core.SVNException: svn: E160013: Diff target 'svn://svnserver/Project/branches/$%7BSVN_Branch%7D' was not found in the repository at revisions '81,828' and '81,829'

This only affects SVN based jobs because for GIT the plugin reads changes from .git folder and not from repository url.

Javascript error while displaying diff

Hi @rmpestano,

I found a problem (I use svn) in browser console while showing diff involving binary files. I realized this because a cli attempt of svn diff didn't display my xml file, even if modified. (See attachment)

There's an svn option (--force) to treat files in text mode but I thinks this could cause rendering problem in case bigger binary archives like jar are added/removed.

What do you suggest?

Thanks in advance

typeerror this each is not a function

findVCSDir researches only one, first folder from workspace.

Function, a module for searching SVn or GIT local copy only do it in a first founded folder in a workspace. If you have more than one folder, e.g for reports it is possible that this module checks only if a local copy exists in this folder and if not found, raise an error "Git or Svn directories not found in workspace..."
-workspace
----dir1 <- module only search inside this directory
--------dir1/A
--------dir1/B
----dir2<- module do not check this structure/directory and do not found .svn or .git so do not found local copy
--------dir2/A
--------dir2/.svn
Wery fast patch, but without considering the depth:

private FilePath findVCSDir(FilePath workspace, String dir) throws IOException, InterruptedException {
	FilePath gitDir = null;
	for (FilePath filePath : workspace.listDirectories()) {
		if (filePath.getName().equalsIgnoreCase(dir)) {
			return filePath;
		} else {
			gitDir = findVCSDirInSubDirectories(filePath, dir);
		}
	}
	return gitDir;
}

private FilePath findVCSDirInSubDirectories(FilePath sourceDir, String dir) throws IOException, InterruptedException {
	for (FilePath filePath : sourceDir.listDirectories()) {
		if (filePath.getName().equalsIgnoreCase(dir)) {
			return filePath;
		} else {
			return findVCSDirInSubDirectories(filePath, dir);
		}
	}
	return null;
}

endRevision does not work

I use the lastChanges-Plugin in a multibranch pipeline script but as soon as I set endRevision to anything else than '' I get an error. I have tried endRevision: 'master', endRevision: 'origin/master' etc. It does not work.

Error message: ERROR: Last Changes NOT published due to the following error: Invalid id: origin/master

pipeline - multi git support

Previous version of the plugin was not supporting multi-scm plugin (job with multiple git)

Has this been considered with the update to support pipleline?
I do not see any example using list of git repository

Plugin does not use the right SCM reliably

My pipeline code is in a svn repository and the project ist stored in a git repository.
I execute the lastChanges step right after the checkout of the git repository.
Sometimes it fails because of the exception listed below. It looks to me, that the order of items from SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(projectAction.getProject()).getSCMs() is random and sometimes the plugin tries to convert the git commit hash into an svn revsion.

java.lang.NumberFormatException: For input string: "784add6adb524b84bb3287607a9fded9b34af16c"
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.lang.Long.parseLong(Long.java:589)
        at java.lang.Long.parseLong(Long.java:631)
        at com.github.jenkins.lastchanges.LastChangesPublisher.perform(LastChangesPublisher.java:181)
        at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:80)
        at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:67)
        at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution$1$1.call(SynchronousNonBlockingStepExecution.java:49)
        at hudson.security.ACL.impersonate(ACL.java:260)
        at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution$1.run(SynchronousNonBlockingStepExecution.java:46)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

Path to a changed file?

Hi guys I am new to this plugin and I am looking for a way to find files which have changed and copy them across to another directory is there any way to get that done? Thanks

Group changes per commit for a single build

Hi @rmpestano,

it is very common to have multiple commit in a single build, so I think it could be useful to have changes grouped by revision involved in a single build. Something like a "relative" changelog containing revision range diff.

What do you think?

LAST_TAG not working

Hi,

i might be using it wrong but i want to see all changes between current build and last build that has a tag (any tag?), and if i understand correctly the "LAST_TAG" is according to the jenkins builds tags, not the git tags?

using the syntax below still only gives me changes since last build, not since the last tag. am i using it wrong?
thanks
Asher

using:
def publisher = LastChanges.getLastChangesPublisher "LAST_TAG", "SIDE", "LINE", true, true, "", "", "", "", ""
publisher.publishLastChanges()
def changes = publisher.getLastChanges()
println(changes.getEscapedDiff())
for (commit in changes.getCommits()) {
println(commit)
def commitInfo = commit.getCommitInfo()
println(commitInfo)
println(commitInfo.getCommitMessage())
println(commit.getChanges())
}

Reorganize UI

With the addition of #26 we will now have 4 ways of comparing current revision with:

1 - Previous revision (default)
2 - Specific revision (one provided in previousRevision text field)
3 - Since last successful build (currently a checkbox)
4 - Since last tag (the new feature)

Do the following refectory:
Put 1, 3 and 4 in one field of type select called Since;
Rename previousRevision to specificRevision

Put difftoHtml options in Advanced section,

Switch current and previous revision summary panel

Most diff tools like in IntelliJ and Github split mode put the previous changes on the left and new changes on the right.

So do the same in LastChanges changes where Current revision summary must be on the right and previous on the left panel.

VCS dir should only be deleted if it was copied before

I get an error (see stacktrace below), possibly because of a situation where:

  • pipeline runs on a single Jenkins (no master-slave setup)
  • "vcsTargetDir" possibly is equal to "remoteGitDir", so "vcsDirFound" did not get copied at line 153 in the first place
  • the .git folder is still needed for additional custom pipeline activities afterwards

I presume most people do not do anything with their .git folder in their pipeline besides using lastChanges, so they do not notice its deletion (or run into this issue).

I think, the delete call should happen only if the copy "branch" (or line 177) was hit before.

Stacktrace:

java.nio.file.FileSystemException: C:\Program Files (x86)\Jenkins\jobs{{my_project}}\branches\master\builds\23.git\objects\pack\pack-bff7ccf14f020218be91e14508750dea6ab1a157.pack: The process cannot access the file because it is being used by another process.

at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(Unknown Source)
at java.nio.file.Files.deleteIfExists(Unknown Source)
at hudson.Util.tryOnceDeleteFile(Util.java:316)
at hudson.Util.deleteFile(Util.java:272)
Also: hudson.AbortException: script returned exit code -1
at org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep$Execution.check(DurableTaskStep.java:335)
at org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep$Execution.run(DurableTaskStep.java:288)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
Caused: java.io.IOException: Unable to delete 'C:\Program Files (x86)\Jenkins\jobs{{my_project}}\branches\master\builds\23.git\objects\pack\pack-bff7ccf14f020218be91e14508750dea6ab1a157.pack'. Tried 3 times (of a maximum of 3) waiting 0,1 sec between attempts.
at hudson.Util.deleteFile(Util.java:277)
at hudson.FilePath.deleteRecursive(FilePath.java:1322)
at hudson.FilePath.deleteContentsRecursive(FilePath.java:1331)
at hudson.FilePath.deleteRecursive(FilePath.java:1313)
at hudson.FilePath.deleteContentsRecursive(FilePath.java:1331)
at hudson.FilePath.deleteRecursive(FilePath.java:1313)
at hudson.FilePath.deleteContentsRecursive(FilePath.java:1331)
at hudson.FilePath.deleteRecursive(FilePath.java:1313)
at hudson.FilePath.access$1600(FilePath.java:209)
at hudson.FilePath$DeleteRecursive.invoke(FilePath.java:1291)
at hudson.FilePath$DeleteRecursive.invoke(FilePath.java:1287)
at hudson.FilePath.act(FilePath.java:1095)
at hudson.FilePath.act(FilePath.java:1078)
at hudson.FilePath.deleteRecursive(FilePath.java:1285)
at com.github.jenkins.lastchanges.LastChangesPublisher.perform(LastChangesPublisher.java:292)
at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:80)
at org.jenkinsci.plugins.workflow.steps.CoreStep$Execution.run(CoreStep.java:67)
at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution$1$1.call(SynchronousNonBlockingStepExecution.java:49)
at hudson.security.ACL.impersonate(ACL.java:290)
at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution$1.run(SynchronousNonBlockingStepExecution.java:46)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Finished: FAILURE

Rename lastSuccessfulBuild to sinceLastSuccessfulBuild

Renaming to sinceLastSuccessfulBuild makes more sense and you can read: "Last changes since last successful build", also in a pipeline dsl:

 post {
            always {
                lastChanges sinceLastSuccessfulBuild: true format:'SIDE',matching: 'LINE'
            }
}

Compare current workspace diff with remote

I'm in a particular case where I have to deploy sources from one repository (our deploy repo) to customer repository (release source to customer).

I saw that scm is caluclated where the scm is the one where files were committed and for which a build trigger occurred:

https://github.com/jenkinsci/last-changes-plugin/blob/master/src/main/java/com/github/jenkins/lastchanges/LastChangesPublisher.java#L155

In my pipeline I do a second scm checkout and I would like to diff in a way like this:

svn diff -r PREV:BASE | diff2html -i stdin -s side -F report.html

Where BASE is workspace with incoming new changes for the customer repo.

Is it possible to point to a different repo to show diff?

Thanks,
Luigi

Wrong diff of specific commit in git repositories

When a commit has more than one parent (e.g merges) the diff is being done with wrong commit.

To solve, instead of diff with previous commit (in chronological order) we need to resolve the previous commit relative to the commit of interest, see here.

Can't delete .git directory after build, exception thrown

Hi,

I'm trying to get the latest commit id from my git repo, if new commits are made since the last time the pipeline job was executed. Here's my scriptable pipeline script. (My git repo is checked-out to a subfolder "MY_REPO" of the jenkins workspace.)

node
{
	stage("Checkout")
	{
		dir ("MY_REPO")
		{
			git url: user@gitrepo:/srv/git/MY_REPO.git, branch: "master", credentialsId: "12345678-1234-1234-1234-123456789012"
		}

		def publisher = LastChanges.getLastChangesPublisher "LAST_SUCCESSFUL_BUILD", "SIDE", "NONE", false, false, "", "", "", "MY_REPO", ""
		publisher.publishLastChanges()
		def changes = publisher.getLastChanges()
		if (changes.getCommits().size() > 0)
		{
			def currentRevision = changes.getCurrentRevision()
			echo "Latest CommitId: " + currentRevision.commitId
		}
		else
		{
			echo "No new commits since last successful build"
		}
	}
}

But I get an exception at the end of the job execution, where it says it can't delete a file in the .git folder. I checked using ProcessExplorer, the file is still being locked by Jenkins process itself. I'm running the WAR version of jenkins using "java -jar jenkins.war".
(Edit:) I'm using the pipeline (non-multibranch) type of Jenkins project
However, if I use "PREVIOUS_REVISION" instead of "LAST_SUCCESSFUL_BUILD", I do not get this exception. My guess is that this plugin is still holding on to the file in .git folder when it is calling vcsTargetDir.deleteRecursive()?
Or did I do something incorrectly here?
The full exception stack is below:

java.nio.file.FileSystemException: D:\Jenkins\jobs\MY_JOB\builds\210\.git\objects\pack\pack-a76739f8dc0c4b6f3eb19e7e54c152b7cc72271f.pack: The process cannot access the file because it is being used by another process.

	at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
	at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
	at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
	at sun.nio.fs.WindowsFileSystemProvider.implDelete(Unknown Source)
	at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(Unknown Source)
	at java.nio.file.Files.deleteIfExists(Unknown Source)
	at hudson.Util.tryOnceDeleteFile(Util.java:316)
	at hudson.Util.deleteFile(Util.java:272)
	at hudson.FilePath.deleteRecursive(FilePath.java:1270)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1279)
	at hudson.FilePath.deleteRecursive(FilePath.java:1261)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1279)
	at hudson.FilePath.deleteRecursive(FilePath.java:1261)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1279)
	at hudson.FilePath.deleteRecursive(FilePath.java:1261)
	at hudson.FilePath.access$1200(FilePath.java:209)
	at hudson.FilePath$DeleteRecursive.invoke(FilePath.java:1241)
	at hudson.FilePath$DeleteRecursive.invoke(FilePath.java:1237)
	at hudson.FilePath.act(FilePath.java:1047)
	at hudson.FilePath.act(FilePath.java:1025)
	at hudson.FilePath.deleteRecursive(FilePath.java:1235)
	at com.github.jenkins.lastchanges.LastChangesPublisher.perform(LastChangesPublisher.java:292)
	at com.github.jenkins.lastchanges.pipeline.LastChangesPublisherScript.doPublish(LastChangesPublisherScript.java:31)
	at com.github.jenkins.lastchanges.pipeline.PublishLastChangesStep$Execution.run(PublishLastChangesStep.java:43)
	at com.github.jenkins.lastchanges.pipeline.PublishLastChangesStep$Execution.run(PublishLastChangesStep.java:24)
	at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution.start(AbstractSynchronousStepExecution.java:42)
	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:229)
	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:153)
	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
	at com.github.jenkins.lastchanges.pipeline.LastChangesPublisherScript.publishLastChanges(LastChangesPublisherScript.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
	at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:47)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:157)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:133)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
Caused: java.io.IOException: Unable to delete 'D:\Jenkins\jobs\MY_JOB\builds\210\.git\objects\pack\pack-a76739f8dc0c4b6f3eb19e7e54c152b7cc72271f.pack'. Tried 3 times (of a maximum of 3) waiting 0.1 sec between attempts.
	at hudson.Util.deleteFile(Util.java:277)
	at hudson.FilePath.deleteRecursive(FilePath.java:1270)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1279)
	at hudson.FilePath.deleteRecursive(FilePath.java:1261)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1279)
	at hudson.FilePath.deleteRecursive(FilePath.java:1261)
	at hudson.FilePath.deleteContentsRecursive(FilePath.java:1279)
	at hudson.FilePath.deleteRecursive(FilePath.java:1261)
	at hudson.FilePath.access$1200(FilePath.java:209)
	at hudson.FilePath$DeleteRecursive.invoke(FilePath.java:1241)
	at hudson.FilePath$DeleteRecursive.invoke(FilePath.java:1237)
	at hudson.FilePath.act(FilePath.java:1047)
	at hudson.FilePath.act(FilePath.java:1025)
	at hudson.FilePath.deleteRecursive(FilePath.java:1235)
	at com.github.jenkins.lastchanges.LastChangesPublisher.perform(LastChangesPublisher.java:292)
	at com.github.jenkins.lastchanges.pipeline.LastChangesPublisherScript.doPublish(LastChangesPublisherScript.java:31)
	at com.github.jenkins.lastchanges.pipeline.PublishLastChangesStep$Execution.run(PublishLastChangesStep.java:43)
	at com.github.jenkins.lastchanges.pipeline.PublishLastChangesStep$Execution.run(PublishLastChangesStep.java:24)
	at org.jenkinsci.plugins.workflow.steps.AbstractSynchronousStepExecution.start(AbstractSynchronousStepExecution.java:42)
	at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:229)
	at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:153)
	at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
	at com.github.jenkins.lastchanges.pipeline.LastChangesPublisherScript.publishLastChanges(LastChangesPublisherScript.java:38)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1213)
	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1022)
	at org.codehaus.groovy.runtime.callsite.PojoMetaClassSite.call(PojoMetaClassSite.java:47)
	at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:157)
	at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:23)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:133)
	at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:155)
	at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:159)
	at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:17)
	at WorkflowScript.run(WorkflowScript:146)
	at ___cps.transform___(Native Method)
	at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:57)
	at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:109)
	at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:77)
	at sun.reflect.GeneratedMethodAccessor248.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
	at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
	at com.cloudbees.groovy.cps.Next.step(Next.java:83)
	at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
	at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
	at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:122)
	at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:261)
	at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
	at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$101(SandboxContinuable.java:34)
	at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.lambda$run0$0(SandboxContinuable.java:59)
	at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:108)
	at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:58)
	at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:174)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:332)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:83)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:244)
	at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:232)
	at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:64)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
	at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
	at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:59)
	at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)

Plugin creates repo clone for each build.

Hi,
We are using a git repo. Is it expected behavior if the plugin cannot find ..//.git, that it will create a clone for the build in that builds folder on the master node?

I confirmed that the workspace does contain a .git folder, and that git commands run from the workspace succeed; git sees this workspace as a git repository.

Our job uses a custom workspace, and we specify a reference repository in the Advanced clone behaviors.

Thanks,

Steve F.

Better error message

Most exception shows "null" as exception cause:

"ERROR: Last Changes NOT published due to the following error: null"

Email the diff

Make it possible to send an e-mail with the diff.

The content should be in plain text in diff format or html.

The e-mail can be send on build that published last changes or only on failed builds.

Diff with an specific revision

Currently the plugin always compare and create the diff with current and previous revisions. Add the ability to specify an specific revision as parameter. This revision will be diff'ed with current checked out/cloned revision.

'null' revision in SVN

Sometimes the plugin cannot get CommitInfo and current revision info is not retrieved.

The job log prints the folling:

Last changes from revision null to 2975 published successfully!

Note that the diff is ok:

null

Pipeline: plugin does not find SCMs

Pipeline job def:

node() {
  def STOP_ON_ERROR = '';
  def mvnHome
  def javaHome
  def failed = false;
  try{
    stage('Preparation') { // for display purposes
      // Get the Maven tool.
      // ** NOTE: This 'M3' Maven tool must be configured
      // **       in the global configuration.
      checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[url: 'https://github.com/thomas-oo/eventAppFrontend']]])
    }
  }catch(Exception e){
    failed = true
    echo 'Build failed'
  }finally{
    if(!failed){
      stage('Last Changes'){
        echo 'In last changes'
        step([$class: 'LastChangesPublisher', format: 'LINE', matchWordsThreshold: '0.25', matching: 'NONE', matchingMaxComparisons: '1000', showFiles: true, synchronisedScroll: true, endRevision: ''])
      }
    }
    echo 'In finally block'
  }
}

The pipeline job runs correct and goes into the Last Changes stage Then throws an error, java.lang.RuntimeException: Git/Svn must be configured on your job to publish Last Changes.

When debugging this plugin, looks like in LastChangesPublisher, wkfJob.getSCMs() returns an empty collection and does not go into the for loop after.

Is there something I need to config in my pipeline script so jenkins knows this is a git scm?

Simplify pipeline script execution

To call the plugin via pipeline script one needs to declare all parameters and declare the step:

 step([$class: 'LastChangesPublisher', format: 'LINE', matchWordsThreshold: '0.25', matching: 'NONE', matchingMaxComparisons: '1000', showFiles: true, synchronisedScroll: true, endRevision: ''])

Make lastChanges pipeline step aware as described here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.