blob: 7f37536d08624b587569e2f79a2c64ef7c9d7993 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "org.asciidoctor:asciidoctorj:1.6.2"
}
}
plugins {
id 'java'
id 'com.github.jruby-gradle.base' version '2.0.0'
}
// This project does not contribute anything to main dependencies.
versionsLock {
testProject()
}
description = 'Solr reference guide'
// Use an internal proxy to ruby gems.
repositories {
ruby.gems()
}
configurations {
depVer
refGuide
}
dependencies {
// Dependencies to compile internal tools.
implementation('org.asciidoctor:asciidoctorj')
implementation('com.vaadin.external.google:android-json')
implementation('org.jsoup:jsoup')
implementation('org.slf4j:jcl-over-slf4j')
implementation('org.slf4j:slf4j-simple')
implementation('org.apache.logging.log4j:log4j-core')
implementation('com.google.guava:guava')
implementation('commons-codec:commons-codec')
// Dependencies referenced in the guide.
depVer('commons-codec:commons-codec')
depVer('io.dropwizard.metrics:metrics-core')
depVer('org.apache.logging.log4j:log4j-core')
depVer('org.apache.opennlp:opennlp-tools')
depVer('org.apache.tika:tika-core')
depVer('org.apache.zookeeper:zookeeper')
// jekyll dependencies
gems 'rubygems:jekyll:3.5.2'
gems 'rubygems:jekyll-asciidoc:3.0.0'
// don't know why we have to explicitly add these deps but it doesn't resolve them
// automatically.
gems 'rubygems:tilt:2.0.10'
gems 'rubygems:slim:4.0.1'
gems 'rubygems:concurrent-ruby:1.0.5'
}
sourceSets {
refGuide {
java {
srcDirs = []
}
resources {
srcDirs = ['src']
}
}
main {
java {
srcDirs = ['tools']
}
}
test {
java {
srcDirs = []
}
}
}
ext {
mainPage = "index"
// the "MAJOR.MINOR" version of solr this guide is about (guides aren't specific to BUGFIX releases)
// So on 'branch_9_9' where 'version' may be 9.9.0, 9.9.1, 9.9.9, etc..; solrDocsVersion = 9.9
solrDocsVersion = "${version}".replaceAll(/^(\d+\.\d+)(|\..*)$/, "\$1")
// the "MAJOR_MINOR" version as a path for publishing the guide
// So on 'branch_9_9' where solrDocsVersion = 9.9; solrGuideVersionPath => 9_9
solrGuideVersionPath = "${solrDocsVersion}".replaceAll(/^(\d+)\.(\d+)$/, "\$1_\$2")
// these will be used to dynamically build up (nearly) identical tasks with consistent names
// for building & link checking the ref guide. One using absolute URLs to javadocs, the
// other using local paths that can be validated by the link checker.
htmlSiteDetails =
[name: 'Site',
path: 'html-site',
desc: 'HTML Site for publishing to the Solr website',
props: [
htmlSolrJavadocs: "https://lucene.apache.org/solr/${solrGuideVersionPath}_0/",
htmlLuceneJavadocs: "https://lucene.apache.org/core/${solrGuideVersionPath}_0/"
]
]
linkCheckSiteDetails =
[name: 'LocalJavadocLinksSite',
path: 'local-jdoc-links-site',
desc: 'Local Site for checking javadoc links',
// NOTE: extra '../' because we'll in a sub-dir of buildDir that will be built later...
props: [
htmlSolrJavadocs : 'link:../' + buildDir.toPath().relativize(project(':solr:documentation').docroot.toPath()).toString().replace(File.separator, '/'),
htmlLuceneJavadocs : skipLucene ? 'link:../' : 'link:../' + buildDir.toPath().relativize(project(':lucene:documentation').docroot.toPath()).toString().replace(File.separator, '/')
]
]
}
// dynamically define the 2 variations of each target that we need...
[ htmlSiteDetails, linkCheckSiteDetails ].each{ details ->
final def contentDir = file("${buildDir}/${details.path}-content")
final def htmlDir = file("${buildDir}/${details.path}")
final def extraProps = details.props.clone()
extraProps.htmlOutDir = "../${details.path}"
task "prepare${details.name}Sources"(type: PrepareSources) {
outDir contentDir
props extraProps
}
task "build${details.name}"(type: com.github.jrubygradle.JRubyExec) {
dependsOn "prepare${details.name}Sources"
group "Documentation"
description "Builds the ${details.desc}"
inputs.dir contentDir
outputs.dir htmlDir
script 'jekyll'
scriptArgs 'build' //, '--verbose'
workingDir contentDir
}
task "check${details.name}"(type: JavaExec) {
dependsOn "build${details.name}"
classpath = sourceSets.main.runtimeClasspath
main = 'CheckLinksAndAnchors'
workingDir = contentDir
// NOTE: even for the 'real' site, we check all relative links
// (there will just be less of them, and this way any stray hardcoded
// '../../' paths can be caught more easily)
args([ htmlDir, "-check-all-relative-links" ])
}
}
// Hook in our dependency on all top level documentation in order to check local javadoc links
checkLocalJavadocLinksSite.dependsOn ':documentation'
// Hook up custom tasks with standard tasks.
check.dependsOn checkLocalJavadocLinksSite, checkSite
// Hook site building to assemble.
assemble.dependsOn buildSite
abstract class PrepareSources extends DefaultTask {
/** Original Source files we'll be syncing <b>FROM</b> */
@InputDirectory
public File getSrcDir() {
return getProject().file("src")
}
/**
* Where we sync the source files <b>TO</b>
*/
public void setOutDir(File outDir) {
this.outDir = outDir;
getOutputs().dir(outDir);
}
public File outDir;
/**
* Task specific props
*/
@Input
public Map<String,String> getProps() {
return props;
}
public void setProps(Map<String,String> props) {
this.props = props;
}
private Map<String,String> props;
/**
* Basic properties that should be the same for all tasks of this type
*/
@Input
public Map<String,String> getStandardProps() {
final Project p = getProject();
return [
javadocLink : "https://docs.oracle.com/en/java/javase/11/docs/api/",
solrGuideDraftStatus : p.propertyOrDefault('solrGuideDraft', "true").toBoolean() ? "DRAFT" : "",
solrRootPath : p.project(':solr').projectDir.toString() + File.separator,
solrDocsVersion : p.property('solrDocsVersion'),
solrGuideVersionPath : p.property('solrGuideVersionPath'),
buildDate : p.property('buildDate'),
buildYear : p.property('buildYear'),
];
}
public PrepareSources() {
// setup 'dependsOn classes, configurations.depVer' here
// so that it's not neccessary for every task impl to declare redundently
final Project p = getProject();
dependsOn(p.getConfigurations().getByName('depVer'))
dependsOn(p.getTasksByName('classes', false))
}
@TaskAction
public void doCopy() {
final Project p = getProject();
final Configuration depVer = p.getConfigurations().getByName('depVer');
// start with any task (instance) specific props.
final def props = getProps().clone();
// then add/override with anystandard props that should alwasy be used
getStandardProps().each { k, v -> props[k] = v };
// These properties have to be resolved after the configuration phase is complete
// (palantir's constraint) so we can't use them as input for caches. But as this task
// depends on the configuration, it's used correctly
[
["ivyCommonsCodec", "commons-codec", "commons-codec"],
["ivyDropwizardMetrics", "io.dropwizard.metrics", "metrics-core"],
["ivyLog4j", "org.apache.logging.log4j", "log4j-core"],
["ivyOpennlpTools", "org.apache.opennlp", "opennlp-tools"],
["ivyTika", "org.apache.tika", "tika-core"],
["ivyZookeeper", "org.apache.zookeeper", "zookeeper"],
].each { prop, depGroup, depId ->
props[prop] = p.getVersion(depGroup, depId, depVer)
}
final File intoDir = this.outDir;
// Emit info about properties for clarity.
logger.lifecycle('Syncing source files to {} using props:\n{}',
intoDir, props.collect({ k, v -> " ${k} -> ${v}" }).join('\n'))
// Escape all the properties, so they can be inserted into YAML templates.
final def escapedProps = props.collectEntries{k, v -> [k, v.replace("'","''")]}
final WorkResult syncResult = p.sync({ copySpec ->
copySpec.setFilteringCharset('UTF-8');
copySpec.from(getSrcDir(), { raw ->
raw.exclude('**/*.template')
})
copySpec.from(getSrcDir(), { templated ->
templated.include('**/*.template')
templated.rename('(.+)\\.template', '$1')
templated.expand(escapedProps)
})
copySpec.into(intoDir);
});
setDidWork(syncResult.getDidWork());
if (syncResult.getDidWork()) {
// if sync did work, that means we need to rebuild the nav data files...
p.javaexec({ execSpec ->
execSpec.setClasspath( getProject().getConvention()
.getPlugin(JavaPluginConvention.class)
.getSourceSets().getByName("main").getRuntimeClasspath() )
execSpec.setWorkingDir( intoDir )
execSpec.setMain( 'BuildNavDataFiles' )
execSpec.args([ intoDir, p.property('mainPage') ])
})
}
}
}