Skip to content
Permalink
Browse files

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 #9674
Closes #16093
  • Loading branch information
Narretz committed Jul 13, 2017
1 parent 7e97db9 commit 828a2757b2e04a3bec12012c127812559fab78e3
@@ -0,0 +1,5 @@
{
"projects": {
"default": "docs-angularjs-org-9p2"
}
}
@@ -9,7 +9,7 @@ performance/temp*.html
*~
*.swp
angular.js.tmproj
/node_modules/
node_modules/
bower_components/
angular.xcodeproj
.idea
@@ -10,7 +10,7 @@ cache:

branches:
except:
- /^g3_.*$/
- "/^g3_.*$/"

env:
matrix:
@@ -20,14 +20,15 @@ env:
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
global:
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
# node 4 likes the G++ v4.8 compiler
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
- CXX=g++-4.8
- SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
- LOGS_DIR=/tmp/angular-build/logs
- BROWSER_PROVIDER_READY_FILE=/tmp/browsersprovider-tunnel-ready
- secure: oTBjhnOKhs0qDSKTf7fE4f6DYiNDPycvB7qfSF5QRIbJK/LK/J4UtFwetXuXj79HhUZG9qnoT+5e7lPaiaMlpsIKn9ann7ffqFWN1E8TMtpJF+AGigx3djYElwfgf5nEnFUFhwjFzvbfpZNnxVGgX5YbIZpe/WUbHkP4ffU0Wks=

# node 4 likes the G++ v4.8 compiler
# see https://docs.travis-ci.com/user/languages/javascript-with-nodejs#Node.js-v4-(or-io.js-v3)-compiler-requirements
addons:
apt:
sources:
@@ -37,20 +38,61 @@ addons:

before_script:
- du -sh ./node_modules ./bower_components/ || true
- ./scripts/travis/before_build.sh

- "./scripts/travis/before_build.sh"
script:
- ./scripts/travis/build.sh
- "./scripts/travis/build.sh"

after_script:
- ./scripts/travis/tear_down_browser_provider.sh
- ./scripts/travis/print_logs.sh
- "./scripts/travis/tear_down_browser_provider.sh"
- "./scripts/travis/print_logs.sh"

notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/d2120f3f2bb39a4531b2
- http://104.197.9.155:8484/hubot/travis/activity #hubot-server
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: always # default: false
on_success: always # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: always # default: false

jobs:
include:
- stage: deploy
env:
- JOB=deploy
before_script: skip
script:
- "./scripts/travis/build.sh"
# Work around the 10min Travis timeout so the code.angularjs firebase+gcs code deploy can complete
before_deploy: |
function keep_alive() {
while true; do
echo -en "\a"
sleep 5
done
}
keep_alive &
deploy:
- provider: firebase
skip_cleanup: true
token:
secure: $FIREBASE_TOKEN
on:
repo: angular/angular.js
all_branches: true
# deploy a new docs version when the commit is tagged on the "latest" npm version
condition: $TRAVIS_TAG != '' && $( jq ".distTag" "package.json" | tr -d "\"[:space:]" ) = latest
- provider: gcs
skip_cleanup: true
access_key_id: GOOGLDB7W2J3LFHICF3R
secret_access_key:
secure: tHIFdSq55qkyZf9zT/3+VkhUrTvOTMuswxXU3KyWaBrSieZqG0UnUDyNm+n3lSfX95zEl/+rJAWbfvhVSxZi13ndOtvRF+MdI1cvow2JynP0aDSiPffEvVrZOmihD6mt2SlMfhskr5FTduQ69kZG6DfLcve1PPDaIwnbOv3phb8=
bucket: code-angularjs-org-338b8.appspot.com
local-dir: upload
detect_encoding: true # detects gzip compression
on:
repo: angular/angular.js
all_branches: true
# upload the build when the commit is tagged or the branch is "master"
condition: $TRAVIS_TAG != '' || ($TRAVIS_PULL_REQUEST = false && $TRAVIS_BRANCH = master)

@@ -49,7 +49,6 @@ if (!process.env.TRAVIS && !process.env.JENKINS_HOME) {
}
}


module.exports = function(grunt) {

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

var deployVersion = NG_VERSION.isSnapshot ? 'snapshot' : NG_VERSION.full;

if (versionInfo.cdnVersion == null) {
throw new Error('Unable to read CDN version, are you offline or has the CDN not been properly pushed?\n' +
'Perhaps you want to set the NG1_BUILD_NO_REMOTE_VERSION_REQUESTS environment variable?');
@@ -324,6 +325,15 @@ module.exports = function(grunt) {
expand: true,
dot: true,
dest: dist + '/'
},
firebaseCodeDeploy: {
options: {
mode: 'gzip'
},
src: ['**'],
cwd: 'build',
expand: true,
dest: 'upload/' + deployVersion + '/'
}
},

@@ -418,7 +428,7 @@ module.exports = function(grunt) {
'write',
'docs',
'copy',
'compress'
'compress:build'
]);
grunt.registerTask('ci-checks', [
'ddescribe-iit',
@@ -0,0 +1,24 @@
{
"hosting": {
"public": "build/docs",
"ignore": [
"/index.html",
"/index-debug.html",
"/index-jquery.html"
],
"rewrites": [
{
"source": "/",
"destination": "/index-production.html"
},
{
"source": "/index.html",
"destination": "/index-production.html"
},
{
"source": "**/*!(.jpg|.jpeg|.gif|.png|.html|.js|.json|.css|.svg|.ttf|.woff|.woff2|.eot)",
"destination": "/index-production.html"
}
]
}
}
@@ -0,0 +1,10 @@
Firebase for docs.angularjs.org
===============================

The docs are deployed to Google Firebase hosting via Travis deployment config, which expects
firebase.json and .firebaserc in the repository root.

See travis.yml for the complete deployment config.

See /scripts/code.angularjs.org-firebase/readme.firebase.code.md for the firebase deployment to
code.angularjs.org
@@ -0,0 +1,5 @@
{
"env": {
"es6": true
}
}
@@ -0,0 +1,5 @@
{
"projects": {
"default": "code-angularjs-org-338b8"
}
}
@@ -0,0 +1,21 @@
{
"hosting": {
"public": "public",
"redirects": [
{
"source": "/:version/docs",
"destination": "/:version/docs/index.html",
"type": 301
}
],
"rewrites": [
{
"source": "/**",
"function": "sendStoredFile"
}
]
},
"storage": {
"rules": "storage.rules"
}
}
@@ -0,0 +1,75 @@
'use strict';

const functions = require('firebase-functions');
const gcs = require('@google-cloud/storage')();
const path = require('path');

const gcsBucketId = `${process.env.GCLOUD_PROJECT}.appspot.com`;
const LOCAL_TMP_FOLDER = '/tmp/';

const BROWSER_CACHE_DURATION = 300;
const CDN_CACHE_DURATION = 600;

function sendStoredFile(request, response) {
let filePathSegments = request.path.split('/').filter((segment) => {
// Remove empty leading or trailing path parts
return segment !== '';
});

const version = filePathSegments[0];
const isDocsPath = filePathSegments[1] === 'docs';
const lastSegment = filePathSegments[filePathSegments.length - 1];
const bucket = gcs.bucket(gcsBucketId);

let downloadSource;
let downloadDestination;
let fileName;

if (isDocsPath && filePathSegments.length === 2) {
fileName = 'index.html';
filePathSegments = [version, 'docs', fileName];
} else {
fileName = lastSegment;
}

downloadSource = path.join.apply(null, filePathSegments);
downloadDestination = `${LOCAL_TMP_FOLDER}${fileName}`;

downloadAndSend(downloadSource, downloadDestination).catch(error => {
if (isDocsPath && error.code === 404) {
fileName = 'index.html';
filePathSegments = [version, 'docs', fileName];
downloadSource = path.join.apply(null, filePathSegments);
downloadDestination = `${LOCAL_TMP_FOLDER}${fileName}`;

return downloadAndSend(downloadSource, downloadDestination);
}

return Promise.reject(error);
}).catch(error => {
let message = 'General error';
if (error.code === 404) {
if (fileName.split('.').length === 1) {
message = 'Directory listing is not supported';
} else {
message = 'File not found';
}
}

return response.status(error.code).send(message);
});

function downloadAndSend(downloadSource, downloadDestination) {
return bucket.file(downloadSource).download({
destination: downloadDestination
}).then(() => {
return response.status(200)
.set({
'Cache-Control': `public, max-age=${BROWSER_CACHE_DURATION}, s-maxage=${CDN_CACHE_DURATION}`
})
.sendFile(downloadDestination);
});
}
}

exports.sendStoredFile = functions.https.onRequest(sendStoredFile);
@@ -0,0 +1,10 @@
{
"name": "functions-firebase-code.angularjs.org",
"description": "Cloud Functions to serve files from gcs to code.angularjs.org",
"dependencies": {
"@google-cloud/storage": "^1.1.1",
"firebase-admin": "^4.2.1",
"firebase-functions": "^0.5.9"
},
"private": true
}
Binary file not shown.
@@ -0,0 +1 @@
google-site-verification: googleb96cceae5888d79f.html
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>AngularJS</title>
</head>
<body>
</body>
</html>
@@ -0,0 +1,5 @@
User-agent: *

Disallow: /*docs/
Disallow: /*i18n/
Disallow: /*.zip$
@@ -0,0 +1,12 @@
Firebase for code.angularjs.org
===============================

This folder contains the Google Firebase scripts for the code.angularjs.org setup.

firebase.json contains the rewrite rules that route every subdirectory request to the cloud function
in functions/index.js that serves the docs from the Firebase Google Cloud Storage bucket.

The deployment to the Google Cloud Storage bucket happens automatically via Travis. See the travis.yml
file in the repository root.

See /readme.firebase.docs.md for the firebase deployment to docs.angularjs.org
@@ -0,0 +1,7 @@
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth!=null;
}
}
}
@@ -59,23 +59,12 @@ function _update_code() {

echo "-- Pushing code.angularjs.org"
git push origin master

for backend in "$@" ; do
echo "-- Refreshing code.angularjs.org: backend=$backend"

# FIXME: We gave up publishing to code.angularjs.org because the GCE automatically removes firewall
# rules that allow access to port 8003.

# curl http://$backend:8003/gitFetchSite.php
done
}

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

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

0 comments on commit 828a275

Please sign in to comment.
You can’t perform that action at this time.