blob: eb52de7dae8eb5ab8165cfcb94f8dc1f36cc4d36 [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.
*/
// Define common lifecycle tasks and artifact types
apply plugin: "base"
// Publish website to asf-git branch.
apply plugin: 'org.ajoberstar.grgit'
def dockerImageTag = 'beam-website'
def dockerWorkDir = "/repo"
def buildDir = "${project.rootDir}/build/website"
def buildContentDir = "${project.rootDir}/build/website/generated-content"
def repoContentDir = "${project.rootDir}/website/generated-content"
def commitedChanges = false
def gitboxUrl = project.findProperty('gitPublishRemote') ?: 'https://gitbox.apache.org/repos/asf/beam.git'
def shell = { cmd ->
println cmd
exec {
executable 'sh'
args '-c', cmd
}
}
def envdir = "${buildDir}/gradleenv"
task setupVirtualenv {
doLast {
exec {
commandLine 'virtualenv', "${envdir}"
}
exec {
executable 'sh'
args '-c', ". ${envdir}/bin/activate && pip install beautifulsoup4"
}
}
outputs.dirs(envdir)
}
task buildDockerImage(type: Exec) {
inputs.files 'Gemfile', 'Gemfile.lock'
commandLine 'docker', 'build', '-t', dockerImageTag, '.'
}
task createDockerContainer(type: Exec) {
dependsOn buildDockerImage
standardOutput = new ByteArrayOutputStream()
ext.containerId = {
return standardOutput.toString().trim()
}
commandLine '/bin/bash', '-c',
"docker create -v $project.rootDir:$dockerWorkDir -u \$(id -u):\$(id -g) $dockerImageTag"
}
task startDockerContainer(type: Exec) {
dependsOn createDockerContainer
ext.containerId = {
return createDockerContainer.containerId()
}
commandLine 'docker', 'start',
"${->createDockerContainer.containerId()}" // Lazily evaluate containerId.
}
task stopAndRemoveDockerContainer(type: Exec) {
commandLine 'docker', 'rm', '-f', "${->createDockerContainer.containerId()}"
}
task setupBuildDir(type: Copy) {
from('.') {
include 'Gemfile*'
include 'Rakefile'
}
into buildDir
}
task cleanWebsite(type: Delete) {
delete buildDir
}
clean.dependsOn cleanWebsite
task buildWebsite(type: Exec) {
def baseurlFlag = project.findProperty('githubPullRequestId') ? "--baseurl=/${project.findProperty('githubPullRequestId')}" : ''
dependsOn startDockerContainer, setupBuildDir
finalizedBy stopAndRemoveDockerContainer
inputs.files 'Gemfile.lock', '_config.yml'
inputs.dir 'src'
inputs.property 'baseurl', baseurlFlag
outputs.dir "$buildDir/.sass-cache"
outputs.dir buildContentDir
commandLine 'docker', 'exec',
"${->startDockerContainer.containerId()}", '/bin/bash', '-c',
"""cd $dockerWorkDir/build/website && \
bundle exec jekyll build \
--config $dockerWorkDir/website/_config.yml \
--incremental ${baseurlFlag} \
--source $dockerWorkDir/website/src
"""
}
build.dependsOn buildWebsite
task testWebsite(type: Exec) {
dependsOn startDockerContainer, buildWebsite
finalizedBy stopAndRemoveDockerContainer
inputs.files "$buildDir/Rakefile"
inputs.dir buildContentDir
commandLine 'docker', 'exec',
"${->startDockerContainer.containerId()}", '/bin/bash', '-c',
"""cd $dockerWorkDir/build/website && \
bundle exec rake test"""
}
check.dependsOn testWebsite
task preCommit {
dependsOn testWebsite
}
// Creates a new commit on asf-site branch
task commitWebsite << {
assert file("${buildContentDir}/index.html").exists()
// Generated javadoc and pydoc content is not built or stored in this repo.
assert !file("${buildContentDir}/documentation/sdks/javadoc").exists()
assert !file("${buildContentDir}/documentation/sdks/pydoc").exists()
def git = grgit.open()
// get the latest commit on master
def latestCommit = grgit.log(maxCommits: 1)[0].abbreviatedId
shell "git fetch --force origin +asf-site:asf-site"
git.checkout(branch: 'asf-site')
// Delete the previous content.
git.remove(patterns: [ 'website/generated-content' ])
assert !file("${repoContentDir}/index.html").exists()
delete repoContentDir
// Copy the built content and add it.
copy {
from buildContentDir
into repoContentDir
}
assert file("${repoContentDir}/index.html").exists()
git.add(patterns: ['website/generated-content'])
def currentDate = new Date().format('yyyy/MM/dd HH:mm:ss')
String message = "Publishing website ${currentDate} at commit ${latestCommit}"
if (git.status().isClean()) {
println 'No changes to commit'
} else {
println 'Creating commit for changes'
commitedChanges = true
git.commit(message: message)
}
}
/*
* Pushes the asf-site branch commits.
*
* This requires write access to the asf-site branch and can be run on
* Jenkins executors with the git-websites label.
*
* For more details on publishing, see:
* https://www.apache.org/dev/project-site.html
* https://github.com/apache/infrastructure-puppet/blob/deployment/modules/gitwcsub/files/config/gitwcsub.cfg
*
* You can test this locally with a forked repository by manually adding the
* website-publish remote pointing to your forked repository, for example:
* git remote add website-publish git@github.com:${GITUSER}/beam.git
* because the remote is only added if it doesn't exist. The remote needs
* to be added before every execution of the publishing.
*/
task publishWebsite << {
def git = grgit.open()
git.checkout(branch: 'asf-site')
if (!commitedChanges) {
println 'No changes to push'
return
}
// Because git.push() fails to authenticate, run git push directly.
shell "git push ${gitboxUrl} asf-site"
}
commitWebsite.dependsOn testWebsite
publishWebsite.dependsOn commitWebsite
/*
* Stages a pull request on GCS
* For example:
* ./gradlew :beam-website:stageWebsite -PgithubPullRequestId=${ghprbPullId} -PwebsiteBucket=foo
*/
task stageWebsite << {
assert project.hasProperty('githubPullRequestId')
assert githubPullRequestId.isInteger()
def gcs_bucket = project.findProperty('websiteBucket') ?: 'apache-beam-website-pull-requests'
def gcs_path = "gs://${gcs_bucket}/${githubPullRequestId}"
// Remove current site if it exists.
shell "gsutil -m rm -r -f ${gcs_path} || true"
// Fixup the links to index.html files
shell "cd ${buildDir} && ln -s generated-content content || true"
shell ". ${envdir}/bin/activate && cd ${buildDir} && " +
"python ${project.rootDir}/website/.jenkins/append_index_html_to_internal_links.py"
// Copy the build website to GCS
shell "gsutil -m cp -r ${buildContentDir} ${gcs_path}"
println "Website published to http://${gcs_bucket}." +
"storage.googleapis.com/${githubPullRequestId}/index.html"
}
stageWebsite.dependsOn setupVirtualenv
stageWebsite.dependsOn buildWebsite