Skip to content

Commit f2ae5b7

Browse files
author
KINAXIS\agharat
committed
Add include versions to enable caching
1 parent 84da9c5 commit f2ae5b7

File tree

8 files changed

+160
-14
lines changed

8 files changed

+160
-14
lines changed

src/main/java/org/jenkinsci/plugins/workflow/libs/LibraryAdder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ static List<URL> retrieve(@NonNull LibraryRecord record, @NonNull LibraryRetriev
210210
shouldCache = false;
211211
}
212212

213-
if(shouldCache) {
213+
if(shouldCache && cachingConfiguration.isIncluded(version)) {
214214
retrieveLock.readLock().lockInterruptibly();
215215
try {
216216
CacheStatus cacheStatus = getCacheStatus(cachingConfiguration, versionCacheDir);

src/main/java/org/jenkinsci/plugins/workflow/libs/LibraryCachingConfiguration.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,19 @@ public final class LibraryCachingConfiguration extends AbstractDescribableImpl<L
2929

3030
private int refreshTimeMinutes;
3131
private String excludedVersionsStr;
32+
private String includedVersionsStr;
3233

3334
private static final String VERSIONS_SEPARATOR = " ";
3435
public static final String GLOBAL_LIBRARIES_DIR = "global-libraries-cache";
3536
public static final String LAST_READ_FILE = "last_read";
3637

37-
@DataBoundConstructor public LibraryCachingConfiguration(int refreshTimeMinutes, String excludedVersionsStr) {
38+
@DataBoundConstructor public LibraryCachingConfiguration(int refreshTimeMinutes, String excludedVersionsStr, String includedVersionsStr) {
3839
this.refreshTimeMinutes = refreshTimeMinutes;
3940
this.excludedVersionsStr = excludedVersionsStr;
41+
this.includedVersionsStr = includedVersionsStr;
4042
}
4143

44+
4245
public int getRefreshTimeMinutes() {
4346
return refreshTimeMinutes;
4447
}
@@ -54,6 +57,8 @@ public Boolean isRefreshEnabled() {
5457
public String getExcludedVersionsStr() {
5558
return excludedVersionsStr;
5659
}
60+
public String getIncludedVersionsStr() { return includedVersionsStr; }
61+
5762

5863
private List<String> getExcludedVersions() {
5964
if (excludedVersionsStr == null) {
@@ -62,6 +67,13 @@ private List<String> getExcludedVersions() {
6267
return Arrays.asList(excludedVersionsStr.split(VERSIONS_SEPARATOR));
6368
}
6469

70+
private List<String> getIncludedVersions() {
71+
if (includedVersionsStr == null) {
72+
return Collections.emptyList();
73+
}
74+
return Arrays.asList(includedVersionsStr.split(VERSIONS_SEPARATOR));
75+
}
76+
6577
public Boolean isExcluded(String version) {
6678
// exit early if the version passed in is null or empty
6779
if (StringUtils.isBlank(version)) {
@@ -78,6 +90,22 @@ public Boolean isExcluded(String version) {
7890
return false;
7991
}
8092

93+
public Boolean isIncluded(String version) {
94+
// exit early if the version passed in is null or empty
95+
if (StringUtils.isBlank(version)) {
96+
return false;
97+
}
98+
for (String it : getIncludedVersions()) {
99+
// confirm that the excluded versions aren't null or empty
100+
// and if the version contains the exclusion thus it can be
101+
// anywhere in the string.
102+
if (StringUtils.isNotBlank(it) && version.contains(it)){
103+
return true;
104+
}
105+
}
106+
return false;
107+
}
108+
81109
@Override public String toString() {
82110
return "LibraryCachingConfiguration{refreshTimeMinutes=" + refreshTimeMinutes + ", excludedVersions="
83111
+ excludedVersionsStr + '}';
@@ -129,6 +157,38 @@ public FormValidation doClearCache(@QueryParameter String name, @QueryParameter
129157
}
130158
return FormValidation.ok("The cache dir was deleted successfully.");
131159
}
160+
}
132161

162+
/**
163+
* Method can be called from an external source to delete cache of a particular version of the shared library
164+
* Example: delete cache from through pipeline script once the build is successful
165+
* @param jenkinsLibrary Name of the shared library
166+
* @param version Name of the version to delete the cache
167+
* @throws IOException
168+
* @throws InterruptedException
169+
*/
170+
public static void deleteLibraryCacheForBranch(String jenkinsLibrary, String version) throws IOException, InterruptedException {
171+
if (LibraryCachingConfiguration.getGlobalLibrariesCacheDir().exists()) {
172+
for (FilePath libraryNamePath : LibraryCachingConfiguration.getGlobalLibrariesCacheDir().list("*-name.txt")) {
173+
String cacheName;
174+
try (InputStream stream = libraryNamePath.read()) {
175+
cacheName = IOUtils.toString(stream, StandardCharsets.UTF_8);
176+
177+
if (cacheName.equals(jenkinsLibrary)) {
178+
FilePath libraryCachePath = LibraryCachingConfiguration.getGlobalLibrariesCacheDir()
179+
.child(libraryNamePath.getName().replace("-name.txt", ""));
180+
ReentrantReadWriteLock retrieveLock = LibraryAdder.getReadWriteLockFor(libraryCachePath.getName());
181+
if (retrieveLock.writeLock().tryLock(10, TimeUnit.SECONDS)) {
182+
try {
183+
libraryCachePath.deleteRecursive();
184+
libraryNamePath.delete();
185+
} finally {
186+
retrieveLock.writeLock().unlock();
187+
}
188+
}
189+
}
190+
}
191+
}
192+
}
133193
}
134194
}

src/main/resources/org/jenkinsci/plugins/workflow/libs/LibraryCachingConfiguration/config.jelly

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ THE SOFTWARE.
3131
<f:entry title="${%Versions to exclude}" field="excludedVersionsStr">
3232
<f:textbox />
3333
</f:entry>
34+
<f:entry title="${%Versions to include}" field="includedVersionsStr">
35+
<f:textbox />
36+
</f:entry>
3437
<j:if test="${h.hasPermission(app.ADMINISTER)}">
3538
<f:entry title="${%Force clear cache}" field="forceDelete">
3639
<f:checkbox/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div>
2+
Space separated list of versions to include to allow caching via substring search using .contains() method. Ex: "release/ master".
3+
</div>
4+
<div>
5+
Note: Excluded versions will always take precedence over included versions
6+
</div>

src/test/java/org/jenkinsci/plugins/workflow/libs/LibraryAdderTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,7 @@ public class LibraryAdderTest {
420420
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
421421
globalLib.setDefaultVersion("master");
422422
globalLib.setImplicit(true);
423-
globalLib.setCachingConfiguration(new LibraryCachingConfiguration(60, ""));
423+
globalLib.setCachingConfiguration(new LibraryCachingConfiguration(60, "", ""));
424424
GlobalLibraries.get().setLibraries(Collections.singletonList(globalLib));
425425
// Create a folder library with the same name and which is also set up to enable caching.
426426
sampleRepo2.write("vars/folderLibVar.groovy", "def call() { jenkins.model.Jenkins.get().setSystemMessage('folder library') }");
@@ -430,7 +430,7 @@ public class LibraryAdderTest {
430430
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo2.toString(), "", "*", "", true)));
431431
folderLib.setDefaultVersion("master");
432432
folderLib.setImplicit(true);
433-
folderLib.setCachingConfiguration(new LibraryCachingConfiguration(60, ""));
433+
folderLib.setCachingConfiguration(new LibraryCachingConfiguration(60, "", ""));
434434
Folder f = r.jenkins.createProject(Folder.class, "folder1");
435435
f.getProperties().add(new FolderLibraries(Collections.singletonList(folderLib)));
436436
// Create a job that uses the folder library, which will take precedence over the global library, since they have the same name.
@@ -493,7 +493,7 @@ public void parallelBuildsDontInterfereWithExpiredCache() throws Throwable {
493493
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
494494
config.setDefaultVersion("master");
495495
config.setImplicit(true);
496-
config.setCachingConfiguration(new LibraryCachingConfiguration(30, null));
496+
config.setCachingConfiguration(new LibraryCachingConfiguration(30, null,null));
497497
GlobalLibraries.get().getLibraries().add(config);
498498
WorkflowJob p1 = r.createProject(WorkflowJob.class);
499499
WorkflowJob p2 = r.createProject(WorkflowJob.class);

src/test/java/org/jenkinsci/plugins/workflow/libs/LibraryCachingCleanupTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public void smokes() throws Throwable {
5959
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
6060
config.setDefaultVersion("master");
6161
config.setImplicit(true);
62-
config.setCachingConfiguration(new LibraryCachingConfiguration(30, null));
62+
config.setCachingConfiguration(new LibraryCachingConfiguration(30, null, null));
6363
GlobalLibraries.get().getLibraries().add(config);
6464
// Run build and check that cache gets created.
6565
WorkflowJob p = r.createProject(WorkflowJob.class);

src/test/java/org/jenkinsci/plugins/workflow/libs/LibraryCachingConfigurationTest.java

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,31 +61,57 @@ public class LibraryCachingConfigurationTest {
6161
private static int NO_REFRESH_TIME_MINUTES = 0;
6262

6363
private static String NULL_EXCLUDED_VERSION = null;
64+
private static String NULL_INCLUDED_VERSION = null;
65+
6466
private static String ONE_EXCLUDED_VERSION = "branch-1";
6567

68+
private static String ONE_INCLUDED_VERSION = "branch-1i";
69+
70+
6671
private static String MULTIPLE_EXCLUDED_VERSIONS_1 = "main";
72+
73+
private static String MULTIPLE_INCLUDED_VERSIONS_1 = "master";
74+
6775
private static String MULTIPLE_EXCLUDED_VERSIONS_2 = "branch-2";
76+
77+
private static String MULTIPLE_INCLUDED_VERSIONS_2 = "branch-2i";
78+
6879
private static String MULTIPLE_EXCLUDED_VERSIONS_3 = "branch-3";
80+
private static String MULTIPLE_INCLUDED_VERSIONS_3 = "branch-3i";
81+
6982

7083
private static String SUBSTRING_EXCLUDED_VERSIONS_1 = "feature/test-substring-exclude";
84+
85+
private static String SUBSTRING_INCLUDED_VERSIONS_1 = "feature_include/test-substring";
86+
7187
private static String SUBSTRING_EXCLUDED_VERSIONS_2 = "test-other-substring-exclude";
88+
private static String SUBSTRING_INCLUDED_VERSIONS_2 = "test-other-substring-include";
89+
7290

7391
private static String MULTIPLE_EXCLUDED_VERSIONS =
7492
MULTIPLE_EXCLUDED_VERSIONS_1 + " " +
7593
MULTIPLE_EXCLUDED_VERSIONS_2 + " " +
7694
MULTIPLE_EXCLUDED_VERSIONS_3;
7795

96+
private static String MULTIPLE_INCLUDED_VERSIONS =
97+
MULTIPLE_INCLUDED_VERSIONS_1 + " " +
98+
MULTIPLE_INCLUDED_VERSIONS_2 + " " +
99+
MULTIPLE_INCLUDED_VERSIONS_3;
100+
78101
private static String SUBSTRING_EXCLUDED_VERSIONS =
79102
"feature/ other-substring";
80103

104+
private static String SUBSTRING_INCLUDED_VERSIONS =
105+
"feature_include/ other-substring";
106+
81107
private static String NEVER_EXCLUDED_VERSION = "never-excluded-version";
82108

83109
@Before
84110
public void createCachingConfiguration() {
85-
nullVersionConfig = new LibraryCachingConfiguration(REFRESH_TIME_MINUTES, NULL_EXCLUDED_VERSION);
86-
oneVersionConfig = new LibraryCachingConfiguration(NO_REFRESH_TIME_MINUTES, ONE_EXCLUDED_VERSION);
87-
multiVersionConfig = new LibraryCachingConfiguration(REFRESH_TIME_MINUTES, MULTIPLE_EXCLUDED_VERSIONS);
88-
substringVersionConfig = new LibraryCachingConfiguration(REFRESH_TIME_MINUTES, SUBSTRING_EXCLUDED_VERSIONS);
111+
nullVersionConfig = new LibraryCachingConfiguration(REFRESH_TIME_MINUTES, NULL_EXCLUDED_VERSION, NULL_INCLUDED_VERSION);
112+
oneVersionConfig = new LibraryCachingConfiguration(NO_REFRESH_TIME_MINUTES, ONE_EXCLUDED_VERSION, ONE_INCLUDED_VERSION);
113+
multiVersionConfig = new LibraryCachingConfiguration(REFRESH_TIME_MINUTES, MULTIPLE_EXCLUDED_VERSIONS, MULTIPLE_INCLUDED_VERSIONS);
114+
substringVersionConfig = new LibraryCachingConfiguration(REFRESH_TIME_MINUTES, SUBSTRING_EXCLUDED_VERSIONS, SUBSTRING_INCLUDED_VERSIONS);
89115
}
90116

91117
@Issue("JENKINS-66045") // NPE getting excluded versions
@@ -125,6 +151,15 @@ public void getExcludedVersionsStr() {
125151
assertThat(substringVersionConfig.getExcludedVersionsStr(), is(SUBSTRING_EXCLUDED_VERSIONS));
126152
}
127153

154+
@Test
155+
@WithoutJenkins
156+
public void getIncludedVersionsStr() {
157+
assertThat(nullVersionConfig.getIncludedVersionsStr(), is(NULL_INCLUDED_VERSION));
158+
assertThat(oneVersionConfig.getIncludedVersionsStr(), is(ONE_INCLUDED_VERSION));
159+
assertThat(multiVersionConfig.getIncludedVersionsStr(), is(MULTIPLE_INCLUDED_VERSIONS));
160+
assertThat(substringVersionConfig.getIncludedVersionsStr(), is(SUBSTRING_INCLUDED_VERSIONS));
161+
}
162+
128163
@Test
129164
@WithoutJenkins
130165
public void isExcluded() {
@@ -155,6 +190,23 @@ public void isExcluded() {
155190
assertFalse(substringVersionConfig.isExcluded(null));
156191
}
157192

193+
@Test
194+
@WithoutJenkins
195+
public void isIncluded() {
196+
assertFalse(nullVersionConfig.isIncluded(NULL_INCLUDED_VERSION));
197+
assertFalse(nullVersionConfig.isIncluded(""));
198+
199+
assertTrue(oneVersionConfig.isIncluded(ONE_INCLUDED_VERSION));
200+
201+
assertTrue(multiVersionConfig.isIncluded(MULTIPLE_INCLUDED_VERSIONS_1));
202+
assertTrue(multiVersionConfig.isIncluded(MULTIPLE_INCLUDED_VERSIONS_2));
203+
assertTrue(multiVersionConfig.isIncluded(MULTIPLE_INCLUDED_VERSIONS_3));
204+
205+
assertTrue(substringVersionConfig.isIncluded(SUBSTRING_INCLUDED_VERSIONS_1));
206+
assertTrue(substringVersionConfig.isIncluded(SUBSTRING_INCLUDED_VERSIONS_2));
207+
208+
}
209+
158210
@Test
159211
public void clearCache() throws Exception {
160212
sampleRepo.init();
@@ -165,7 +217,7 @@ public void clearCache() throws Exception {
165217
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
166218
config.setDefaultVersion("master");
167219
config.setImplicit(true);
168-
config.setCachingConfiguration(new LibraryCachingConfiguration(30, null));
220+
config.setCachingConfiguration(new LibraryCachingConfiguration(30, null, "master"));
169221
GlobalLibraries.get().getLibraries().add(config);
170222
// Run build and check that cache gets created.
171223
WorkflowJob p = r.createProject(WorkflowJob.class);
@@ -182,4 +234,29 @@ public void clearCache() throws Exception {
182234
assertThat(new File(cache.withSuffix("-name.txt").getRemote()), not(anExistingFile()));
183235
}
184236

237+
@Test
238+
public void clearCacheConflict() throws Exception {
239+
sampleRepo.init();
240+
sampleRepo.write("vars/foo.groovy", "def call() { echo 'foo' }");
241+
sampleRepo.git("add", "vars");
242+
sampleRepo.git("commit", "--message=init");
243+
LibraryConfiguration config = new LibraryConfiguration("library",
244+
new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
245+
config.setDefaultVersion("master");
246+
config.setImplicit(true);
247+
// Same version specified in both include and exclude version
248+
//Exclude takes precedence
249+
config.setCachingConfiguration(new LibraryCachingConfiguration(30, "master", "master"));
250+
GlobalLibraries.get().getLibraries().add(config);
251+
// Run build and check that cache gets created.
252+
WorkflowJob p = r.createProject(WorkflowJob.class);
253+
p.setDefinition(new CpsFlowDefinition("foo()", true));
254+
WorkflowRun b = r.buildAndAssertSuccess(p);
255+
LibrariesAction action = b.getAction(LibrariesAction.class);
256+
LibraryRecord record = action.getLibraries().get(0);
257+
FilePath cache = LibraryCachingConfiguration.getGlobalLibrariesCacheDir().child(record.getDirectoryName());
258+
assertThat(new File(cache.getRemote()), not(anExistingDirectory()));
259+
assertThat(new File(cache.withSuffix("-name.txt").getRemote()), not(anExistingFile()));
260+
}
261+
185262
}

src/test/java/org/jenkinsci/plugins/workflow/libs/ResourceStepTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public class ResourceStepTest {
7171
initFixedContentLibrary();
7272

7373
LibraryConfiguration libraryConfig = new LibraryConfiguration("stuff", new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
74-
libraryConfig.setCachingConfiguration(new LibraryCachingConfiguration(0, ""));
74+
libraryConfig.setCachingConfiguration(new LibraryCachingConfiguration(0, "",""));
7575
GlobalLibraries.get().setLibraries(Collections.singletonList(libraryConfig));
7676
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
7777

@@ -92,7 +92,7 @@ public class ResourceStepTest {
9292
initFixedContentLibrary();
9393

9494
LibraryConfiguration libraryConfig = new LibraryConfiguration("stuff", new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
95-
libraryConfig.setCachingConfiguration(new LibraryCachingConfiguration(0, "test_unused other"));
95+
libraryConfig.setCachingConfiguration(new LibraryCachingConfiguration(0, "test_unused other", null));
9696
GlobalLibraries.get().setLibraries(Collections.singletonList(libraryConfig));
9797
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
9898

@@ -114,7 +114,7 @@ public class ResourceStepTest {
114114
initFixedContentLibrary();
115115

116116
LibraryConfiguration libraryConfig = new LibraryConfiguration("stuff", new SCMSourceRetriever(new GitSCMSource(null, sampleRepo.toString(), "", "*", "", true)));
117-
libraryConfig.setCachingConfiguration(new LibraryCachingConfiguration(60, "test_unused other"));
117+
libraryConfig.setCachingConfiguration(new LibraryCachingConfiguration(60, "test_unused other", ""));
118118
GlobalLibraries.get().setLibraries(Collections.singletonList(libraryConfig));
119119
WorkflowJob p = r.jenkins.createProject(WorkflowJob.class, "p");
120120

0 commit comments

Comments
 (0)