Skip to content

Commit

Permalink
[JENKINS-4162] Optionally report the most recent commit as the change…
Browse files Browse the repository at this point in the history
…log of a new build (#1565)

* Add files via upload

* code for gui

* trait file

* gitscm changes

* testing for new trait behavior

* null check time

* update to proper version number

Co-authored-by: UltimateGeek <[email protected]>

* Update FirstBuildChangelogTrait

Removed improper CloudBees copyright documentation, updated @param for the constructor

* Format new files with spotless:apply

Use line termination that is consistent with the other files in the repository.

Use import ordering as defined by spotless.

* Remove trailing space characters

* Changed equals to use proper equals method

* Changed equals to use proper equals method

* Changed equals to use proper equals method

* changed to compatible equal

* Fix Mark's poor code review

* Use leading lower case letter for the symbol

Jenkins symbol names consistently start with a lower case letter.

* Use sentence case for display name

* Set API release to 5.3.0

* removed groovy and checkbox

* Update to documentation and applying spotless

* Pushing documentation image

* Undo spotless changes - not ready for spotless

* Reduce doc diffs

* Use Unix file format for help

* Jenkins Pipeline symbols start with a lower case letter

* Remove blank line from doc example

* First build changelog reports most recent commit as changelog

The new extension reports the most recent commit as the changelog.
It does not report the changes from a base branch, because there is no
reliable method to identify the base branch from command line git.

Also adjusts capitalization to be consistent with other parts of the
documentation.

* Format new example same as prior examples.

* Clarify first build option help and docs

* Remove comment as suggested by reviewer

---------

Co-authored-by: Derek Inskeep <[email protected]>
Co-authored-by: UltimateGeek <[email protected]>
Co-authored-by: Mark Waite <[email protected]>
Co-authored-by: Derek Inskeep <[email protected]>
  • Loading branch information
5 people committed Jul 29, 2024
1 parent a2b54b1 commit 25ca71b
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 3 deletions.
17 changes: 17 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,23 @@ Inverse::
This is useful, for example, when you have jobs building your master and various release branches and you want a second job which builds all new feature branches.
For example, branches which do not match these patterns without redundantly building master and the release branches again each time they change.

[#first-build-changelog]
==== First build changelog

image:/images/git-extension-for-first-build.png[First build changelog]

The Jenkins git plugin provides an option to trigger a Pipeline build on the first commit on a branch.
By default, no changelog is generated for the first build because the first build has no predecessor build for comparison.
When the first build changelog option is enabled, the most recent commit will be used as the changelog of the first build.

[source,groovy]
----
checkout scmGit(
branches: [[name: 'master']],
extensions: [ firstBuildChangelog() ],
userRemoteConfigs: [[url: 'https://github.com/jenkinsci/git-plugin.git']])
----

[#merge-extensions]
=== Merge Extensions

Expand Down
Binary file added images/git-extension-for-first-build.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 9 additions & 3 deletions src/main/java/hudson/plugins/git/GitSCM.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import hudson.plugins.git.extensions.impl.BuildSingleRevisionOnly;
import hudson.plugins.git.extensions.impl.ChangelogToBranch;
import hudson.plugins.git.extensions.impl.CloneOption;
import hudson.plugins.git.extensions.impl.FirstBuildChangelog;
import hudson.plugins.git.extensions.impl.PathRestriction;
import hudson.plugins.git.extensions.impl.LocalBranch;
import hudson.plugins.git.extensions.impl.RelativeTargetDirectory;
Expand Down Expand Up @@ -1493,9 +1494,14 @@ private void computeChangeLog(GitClient git, Revision revToBuild, TaskListener l
}

if (!exclusion) {
// this is the first time we are building this branch, so there's no base line to compare against.
// if we force the changelog, it'll contain all the changes in the repo, which is not what we want.
listener.getLogger().println("First time build. Skipping changelog.");
FirstBuildChangelog firstBuildChangelog = getExtensions().get(FirstBuildChangelog.class);
if (firstBuildChangelog != null && firstBuildChangelog.isMakeChangelog()) {

Check warning on line 1498 in src/main/java/hudson/plugins/git/GitSCM.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 1498 is only partially covered, one branch is missing
changelog.to(out).max(1).execute();
executed = true;
listener.getLogger().println("First time build. Latest changes added to changelog.");
} else {
listener.getLogger().println("First time build. Skipping changelog.");
}
} else {
changelog.to(out).max(MAX_CHANGELOG).execute();
executed = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package hudson.plugins.git.extensions.impl;

import hudson.Extension;
import hudson.plugins.git.extensions.GitSCMExtension;
import hudson.plugins.git.extensions.GitSCMExtensionDescriptor;
import java.util.Objects;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

/**
* First Build generates a changelog.
*
* @author Derek Inskeep
*/
public class FirstBuildChangelog extends GitSCMExtension {
private boolean makeChangelog;

@DataBoundConstructor
public FirstBuildChangelog() {
makeChangelog = true;
}

public boolean isMakeChangelog() {
return makeChangelog;
}

@DataBoundSetter
public void setMakeChangelog(boolean makeChangelog) {
this.makeChangelog = makeChangelog;
}

/**
* {@inheritDoc}
*/
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
FirstBuildChangelog that = (FirstBuildChangelog) o;
return makeChangelog == that.makeChangelog;
}

/**
* {@inheritDoc}
*/
@Override
public int hashCode() {
return Objects.hash(makeChangelog);
}

/**
* {@inheritDoc}
*/
@Override
public String toString() {
return "FirstBuildChangelog{" + "makeChangelog=" + makeChangelog + '}';

Check warning on line 61 in src/main/java/hudson/plugins/git/extensions/impl/FirstBuildChangelog.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 30-61 are not covered by tests
}

@Extension
@Symbol("firstBuildChangelog")
public static class DescriptorImpl extends GitSCMExtensionDescriptor {

/**
* {@inheritDoc}
*/
@Override
public String getDisplayName() {
return "First build changelog";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package jenkins.plugins.git.traits;

import edu.umd.cs.findbugs.annotations.CheckForNull;
import hudson.Extension;
import hudson.plugins.git.extensions.impl.FirstBuildChangelog;
import jenkins.scm.api.trait.SCMSourceTrait;
import org.jenkinsci.Symbol;
import org.kohsuke.stapler.DataBoundConstructor;

/**
* Exposes {@link FirstBuildChangelog} as a {@link SCMSourceTrait}.
*
* @since 5.3.0
*/
public class FirstBuildChangelogTrait extends GitSCMExtensionTrait<FirstBuildChangelog> {

/**
* @deprecated Use constructor that accepts extension instead.
*/
@Deprecated
public FirstBuildChangelogTrait() {
this(null);
}

/**
* Stapler constructor.
*
* @param extension the option to force first build to have a non-empty changelog.
*/
@DataBoundConstructor
public FirstBuildChangelogTrait(@CheckForNull FirstBuildChangelog extension) {
super(extension == null ? new FirstBuildChangelog() : extension);
}

Check warning on line 33 in src/main/java/jenkins/plugins/git/traits/FirstBuildChangelogTrait.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 22-33 are not covered by tests

/**
* Our {@link hudson.model.Descriptor}
*/
@Extension
@Symbol("firstBuildChangelog")
public static class DescriptorImpl extends GitSCMExtensionTraitDescriptor {
/**
* {@inheritDoc}
*/
@Override
public String getDisplayName() {
return "First Build Changelog";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div>
First builds will populate the changelog with the latest commit, if any, to allow Pipelines to check and test for file changes.
By default, no changelog is generated for the first build because the first build has no predecessor build for comparison.
When the first build changelog option is enabled, the most recent commit on the branch will be used as the changelog of the first build.
</div>
19 changes: 19 additions & 0 deletions src/test/java/hudson/plugins/git/GitSCMTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1188,6 +1188,25 @@ public void testCleanBeforeCheckout() throws Exception {
assertThat("Cleaning should happen before fetch", cleaningLogLine, is(lessThan(fetchingLogLine)));
}

@Test
public void testFirstBuiltChangelog() throws Exception {
assumeTrue("Test class max time " + MAX_SECONDS_FOR_THESE_TESTS + " exceeded", isTimeAvailable());
FreeStyleProject p = setupProject("master", false, null, null, "Jane Doe", null);
FirstBuildChangelog fbc = new FirstBuildChangelog();
((GitSCM) p.getScm()).getExtensions().add(fbc);

/* First build should should generate a changelog */
final String commitFile1 = "commitFile1";
commit(commitFile1, johnDoe, janeDoe, "Commit number 1");
final FreeStyleBuild firstBuild = build(p, Result.SUCCESS, commitFile1);
assertThat(firstBuild.getLog(50), hasItem("First time build. Latest changes added to changelog."));
/* Second build should have normal behavior */
final String commitFile2 = "commitFile2";
commit(commitFile2, johnDoe, janeDoe, "Commit number 2");
final FreeStyleBuild secondBuild = build(p, Result.SUCCESS, commitFile2);
assertThat(secondBuild.getLog(50), not(hasItem("First time build. Latest changes added to changelog.")));
}

@Issue("JENKINS-8342")
@Test
public void testExcludedRegionMultiCommit() throws Exception {
Expand Down

0 comments on commit 25ca71b

Please sign in to comment.