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
Showing
with
308 additions
and 65 deletions.
- +5 −0 .firebaserc
- +1 −1 .gitignore
- +54 −12 .travis.yml
- +12 −2 Gruntfile.js
- +24 −0 firebase.json
- +10 −0 readme.firebase.docs.md
- +5 −0 scripts/code.angularjs.org-firebase/.eslintrc.json
- +5 −0 scripts/code.angularjs.org-firebase/.firebaserc
- +21 −0 scripts/code.angularjs.org-firebase/firebase.json
- +75 −0 scripts/code.angularjs.org-firebase/functions/index.js
- +10 −0 scripts/code.angularjs.org-firebase/functions/package.json
- BIN scripts/code.angularjs.org-firebase/public/favicon.ico
- +1 −0 scripts/code.angularjs.org-firebase/public/googleb96cceae5888d79f.html
- +10 −0 scripts/code.angularjs.org-firebase/public/index.html
- +5 −0 scripts/code.angularjs.org-firebase/public/robots.txt
- +12 −0 scripts/code.angularjs.org-firebase/readme.firebase.code.md
- +7 −0 scripts/code.angularjs.org-firebase/storage.rules
- +3 −14 scripts/code.angularjs.org/publish.sh
- +48 −36 scripts/travis/build.sh
| @@ -0,0 +1,5 @@ | ||
| { | ||
| "projects": { | ||
| "default": "docs-angularjs-org-9p2" | ||
| } | ||
| } |
| @@ -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; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.