| /* |
| * 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 |