Skip to content

Commit 7b43332

Browse files
committed
chore: deploy docs|code .angularjs.org to Firebase via Travis
- code.angularjs.org and docs.angularjs.org are two separate Firebase projects - both are automatically deployed via Travis config - Travis is split up into 2 build stages: first, all tests are run, and if they pass, the deploy stage runs a single job with both deployments (actual deployment depends on the state of the commit) - docs. is deployed directly to Firebase hosting - code. is uploaded to Firebase Google Cloud Storage and uses Firebase hosting rewrites to acces the files - jenkins builds still push the code builds to the code.angularjs.org Github repository Closes angular#9674
1 parent af83c15 commit 7b43332

19 files changed

+300
-77
lines changed

.firebaserc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "docs-angularjs-org-9p2"
4+
}
5+
}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ performance/temp*.html
1010
*.swp
1111
angular.js.tmproj
1212
/node_modules/
13+
/scripts/code.angularjs.org-firebase/functions/node_modules/
1314
bower_components/
1415
angular.xcodeproj
1516
.idea

.travis.yml

+67-35
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,88 @@
11
language: node_js
22
sudo: false
33
node_js:
4-
- '6'
5-
4+
- '6'
65
cache:
76
yarn: true
87
directories:
9-
- bower_components
10-
8+
- bower_components
119
branches:
1210
except:
13-
- /^g3_.*$/
14-
11+
- "/^g3_.*$/"
1512
env:
1613
matrix:
17-
- JOB=ci-checks
18-
- JOB=unit BROWSER_PROVIDER=saucelabs
19-
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
20-
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
21-
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
14+
- JOB=ci-checks
15+
- JOB=unit BROWSER_PROVIDER=saucelabs
16+
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
17+
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
18+
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
2219
global:
23-
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
24-
- SAUCE_USERNAME=angular-ci
25-
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
26-
- LOGS_DIR=/tmp/angular-build/logs
27-
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
28-
29-
# node 4 likes the G++ v4.8 compiler
30-
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
20+
- CXX=g++-4.8
21+
- SAUCE_USERNAME=angular-ci
22+
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
23+
- LOGS_DIR=/tmp/angular-build/logs
24+
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
25+
- secure: oTBjhnOKhs0qDSKTf7fE4f6DYiNDPycvB7qfSF5QRIbJK/LK/J4UtFwetXuXj79HhUZG9qnoT+5e7lPaiaMlpsIKn9ann7ffqFWN1E8TMtpJF+AGigx3djYElwfgf5nEnFUFhwjFzvbfpZNnxVGgX5YbIZpe/WUbHkP4ffU0Wks=
3126
addons:
3227
apt:
3328
sources:
34-
- ubuntu-toolchain-r-test
29+
- ubuntu-toolchain-r-test
3530
packages:
36-
- g++-4.8
37-
31+
- g++-4.8
3832
before_script:
39-
- du -sh ./node_modules ./bower_components/ || true
40-
- ./scripts/travis/before_build.sh
41-
33+
- du -sh ./node_modules ./bower_components/ || true
34+
- "./scripts/travis/before_build.sh"
4235
script:
43-
- ./scripts/travis/build.sh
44-
36+
- "./scripts/travis/build.sh"
4537
after_script:
46-
- ./scripts/travis/tear_down_browser_provider.sh
47-
- ./scripts/travis/print_logs.sh
48-
38+
- "./scripts/travis/tear_down_browser_provider.sh"
39+
- "./scripts/travis/print_logs.sh"
4940
notifications:
5041
webhooks:
5142
urls:
52-
- https://webhooks.gitter.im/e/d2120f3f2bb39a4531b2
53-
- http://104.197.9.155:8484/hubot/travis/activity #hubot-server
54-
on_success: always # options: [always|never|change] default: always
55-
on_failure: always # options: [always|never|change] default: always
56-
on_start: always # default: false
43+
- https://webhooks.gitter.im/e/d2120f3f2bb39a4531b2
44+
- http://104.197.9.155:8484/hubot/travis/activity
45+
on_success: always
46+
on_failure: always
47+
on_start: always
48+
jobs:
49+
include:
50+
- stage: deploy
51+
env:
52+
- JOB=deploy
53+
before_script: skip
54+
script:
55+
- "./scripts/travis/build.sh"
56+
# Work around the 10min Travis timeout so the code.angularjs firebase+gcs code deploy can complete
57+
before_deploy: |
58+
function keep_alive() {
59+
while true; do
60+
echo -en "\a"
61+
sleep 5
62+
done
63+
}
64+
keep_alive &
65+
deploy:
66+
- provider: firebase
67+
skip_cleanup: true
68+
token:
69+
secure: $FIREBASE_TOKEN
70+
on:
71+
repo: angular/angular.js
72+
all_branches: true
73+
# deploy a new docs version when the commit is tagged on the "latest" npm version
74+
condition: $TRAVIS_TAG != '' && $( jq ".distTag" "package.json" | tr -d "\"[:space:]" ) = latest
75+
- provider: gcs
76+
skip_cleanup: true
77+
access_key_id: GOOGLDB7W2J3LFHICF3R
78+
secret_access_key:
79+
secure: tHIFdSq55qkyZf9zT/3+VkhUrTvOTMuswxXU3KyWaBrSieZqG0UnUDyNm+n3lSfX95zEl/+rJAWbfvhVSxZi13ndOtvRF+MdI1cvow2JynP0aDSiPffEvVrZOmihD6mt2SlMfhskr5FTduQ69kZG6DfLcve1PPDaIwnbOv3phb8=
80+
bucket: code-angularjs-org-338b8.appspot.com
81+
local-dir: upload
82+
detect_encoding: true # detects gzip compression
83+
on:
84+
repo: angular/angular.js
85+
all_branches: true
86+
# upload the build when the commit is tagged or the branch is "master"
87+
condition: $TRAVIS_TAG != '' || ($TRAVIS_PULL_REQUEST = false && $TRAVIS_BRANCH = master)
88+

Gruntfile.js

+12-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ if (!process.env.TRAVIS && !process.env.JENKINS_HOME) {
4949
}
5050
}
5151

52-
5352
module.exports = function(grunt) {
5453

5554
// this loads all the node_modules that start with `grunt-` as plugins
@@ -64,6 +63,8 @@ module.exports = function(grunt) {
6463
NG_VERSION.cdn = versionInfo.cdnVersion;
6564
var dist = 'angular-' + NG_VERSION.full;
6665

66+
var deployVersion = NG_VERSION.isSnapshot ? 'snapshot' : NG_VERSION.full;
67+
6768
if (versionInfo.cdnVersion == null) {
6869
throw new Error('Unable to read CDN version, are you offline or has the CDN not been properly pushed?\n' +
6970
'Perhaps you want to set the NG1_BUILD_NO_REMOTE_VERSION_REQUESTS environment variable?');
@@ -324,6 +325,15 @@ module.exports = function(grunt) {
324325
expand: true,
325326
dot: true,
326327
dest: dist + '/'
328+
},
329+
firebaseCodeDeploy: {
330+
options: {
331+
mode: 'gzip'
332+
},
333+
src: ['**'],
334+
cwd: 'build',
335+
expand: true,
336+
dest: 'upload/' + deployVersion + '/'
327337
}
328338
},
329339

@@ -418,7 +428,7 @@ module.exports = function(grunt) {
418428
'write',
419429
'docs',
420430
'copy',
421-
'compress'
431+
'compress:build'
422432
]);
423433
grunt.registerTask('ci-checks', [
424434
'ddescribe-iit',

firebase.json

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"hosting": {
3+
"public": "build/docs",
4+
"ignore": [
5+
"/index-debug.html",
6+
"/index-jquery.html"
7+
],
8+
"redirects": [
9+
{
10+
"source": "/",
11+
"destination": "/index-production.html",
12+
"type": 301
13+
},
14+
{
15+
"source": "/index.html",
16+
"destination": "/index-production.html",
17+
"type": 301
18+
}
19+
],
20+
"rewrites": [
21+
{
22+
"source": "**/*!(.jpg|.jpeg|.gif|.png|.html|.js|.json|.css|.svg|.ttf|.woff|.woff2|.eot)",
23+
"destination": "/index-production.html"
24+
}
25+
]
26+
}
27+
}

readme.firebase.docs.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Firebase for docs.angularjs.org
2+
===============================
3+
4+
The docs are deployed to Google Firebase hosting via Travis deployment config, which expects
5+
firebase.json and .firebaserc in the repository root.
6+
7+
See travis.yml for the complete deployment config.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"env": {
3+
"es6": true
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "code-angularjs-org-338b8"
4+
}
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"hosting": {
3+
"public": "public",
4+
"redirects": [
5+
{
6+
"source": "/:version/docs",
7+
"destination": "/:version/docs/index.html",
8+
"type": 301
9+
}
10+
],
11+
"rewrites": [
12+
{
13+
"source": "/**",
14+
"function": "sendStoredFile"
15+
}
16+
]
17+
},
18+
"storage": {
19+
"rules": "storage.rules"
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use strict';
2+
3+
const functions = require('firebase-functions');
4+
const gcs = require('@google-cloud/storage')();
5+
const path = require('path');
6+
7+
const gcsBucket = 'code-angularjs-org-338b8.appspot.com';
8+
const LOCAL_TMP_FOLDER = '/tmp/';
9+
10+
function sendStoredFile(request, response) {
11+
let filePathSegments = request.path.split('/').filter((segment) => {
12+
return segment !== '';
13+
});
14+
15+
const version = filePathSegments[0];
16+
const isDocsPath = filePathSegments[1] === 'docs';
17+
const lastSegment = filePathSegments[filePathSegments.length - 1];
18+
let downloadPath;
19+
let fileName;
20+
21+
if (isDocsPath && filePathSegments.length === 2) {
22+
fileName = 'index.html';
23+
filePathSegments = [version, 'docs', fileName];
24+
} else {
25+
fileName = lastSegment;
26+
}
27+
28+
downloadPath = path.join.apply(null, filePathSegments);
29+
30+
const bucket = gcs.bucket(gcsBucket);
31+
32+
downloadAndSend().catch(error => {
33+
if (isDocsPath && error.code === 404) {
34+
fileName = 'index.html';
35+
filePathSegments = [version, 'docs', fileName];
36+
downloadPath = path.join.apply(null, filePathSegments);
37+
return downloadAndSend();
38+
}
39+
40+
return Promise.reject(error);
41+
}).catch(error => {
42+
let message = 'General error';
43+
if (error.code === 404) {
44+
if (fileName.split('.').length === 1) {
45+
message = 'Directory listing is not supported';
46+
} else {
47+
message = 'File not found';
48+
}
49+
}
50+
51+
return response.status(error.code).send(message);
52+
});
53+
54+
function downloadAndSend() {
55+
return bucket.file(downloadPath).download({
56+
destination: `/tmp/${fileName}`
57+
}).then(() => {
58+
return response.status(200)
59+
.set({
60+
'Cache-Control': 'public, max-age=300, s-maxage=600'
61+
})
62+
.sendFile(`${LOCAL_TMP_FOLDER}${fileName}`);
63+
});
64+
}
65+
}
66+
67+
exports.sendStoredFile = functions.https.onRequest(sendStoredFile);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "functions-firebase-code.angularjs.org",
3+
"description": "Cloud Functions to serve files from gcs to code.angularjs.org",
4+
"dependencies": {
5+
"@google-cloud/storage": "^1.1.1",
6+
"firebase-admin": "^4.2.1",
7+
"firebase-functions": "^0.5.9"
8+
},
9+
"private": true
10+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-site-verification: googleb96cceae5888d79f.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>AngularJS</title>
7+
</head>
8+
<body>
9+
</body>
10+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
User-agent: *
2+
3+
Disallow: /*docs/
4+
Disallow: /*i18n/
5+
Disallow: /*.zip$
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Firebase for code.angularjs.org
2+
===============================
3+
4+
This folder contains the Google Firebase scripts for the code.angularjs.org setup.
5+
6+
firebase.json contains the rewrite rules that route every subdirectory request to the cloud function
7+
in functions/index.js that serves the docs from the Firebase Google Cloud Storage bucket.
8+
9+
The deployment to the Google Cloud Storage bucket happens automatically via Travis. See the travis.yml
10+
file in the repository root.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
service firebase.storage {
2+
match /b/{bucket}/o {
3+
match /{allPaths=**} {
4+
allow read, write: if request.auth!=null;
5+
}
6+
}
7+
}

scripts/code.angularjs.org/publish.sh

+3-14
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,12 @@ function _update_code() {
5959

6060
echo "-- Pushing code.angularjs.org"
6161
git push origin master
62-
63-
for backend in "$@" ; do
64-
echo "-- Refreshing code.angularjs.org: backend=$backend"
65-
66-
# FIXME: We gave up publishing to code.angularjs.org because the GCE automatically removes firewall
67-
# rules that allow access to port 8003.
68-
69-
# curl http://$backend:8003/gitFetchSite.php
70-
done
7162
}
7263

7364
function publish {
74-
# The TXT record for backends.angularjs.org is a CSV of the IP addresses for
75-
# the currently serving Compute Engine backends.
76-
# code.angularjs.org is served out of port 8003 on these backends.
77-
backends=("$(dig backends.angularjs.org +short TXT | python -c 'print raw_input()[1:-1].replace(",", "\n")')")
78-
_update_code ${backends[@]}
65+
# publish updates the code.angularjs.org Github repository
66+
# the deployment to Firebase happens via Travis
67+
_update_code
7968
}
8069

8170
source $(dirname $0)/../utils.inc

0 commit comments

Comments
 (0)