Skip to content

Commit

Permalink
Added option to control whether or not artifacts are downloaded
Browse files Browse the repository at this point in the history
There is a new option (downloadArtifacts) that controls whether or not
artifacts are downloaded. If they are (the default to maintain backwards
compatibility) then the trigger will check to see if any artifacts inside
a dependency have changed with out changing the version number.

If artifacts are not configured for download, the trigger only checks to
make sure the resolved dependency version has not changed.

Fixes JENKINS-28044
  • Loading branch information
rjclark committed Apr 25, 2015
1 parent adcf390 commit 3897869
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 22 deletions.
35 changes: 27 additions & 8 deletions src/main/java/org/jenkinsci/plugins/ivytrigger/IvyTrigger.java
Expand Up @@ -48,18 +48,21 @@ public class IvyTrigger extends AbstractTriggerByFullContext<IvyTriggerContext>

private boolean enableConcurrentBuild;

private boolean downloadArtifacts;

private transient FilePathFactory filePathFactory;

private transient PropertiesFileContentExtractor propertiesFileContentExtractor;

@DataBoundConstructor
public IvyTrigger(String cronTabSpec, String ivyPath, String ivySettingsPath, String propertiesFilePath, String propertiesContent, LabelRestrictionClass labelRestriction, boolean enableConcurrentBuild, boolean debug) throws ANTLRException {
public IvyTrigger(String cronTabSpec, String ivyPath, String ivySettingsPath, String propertiesFilePath, String propertiesContent, LabelRestrictionClass labelRestriction, boolean enableConcurrentBuild, boolean debug, boolean downloadArtifacts) throws ANTLRException {
super(cronTabSpec, (labelRestriction == null) ? null : labelRestriction.getTriggerLabel(), enableConcurrentBuild);
this.ivyPath = Util.fixEmpty(ivyPath);
this.ivySettingsPath = Util.fixEmpty(ivySettingsPath);
this.propertiesFilePath = Util.fixEmpty(propertiesFilePath);
this.propertiesContent = Util.fixEmpty(propertiesContent);
this.debug = debug;
this.downloadArtifacts = downloadArtifacts;
this.labelRestriction = (labelRestriction == null) ? false : true;
this.enableConcurrentBuild = enableConcurrentBuild;
}
Expand Down Expand Up @@ -89,6 +92,11 @@ public boolean isDebug() {
return debug;
}

@SuppressWarnings("unused")
public boolean isDownloadArtifacts() {
return downloadArtifacts;
}

public boolean isLabelRestriction() {
return labelRestriction;
}
Expand Down Expand Up @@ -191,6 +199,10 @@ protected IvyTriggerContext getContext(Node pollingNode, XTriggerLog log) throws
ivySettingsUrl == null ? ivySettingsFilePath.getRemote() : ivySettingsUrl
.toString()));

if ( downloadArtifacts ) {
log.info("Artifacts in dependencies will be downloaded");
}

PropertiesFileContentExtractor propertiesFileContentExtractor = new PropertiesFileContentExtractor(new FilePathFactory());
String propertiesFileContent = propertiesFileContentExtractor.extractPropertiesFileContents(propertiesFilePath, project, pollingNode, log, envVars);
String propertiesContentResolved = Util.replaceMacro(propertiesContent, envVars);
Expand Down Expand Up @@ -221,7 +233,7 @@ private Map<String, IvyDependencyValue> getDependenciesMapForNode(Node launcherN
if (launcherNode != null) {
FilePath launcherFilePath = launcherNode.getRootPath();
if (launcherFilePath != null) {
dependenciesMap = launcherFilePath.act(new IvyTriggerEvaluator(job.getName(), ivyFilePath, ivySettingsFilePath, ivySettingsURL, propertiesFilePath, propertiesContent, log, debug, envVars));
dependenciesMap = launcherFilePath.act(new IvyTriggerEvaluator(job.getName(), ivyFilePath, ivySettingsFilePath, ivySettingsURL, propertiesFilePath, propertiesContent, log, debug, downloadArtifacts, envVars));
}
}
return dependenciesMap;
Expand All @@ -240,7 +252,7 @@ private static URL getRemoteURL(String filename, XTriggerLog log) {
try {
settingsUrl = new URL(filename);
} catch (MalformedURLException e) {
log.info("URL is not well-fotmatted. Assuming it is a local file: " + filename);
log.info("URL is not well-formatted. Assuming it is a local file: " + filename);
return null;
}
final String scheme = settingsUrl.getProtocol();
Expand Down Expand Up @@ -359,13 +371,20 @@ private boolean isDependencyChanged(XTriggerLog log,
log.info("....The number of artifacts of the dependency has changed.");
}

//Check if there is at least one change to previous recording artifacts
log.info("...Checking comparison to previous recorded artifacts.");
for (IvyArtifactValue ivyArtifactValue : previousArtifactValueList) {
if (isArtifactsChanged(log, ivyArtifactValue, newArtifactValueList)) {
return true;
// Check if there is at least one change to previous recording artifacts
// Only do this if we've been told to download artifacts. Otherwise there is
// nothing to compare.
if ( downloadArtifacts ) {
log.info("...Checking comparison to previous recorded artifacts.");
for ( IvyArtifactValue ivyArtifactValue : previousArtifactValueList ) {
if ( isArtifactsChanged(log, ivyArtifactValue, newArtifactValueList) ) {
return true;
}
}
}
else {
log.info("...Artifacts were not configured for download, no individual artifact checks made.");
}

return false;
}
Expand Down
Expand Up @@ -13,6 +13,7 @@
import org.apache.ivy.core.module.id.ModuleRevisionId;
import org.apache.ivy.core.report.ResolveReport;
import org.apache.ivy.core.resolve.IvyNode;
import org.apache.ivy.core.resolve.ResolveOptions;
import org.apache.ivy.core.settings.IvySettings;
import org.jenkinsci.lib.xtrigger.XTriggerException;
import org.jenkinsci.lib.xtrigger.XTriggerLog;
Expand Down Expand Up @@ -43,6 +44,8 @@ public class IvyTriggerEvaluator implements FilePath.FileCallable<Map<String, Iv

private boolean debug;

private final boolean downloadArtifacts;

private Map<String, String> envVars;

public IvyTriggerEvaluator(String namespace,
Expand All @@ -53,6 +56,7 @@ public IvyTriggerEvaluator(String namespace,
String propertiesContent,
XTriggerLog log,
boolean debug,
boolean downloadArtifacts,
Map<String, String> envVars) {
this.namespace = namespace;
this.ivyFilePath = ivyFilePath;
Expand All @@ -62,6 +66,7 @@ public IvyTriggerEvaluator(String namespace,
this.propertiesContent = propertiesContent;
this.log = log;
this.debug = debug;
this.downloadArtifacts = downloadArtifacts;
this.envVars = envVars;
}

Expand All @@ -70,7 +75,14 @@ public Map<String, IvyDependencyValue> invoke(File launchDir, VirtualChannel cha
try {
Ivy ivy = getIvyObject(launchDir, log);
log.info("\nResolving Ivy dependencies.");
ResolveReport resolveReport = ivy.resolve(new File(ivyFilePath.getRemote()));

ResolveOptions options = new ResolveOptions();
options.setDownload(downloadArtifacts);

// Need to be able to pass a URL to resolve() so that we can also pass in some options
final URL ivyFileURL = new File(ivyFilePath.getRemote()).toURI().toURL();

ResolveReport resolveReport = ivy.resolve(ivyFileURL, options);
if (resolveReport.hasError()) {
List problems = resolveReport.getAllProblemMessages();
if (problems != null && !problems.isEmpty()) {
Expand Down Expand Up @@ -233,20 +245,25 @@ private Map<String, IvyDependencyValue> getMapDependencies(Ivy ivy, ResolveRepor
IvyNode dependencyNode = (IvyNode) dependencyObject;
ModuleRevisionId moduleRevisionId = dependencyNode.getResolvedId();
String moduleRevision = moduleRevisionId.getRevision();
Artifact[] artifacts = dependencyNode.getAllArtifacts();

List<IvyArtifactValue> ivyArtifactValues = new ArrayList<IvyArtifactValue>();
if (artifacts != null) {
for (Artifact artifact : artifacts) {
IvySettings settings = ivy.getSettings();
File cacheDirFile = settings.getDefaultRepositoryCacheBasedir();
RepositoryCacheManager repositoryCacheManager = new DefaultRepositoryCacheManager("repo", settings, cacheDirFile);
ArtifactOrigin artifactOrigin = repositoryCacheManager.getSavedArtifactOrigin(artifact);
if (artifactOrigin != null && artifactOrigin.isLocal()) {
String location = artifactOrigin.getLocation();
File artifactFile = new File(location);
if (artifactFile != null) {
long lastModificationDate = artifactFile.lastModified();
ivyArtifactValues.add(new IvyArtifactValue(artifact.getName(), artifact.getExt(), lastModificationDate));

if ( dependencyNode.isDownloaded() ) {
Artifact[] artifacts = dependencyNode.getAllArtifacts();

if (artifacts != null) {
for (Artifact artifact : artifacts) {
IvySettings settings = ivy.getSettings();
File cacheDirFile = settings.getDefaultRepositoryCacheBasedir();
RepositoryCacheManager repositoryCacheManager = new DefaultRepositoryCacheManager("repo", settings, cacheDirFile);
ArtifactOrigin artifactOrigin = repositoryCacheManager.getSavedArtifactOrigin(artifact);
if (artifactOrigin != null && artifactOrigin.isLocal()) {
String location = artifactOrigin.getLocation();
File artifactFile = new File(location);
if (artifactFile != null) {

This comment has been minimized.

Copy link
@darxriggs

darxriggs Jan 7, 2019

Contributor

Do you really mean artifactFile != null?
This variable is assigned one line above and therefore never null.
Did you possibly check for artifactFile.exists()?

long lastModificationDate = artifactFile.lastModified();
ivyArtifactValues.add(new IvyArtifactValue(artifact.getName(), artifact.getExt(), lastModificationDate));
}
}
}
}
Expand Down
Expand Up @@ -23,6 +23,11 @@
<f:checkbox name="debug" checked="${instance.debug}"/>
</f:entry>

<f:entry field="downloadArtifacts"
title="${%Download artifacts for dependencies to see if they have changed}">
<f:checkbox name="downloadArtifacts" checked="${instance.downloadArtifacts}" default="true"/>
</f:entry>

<f:entry field="enableConcurrentBuild" title="${%Enable Concurrent Build}">
<f:checkbox name="enableConcurrentBuild" checked="${instance.enableConcurrentBuild}"/>
</f:entry>
Expand Down
@@ -0,0 +1,9 @@
<div>
<p>
Whether or not to download the artifacts within a dependency.<br/>
If this is false, then much less disk space is used. However a change in the
artifacts, or the addition or removal of artifacts, of a dependency that does
not <strong>also</strong> cause a version number change in the dependency
will not be detected.
</p>
</div>

0 comments on commit 3897869

Please sign in to comment.