Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable changeset when pattern comparator with fullMatch #367

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,14 @@ public class ChangeSetConditional extends DeclarativeStageConditional<ChangeSetC
private transient String glob;
private String pattern;
private boolean caseSensitive;
private boolean shouldMatchAll;
private String comparator;

@DataBoundConstructor
public ChangeSetConditional(String pattern) {
this.pattern = pattern;
this.caseSensitive = false;
this.shouldMatchAll = false;
}

@Deprecated
Expand All @@ -72,6 +74,10 @@ public boolean isCaseSensitive() {
return caseSensitive;
}

public boolean isShouldMatchAll() {
return shouldMatchAll;
}

public String getPattern() {
return pattern;
}
Expand Down Expand Up @@ -107,10 +113,23 @@ public void setCaseSensitive(boolean caseSensitive) {
this.caseSensitive = caseSensitive;
}

public boolean changeSetMatches(ChangeLogSet.Entry change, String pattern, boolean caseSensitive) {
@DataBoundSetter
public void setShouldMatchAll(boolean shouldMatchAll) {
this.shouldMatchAll = shouldMatchAll;
}

public boolean changeSetMatches(ChangeLogSet.Entry change, String pattern, boolean caseSensitive, boolean shouldMatchAll) {
Comparator c = Comparator.get(comparator, Comparator.GLOB);
if (shouldMatchAll) {
return change.getAffectedPaths().stream().allMatch(path -> c.compare(pattern, path, caseSensitive));
} else {
return change.getAffectedPaths().stream().anyMatch(path -> c.compare(pattern, path, caseSensitive));
}
}

return change.getAffectedPaths().stream().anyMatch(path -> c.compare(pattern, path, caseSensitive));
@Deprecated
public boolean changeSetMatches(ChangeLogSet.Entry change, String pattern, boolean caseSensitive) {
return changeSetMatches(change, pattern, caseSensitive, this.isShouldMatchAll());
}

@Extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,20 @@ abstract class AbstractChangelogConditionalScript<S extends DeclarativeStageCond
}
return false
}
return changeSets.any {def set ->
return set.any { def change ->
return matches(change)
}
}
return changeSetsMatches(changeSets);
}
return false
}

abstract boolean matches(ChangeLogSet.Entry change)

boolean changeSetsMatches(List<ChangeLogSet<? extends ChangeLogSet.Entry>> changeSets) {
return changeSets.any {def set ->
return set.any { def change ->
return matches(change)
}
}
}

void initializeEval() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,8 @@
<f:entry field="comparator" title="Comparator">
<f:select/>
</f:entry>
<f:entry field="shouldMatchAll">
<f:checkbox title="whether all the elements in the changeset should match with the given pattern" checked="false"/>
</f:entry>
</f:advanced>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!--
~ The MIT License
~
~ Copyright (c) 2019, Elasticsearch B.V.
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in
~ all copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
~ THE SOFTWARE.
-->

<p>
If true, the comparison should match all the elements in the changeset. Defaults to false.
</p>
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,21 @@ class ChangeSetConditionalScript extends AbstractChangelogConditionalScript<Chan
super(s, c)
}

@Override
boolean changeSetsMatches(List<ChangeLogSet<? extends ChangeLogSet.Entry>> changeSets) {
if (describable.shouldMatchAll) {
return changeSets.every { def set ->
return set.every { def change ->
return matches(change)
}
}
} else {
super.changeSetsMatches(changeSets);
}
}

@Override
boolean matches(ChangeLogSet.Entry change) {
return describable.changeSetMatches(change, describable.pattern, describable.caseSensitive)
return describable.changeSetMatches(change, describable.pattern, describable.caseSensitive, describable.shouldMatchAll)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ public void whenChangeset() throws Exception {
"Hello",
"Stage \"Two\" skipped due to when conditional",
"Stage \"Three\" skipped due to when conditional",
"Stage \"Four\" skipped due to when conditional",
"Warning, empty changelog. Probably because this is the first build.")
.logNotContains("JS World", "With regexp");
.logNotContains("JS World", "With regexp", "With shouldMatchAll");
builder.go();

builder.resetForNewRun(Result.SUCCESS);
Expand All @@ -167,10 +168,11 @@ public void whenChangeset() throws Exception {
sampleRepo.git("add", "somecode.js");
sampleRepo.git("commit", "--message=files");

builder.logContains("Hello", "JS World", "With regexp")
builder.logContains("Hello", "JS World", "With regexp", "With shouldMatchAll")
.logNotContains(
"Stage \"Two\" skipped due to when conditional",
"Stage \"Three\" skipped due to when conditional",
"Stage \"Four\" skipped due to when conditional",
"Warning, empty changelog.",
"Examining changelog from all builds of this change request.")
.go();
Expand All @@ -184,8 +186,9 @@ public void whenChangesetMoreCommits() throws Exception {
"Hello",
"Stage \"Two\" skipped due to when conditional",
"Stage \"Three\" skipped due to when conditional",
"Stage \"Four\" skipped due to when conditional",
"Warning, empty changelog. Probably because this is the first build.")
.logNotContains("JS World", "With regexp");
.logNotContains("JS World", "With regexp", "With shouldMatchAll");
builder.go();

builder.resetForNewRun(Result.SUCCESS);
Expand All @@ -209,10 +212,12 @@ public void whenChangesetMoreCommits() throws Exception {
sampleRepo.git("add", "somefile.js");
sampleRepo.git("commit", "--message=same");

builder.logContains("Hello", "JS World", "With regexp")
builder.logContains("Hello", "JS World", "With regexp",
"Stage \"Four\" skipped due to when conditional")
.logNotContains(
"Stage \"Two\" skipped due to when conditional",
"Stage \"Three\" skipped due to when conditional",
"With shouldMatchAll",
"Warning, empty changelog.",
"Examining changelog from all builds of this change request.")
.go();
Expand Down Expand Up @@ -242,8 +247,10 @@ public void whenChangesetPR() throws Exception {
j.assertLogContains("Hello", build);
j.assertLogContains("Stage \"Two\" skipped due to when conditional", build);
j.assertLogContains("Stage \"Three\" skipped due to when conditional", build);
j.assertLogContains("With shouldMatchAll", build);
j.assertLogNotContains("JS World", build);
j.assertLogNotContains("With regexp", build);
j.assertLogNotContains("Stage \"Four\" skipped due to when conditional", build);

controller.addFile("repoX", crNum,
"files",
Expand All @@ -257,8 +264,10 @@ public void whenChangesetPR() throws Exception {
j.assertLogContains("Hello", build2);
j.assertLogContains("JS World", build2);
j.assertLogContains("With regexp", build2);
j.assertLogContains("With shouldMatchAll", build2);
j.assertLogNotContains("Stage \"Two\" skipped due to when conditional", build2);
j.assertLogNotContains("Stage \"Three\" skipped due to when conditional", build2);
j.assertLogNotContains("Stage \"Four\" skipped due to when conditional", build2);
j.assertLogNotContains("Warning, empty changelog", build2);

controller.addFile("repoX", crNum,
Expand All @@ -273,9 +282,11 @@ public void whenChangesetPR() throws Exception {
j.assertLogContains("Hello", build3);
j.assertLogContains("JS World", build3);
j.assertLogContains("With regexp", build3);
j.assertLogContains("Stage \"Four\" skipped due to when conditional", build3);
j.assertLogContains("Examining changelog from all builds of this change request", build3);
j.assertLogNotContains("Stage \"Two\" skipped due to when conditional", build3);
j.assertLogNotContains("Stage \"Three\" skipped due to when conditional", build3);
j.assertLogNotContains("With shouldMatchAll", build3);
j.assertLogNotContains("Warning, empty changelog", build3);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,48 @@
"value": ".*\\.js"
}
}]}
},
{
"name": "Four",
"branches": [ {
"name": "default",
"steps": [ {
"name": "echo",
"arguments": [ {
"key": "message",
"value": {
"isLiteral": true,
"value": "With shouldMatchAll"
}
}]
}]
}],
"when": {"conditions": [ {
"name": "changeset",
"arguments": [
{
"key": "pattern",
"value": {
"isLiteral": true,
"value": "(.*\\.js|Jenkinsfile)"
}
},
{
"key": "comparator",
"value": {
"isLiteral": true,
"value": "regexp"
}
},
{
"key": "shouldMatchAll",
"value": {
"isLiteral": true,
"value": "true"
}
}
]
}]}
}
],
"agent": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,13 @@ pipeline {
echo "With regexp"
}
}
stage("Four") {
when {
changeset pattern: '(.*\\.js|Jenkinsfile)', comparator: 'regexp', shouldMatchAll: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need this, it looks good. But could the same behavior be achieved like this?

Suggested change
changeset pattern: '(.*\\.js|Jenkinsfile)', comparator: 'regexp', shouldMatchAll: true
changeset pattern: '^(.*\\.js|Jenkinsfile)$', comparator: 'regexp'

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is related to the test example, probably it could be improved, if it's related to this PR, then I've got some doubts if the regex could help since the current pattern is searched with anyMatch https://github.com/jenkinsci/pipeline-model-definition-plugin/pull/367/files#diff-cbce163a23e232096d8a5d0ef5bddf31L113

For instance, one particular use case could be when changes are not related to the source code but some markdown files or files in the docs folder, therefore the pattern (.*\\.md|docs/.*) could help, but what if the changeset contains docs and source code, then this particular feature could help to enable stages for compiling/testing the project.

Please let me know if I misunderstood your question, thanks

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 -- I'm looking for exactly this feature. @bitwiseman -- this is for matching all files in the changeset and not about matching the entire filename

}
steps {
echo "With shouldMatchAll"
}
}
}
}