CI now builds docs website and deploys it to /%version% path

Summary:
Copy of #5760 reverted merge.

We need to preserve history of docs changes on the webserver.
The goal is to allow users to browse outdated versions of docs.
To make things simple all websites will be released to https://facebook.github.io/react-native/releases/version/XX folder when there is a branch cut.

I switched from Travis CI to Cirle CI because it works faster and I am more familiar with it.

How it works:

1. If code is pushed to `master` branch then CI will build a fresh version of docs and put it in https://github.com/facebook/react-native/tree/gh-pages/releases/next folder.
Github will serve this website from https://facebook.github.io/react-native/releases/version/next URL.
All relative URLs will work within that website

2. If code is pushed to `0.20-stable` branch then CI will build a fresh version of docs and put it in https://github.com/facebook/react-native/tree/gh-pages/releases/0.20 folder.
Github will serve this website from https://facebook.github.io/react-native/releases/v
Closes https://github.com/facebook/react-native/pull/5873

Reviewed By: svcscm

Differential Revision: D2926901

Pulled By: androidtrunkagent

fb-gh-sync-id: 16aea430bac815933d9c603f03921cc6353906f1
shipit-source-id: 16aea430bac815933d9c603f03921cc6353906f1
This commit is contained in:
Konstantin Raev
2016-02-11 06:16:34 -08:00
committed by facebook-github-bot-0
parent 0b89b18b1b
commit 6f1417c849
44 changed files with 234 additions and 186 deletions

1
website/.gitignore vendored
View File

@@ -1,3 +1,4 @@
src/react-native/docs/**
core/metadata.js
*.log
/build/

View File

@@ -17,14 +17,8 @@ Anytime you change the contents, just refresh the page and it's going to be upda
# Publish the website
First setup your environment by having two folders, one `react-native` and one `react-native-gh-pages`. The publish script expects those exact names.
```sh
./setup.sh
cd website
npm run publish-website
```
Then, after you've done changes, just run the command and it'll automatically build the static version of the site and publish it to gh-pages.
```sh
./publish.sh
```

View File

@@ -72,7 +72,7 @@ var DocsSidebar = React.createClass({
if (metadata.permalink.match(/^https?:/)) {
return metadata.permalink;
}
return '/react-native/' + metadata.permalink + '#content';
return metadata.permalink + '#content';
},
render: function() {

View File

@@ -14,11 +14,11 @@ var AlgoliaDocSearch = require('AlgoliaDocSearch');
var HeaderLinks = React.createClass({
linksInternal: [
{section: 'docs', href: '/react-native/docs/getting-started.html', text: 'Docs'},
{section: 'support', href: '/react-native/support.html', text: 'Support'},
{section: 'docs', href: 'docs/getting-started.html', text: 'Docs'},
{section: 'support', href: 'support.html', text: 'Support'},
{section: 'releases', href: 'https://github.com/facebook/react-native/releases', text: 'Releases'},
{section: 'newsletter', href: 'http://reactnative.cc', text: 'Newsletter'},
{section: 'showcase', href: '/react-native/showcase.html', text: 'Showcase'},
{section: 'showcase', href: 'showcase.html', text: 'Showcase'},
],
linksExternal: [
{section: 'github', href: 'https://github.com/facebook/react-native', text: 'GitHub'},

View File

@@ -11,9 +11,12 @@
var React = require('React');
var HeaderLinks = require('HeaderLinks');
var Metadata = require('Metadata');
var Site = React.createClass({
render: function() {
const path = Metadata.config.RN_DEPLOYMENT_PATH;
var basePath = '/react-native/' + (path ? path + '/' : '');
var title = this.props.title ? this.props.title + ' ' : '';
var currentYear = (new Date()).getFullYear();
title += 'React Native | A framework for building native apps using React';
@@ -30,10 +33,12 @@ var Site = React.createClass({
<meta property="og:image" content="http://facebook.github.io/react-native/img/opengraph.png?2" />
<meta property="og:description" content="A framework for building native apps using React" />
<base href={basePath} />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" />
<link rel="shortcut icon" href="/react-native/img/favicon.png?2" />
<link rel="stylesheet" href="/react-native/css/react-native.css" />
<link rel="shortcut icon" href="img/favicon.png?2" />
<link rel="stylesheet" href="css/react-native.css" />
<script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script>
<script type="text/javascript">{'try{Typekit.load();}catch(e){}'}</script>
@@ -43,8 +48,8 @@ var Site = React.createClass({
<div className="container">
<div className="nav-main">
<div className="wrap">
<a className="nav-home" href="/react-native/">
<img src="/react-native/img/header_logo.png" />
<a className="nav-home" href="">
<img src="img/header_logo.png" />
React Native
</a>
<HeaderLinks section={this.props.section} />
@@ -72,7 +77,7 @@ var Site = React.createClass({
fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
`}} />
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
<script src="/react-native/js/scripts.js" />
<script src="js/scripts.js" />
</body>
</html>
);

View File

@@ -122,7 +122,7 @@ var ComponentDoc = React.createClass({
</Header>
{prop.deprecationMessage && <div className="deprecated">
<div className="deprecatedTitle">
<img className="deprecatedIcon" src="/react-native/img/Warning.png" />
<img className="deprecatedIcon" src="img/Warning.png" />
<span>Deprecated</span>
</div>
<div className="deprecatedMessage">
@@ -416,7 +416,7 @@ var EmbeddedSimulator = React.createClass({
<div className="column-left">
<p><a className="modal-button-open"><strong>Run this example</strong></a></p>
<div className="modal-button-open modal-button-open-img">
<img alt="Run example in simulator" width="170" height="358" src="/react-native/img/alertIOS.png" />
<img alt="Run example in simulator" width="170" height="358" src="img/alertIOS.png" />
</div>
<Modal />
</div>

View File

@@ -1,6 +1,7 @@
{
"scripts": {
"start": "node server/server.js"
"start": "node server/server.js",
"gh-pages": "node publish-gh-pages.js"
},
"dependencies": {
"bluebird": "^2.9.21",
@@ -14,6 +15,7 @@
"react": "~0.13.0",
"react-docgen": "^2.0.1",
"react-page-middleware": "git://github.com/facebook/react-page-middleware.git",
"request": "latest"
"request": "latest",
"shelljs": "^0.6.0"
}
}

View File

@@ -1,36 +0,0 @@
#!/bin/bash
# Copyright (c) 2015-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
# This script publishes to gh-pages of the private github repo.
# It assumes you have a react-native-android-gh-pages folder next to your react-native-android folder.
# You can clone that using:
# git clone -b gh-pages git@github.com:facebook/react-native-android.git react-native-android-gh-pages
set -e
# Start in website/ even if run from root directory
cd "$(dirname "$0")"
cd ../../react-native-android-gh-pages
git checkout -- .
git clean -dfx
git fetch
git rebase
rm -Rf *
cd ../react-native-android/website
node server/generate.js
cp -R build/react-native/* ../../react-native-android-gh-pages/
rm -Rf build/
cd ../../react-native-android-gh-pages
git status
if ! git diff-index --quiet HEAD --; then
git add -A .
git commit -m "update website"
git push origin gh-pages
fi

View File

@@ -0,0 +1,99 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
const CIRCLE_BRANCH = process.env.CIRCLE_BRANCH || '';
const CIRCLE_PROJECT_USERNAME = process.env.CIRCLE_PROJECT_USERNAME;
const CIRCLE_PROJECT_REPONAME = process.env.CIRCLE_PROJECT_REPONAME;
const CI_PULL_REQUESTS = process.env.CI_PULL_REQUESTS;
const CI_PULL_REQUEST = process.env.CI_PULL_REQUEST;
const GIT_USER = process.env.GIT_USER;
const remoteBranch = `https://${GIT_USER}@github.com/facebook/react-native.git`;
require(`shelljs/global`);
if (!which(`git`)) {
echo(`Sorry, this script requires git`);
exit(1);
}
let version;
if (CIRCLE_BRANCH.indexOf(`-stable`) !== -1) {
version = CIRCLE_BRANCH.slice(0, CIRCLE_BRANCH.indexOf(`-stable`));
} else if (CIRCLE_BRANCH === `master`) {
version = `next`;
}
rm(`-rf`, `build`);
mkdir(`-p`, `build`);
// if current commit is tagged "latest" we do a release to gh-pages root
let currentCommit = exec(`git rev-parse HEAD`).stdout.trim();
let latestTagCommit = exec(`git ls-remote origin latest`).stdout.split(/\s/)[0];
if (!CI_PULL_REQUEST && CIRCLE_PROJECT_USERNAME === `facebook`) {
echo(`Building branch ${version}, preparing to push to gh-pages`);
// if code is running in a branch in CI, commit changes to gh-pages branch
cd(`build`);
rm(`-rf`, `react-native-gh-pages`);
if (exec(`git clone ${remoteBranch} react-native-gh-pages`).code !== 0) {
echo(`Error: Git clone failed`);
exit(1);
}
cd(`react-native-gh-pages`);
if (exec(`git checkout origin/gh-pages`).code +
exec(`git checkout -b gh-pages`).code +
exec(`git branch --set-upstream-to=origin/gh-pages`).code !== 0
) {
echo(`Error: Git checkout gh-pages failed`);
exit(1);
}
// generate to releases/XX when branch name indicates that it is some sort of release
if (!!version) {
echo(`------------ DEPLOYING /releases/${version}`);
rm(`-rf`, `releases/${version}`);
mkdir(`-p`, `releases/${version}`);
cd(`../..`);
if (exec(`RN_DEPLOYMENT_PATH=releases/${version} node server/generate.js`).code !== 0) {
echo(`Error: Generating HTML failed`);
exit(1);
}
cd(`build/react-native-gh-pages`);
exec(`cp -R ../react-native/* releases/${version}`);
}
if (currentCommit === latestTagCommit) {
echo(`------------ DEPLOYING latest`);
// leave only releases folder
rm(`-rf`, ls(`*`).filter(name => name !== 'releases'));
cd(`../..`);
if (exec(`node server/generate.js`).code !== 0) {
echo(`Error: Generating HTML failed`);
exit(1);
}
cd(`build/react-native-gh-pages`);
exec(`cp -R ../react-native/* .`);
}
if (currentCommit === latestTagCommit || version) {
exec(`git status`);
exec(`git add -A .`);
if (exec(`git diff-index --quiet HEAD --`).code !== 0) {
if (exec(`git commit -m "Updated docs for ${version}"`).code !== 0) {
echo(`Error: Git commit gh-pages failed`);
exit(1);
}
if (exec(`git push origin gh-pages`).code !== 0) {
echo(`Error: Git push gh-pages failed`);
exit(1);
}
}
echo(`------------ gh-pages updated`);
}
}

View File

@@ -1,33 +0,0 @@
#!/bin/bash
# Copyright (c) 2015-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
set -e
# Start in website/ even if run from root directory
cd "$(dirname "$0")"
cd ../../react-native-gh-pages
git checkout -- .
git clean -dfx
git fetch
git rebase
rm -Rf *
cd ../react-native/website
node server/generate.js
cp -R build/react-native/* ../../react-native-gh-pages/
cp ../circle.yml ../../react-native-gh-pages/
rm -Rf build/
cd ../../react-native-gh-pages
git status
git add -A .
if ! git diff-index --quiet HEAD --; then
git commit -m "update website"
git push origin gh-pages
fi
cd ../react-native/website

View File

@@ -125,6 +125,17 @@ function execute() {
}
});
// we need to pass globals for the components to be configurable
// metadata is generated in this process which has access to process.env
// but the web pages are generated in a sandbox context and have only access to CommonJS module files
metadatas.config = Object.create(null);
Object
.keys(process.env)
.filter(key => key.startsWith('RN_'))
.forEach((key) => {
metadatas.config[key] = process.env[key];
});
fs.writeFileSync(
'core/metadata.js',
'/**\n' +

View File

@@ -267,7 +267,7 @@ var stylesForEmbed = [
];
var polyfills = [
'../Libraries/GeoLocation/Geolocation.js',
'../Libraries/Geolocation/Geolocation.js',
];
var all = components

View File

@@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
'use strict';
var Promise = require('bluebird');
var request = require('request');
@@ -56,7 +57,7 @@ glob('src/**/*.*', function(er, files) {
});
queue = queue.then(function() {
console.log('It is live at: http://facebook.github.io/react-native/');
console.log('Generated HTML files from JS');
}).finally(function() {
server.close();
}).catch(function(e) {

View File

@@ -0,0 +1,4 @@
general:
branches:
ignore:
- gh-pages

View File

@@ -1276,7 +1276,7 @@ input#algolia-doc-search {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-family: proxima-nova, "Helvetica Neue", Helvetica, Arial, sans-serif;
background: transparent url('/react-native/img/search.png') no-repeat left center;
background: transparent url('../img/search.png') no-repeat left center;
background-size: 16px 16px;
padding-left: 30px;

View File

@@ -89,7 +89,7 @@ var App = React.createClass({
<p>
See <a href="docs/debugging.html#content">Debugging</a>.
</p>
<img src="/react-native/img/chrome_breakpoint.png" width="800" height="443" />
<img src="img/chrome_breakpoint.png" width="800" height="443" />
<h2>Touch Handling</h2>
<p>