Skip to content

Commit

Permalink
Lint, Yarn, Travis, Expo UI (#313)
Browse files Browse the repository at this point in the history
* Fix README markdown lint errors and typos
* Reorganize README; remove sudo from npm start
* Convert tabs to spaces in api.js
* Simplify the eslintrc
* Add travis config
* Lint the markdown
* Switch from npm to yarn
For consistency with abe-web. Also, because yarn is better :-).
* Lint js files in static
* Fix trivial lint errors
Semicolons, mixed spaces and tabs, one of the unused variables
* Add a Travis badge
* Fix lint errors in board_events.js
Since I'm going to be working here
* Teach server to display listening address in URL form, so I can click on it
* Workaround for #310 events setup crashes on time with sub seconds
* Update views url
* Add expo UI, Update video background to black
* Update css for expo UI
* Fix css error in upload.cscs
  • Loading branch information
Seungin Lyu(승인) authored May 10, 2018
1 parent 7382aa4 commit 44236d2
Show file tree
Hide file tree
Showing 20 changed files with 596 additions and 365 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
static/vendor/**/*.js
57 changes: 36 additions & 21 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,44 @@ parserOptions:
extends:
- eslint:recommended

# see https://eslint.org/docs/user-guide/configuring#specifying-globals
globals:
# $: false
# moment: false # TODO: use `import` to import this, and remove this exception
# global: false
# module: false
db: false
process: false # for webpack process.env variables

rules:
no-console: warn
no-unused-vars: [error, { argsIgnorePattern: "^_" }]
no-useless-escape: warn # TODO: remove (so this is an error)
no-useless-escape: warn # TODO: remove (so this is an error)

# Server-side:
overrides:
files: [ "*.js", "models/*.js", "routes/*.js", "scripts/*.js" ]
env:
browser: false
node: true
globals:
Promise: false
module: false
require: false
rules:
no-console: off
# Client:
- files: [ "routes/*.js", "static/**/*.js" ]
globals:
$: false
ABE_API_URI: false
SUBMIT_URL: true
db: false
showdown: false
# defined and used in admin.js:
tableColumns: true
# defined in server.js:
io: true
# defined and used in board_carousel:
$activeItem: true
$carousel: true
carouselSelector: true
# defined in vendor files:
Cookies: false
Dropzone: false
rules:
# FIXME: remove these exceptions, to turn them back into errors
no-undef: warn
no-unused-vars: warn
no-redeclare: warn
# Server:
- files: [ "server.js", "models/*.js", "routes/*.js", "scripts/*.js" ]
env:
browser: false
node: true
globals:
Promise: false
module: false
require: false
rules:
no-console: off
10 changes: 10 additions & 0 deletions .markdownlintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"default": true,

"line-length": { "line_length": 1000 },
"no-trailing-punctuation": false,
"ul-style": false, // * instead of -

// FIXME: remove the instance of this
"no-empty-links": false
}
8 changes: 8 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
language: node_js
node_js:
- "9.3"

cache: yarn

script:
- yarn lint
290 changes: 165 additions & 125 deletions README.md

Large diffs are not rendered by default.

133 changes: 82 additions & 51 deletions lambdas/aws-lambda-ffmpeg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,70 +5,85 @@
[![Known Vulnerabilities](https://snyk.io/test/github/binoculars/aws-lambda-ffmpeg/badge.svg)](https://snyk.io/test/github/binoculars/aws-lambda-ffmpeg)
[![Greenkeeper badge](https://badges.greenkeeper.io/binoculars/aws-lambda-ffmpeg.svg)](https://greenkeeper.io/)

- Master: [![Build Status](https://travis-ci.org/binoculars/aws-lambda-ffmpeg.svg?branch=master)](https://travis-ci.org/binoculars/aws-lambda-ffmpeg)
- Develop: [![Build Status](https://travis-ci.org/binoculars/aws-lambda-ffmpeg.svg?branch=develop)](https://travis-ci.org/binoculars/aws-lambda-ffmpeg)
* Master: [![Build Status](https://travis-ci.org/binoculars/aws-lambda-ffmpeg.svg?branch=master)](https://travis-ci.org/binoculars/aws-lambda-ffmpeg)
* Develop: [![Build Status](https://travis-ci.org/binoculars/aws-lambda-ffmpeg.svg?branch=develop)](https://travis-ci.org/binoculars/aws-lambda-ffmpeg)

The different platforms have different naming conventions for their services. To simplify this, listed below is a *proposed* table of generalized terms that are platform-independent.
The different platforms have different naming conventions for their services. To simplify this, listed below is a _proposed_ table of generalized terms that are platform-independent.

| Term | Amazon Web Services | Microsoft Azure | Google Cloud Platform |
| --- | --- | --- | --- |
| Function | Lambda Function | Azure Function | Cloud Function |
| Storage Location | S3 Bucket | Storage Container | GCS Bucket |
| Storage Path | S3 Key | Blob Name | GCS File |
| Term | Amazon Web Services | Microsoft Azure | Google Cloud Platform |
| ---------------- | ------------------- | ----------------- | --------------------- |
| Function | Lambda Function | Azure Function | Cloud Function |
| Storage Location | S3 Bucket | Storage Container | GCS Bucket |
| Storage Path | S3 Key | Blob Name | GCS File |

# Function Process Overview
1. A video file is uploaded to the source storage location
1. A notification event triggers the function
1. The function downloads the video file from the source location
1. Streams the video through FFmpeg
1. Outputs a scaled video file and a thumbnail image
1. Uploads both files to the destination bucket

1. A video file is uploaded to the source storage location
2. A notification event triggers the function
3. The function downloads the video file from the source location
4. Streams the video through FFmpeg
5. Outputs a scaled video file and a thumbnail image
6. Uploads both files to the destination bucket

# Supported Platforms
- [x] Amazon Web Services (aws) Lambda
- [x] Google Cloud Platform (gcp) Cloud Functions (Alpha)
- [ ] IBM (ibm) OpenWhisk (Not started)
- [ ] Microsoft Azure (msa) Functions (Still some work to do here)

* [x] Amazon Web Services (aws) Lambda
* [x] Google Cloud Platform (gcp) Cloud Functions (Alpha)
* [ ] IBM (ibm) OpenWhisk (Not started)
* [ ] Microsoft Azure (msa) Functions (Still some work to do here)

# Setup
1. Install node.js, preferably through [nvm](/creationix/nvm). Each platform service uses a specific version of Node.js.
1. Clone this repo `git clone ...`
1. Run `npm install`
1. Create your function code's storage location (or choose an existing one)
1. Update the platform-specific configuration JSON file (see below), and/or modify the code file for your purposes
1. Run Gulp (see below)
1. Invoke the function by uploading a video to your source storage location.

1. Install [Node.js](https://nodejs.org/en/), preferably through
[nvm](/creationix/nvm). Each platform service uses a specific version of
Node.js.
2. Clone this repo: `git clone ...`
3. Run `yarn install`
4. Create your function code's storage location (or choose an existing one)
5. Update the platform-specific configuration JSON file (see below), and/or modify the code file for your purposes
6. Run Gulp (see below)
7. Invoke the function by uploading a video to your source storage location.

## Configuration

See [config_samples](config_samples/).

At minimum, you need to modify:
- `functionBucket` - The name of the bucket where your the lambda function code will be uploaded to. It's necessary for CloudFormation.
- `sourceBucket` - The name of the bucket that will receive the videos and send them to the lambda for processing.
- `destinationBucket` - The name of the bucket that will be used to store the output video and thumbnail image.

* `functionBucket` - The name of the bucket where your the lambda function code will be uploaded to. It's necessary for CloudFormation.
* `sourceBucket` - The name of the bucket that will receive the videos and send them to the lambda for processing.
* `destinationBucket` - The name of the bucket that will be used to store the output video and thumbnail image.

## Local Testing

### Unit Tests
- Run `npm test`

TODO: Unit tests are not implemented.

* Run `yarn test`

### Integration Tests
- [Install FFmpeg locally](https://ffmpeg.org/download.html) or use the [compilation guide](https://trac.ffmpeg.org/wiki/CompilationGuide)
- Edit `event/{platform}.json` and run `node test/{platform}.js`, where platform is (aws|msa|gcp)
- When switching among the platforms, reinstall the node modules if the runtime supports a different version of Node.js.
- See the platform-specific notes

* [Install FFmpeg locally](https://ffmpeg.org/download.html) or use the [compilation guide](https://trac.ffmpeg.org/wiki/CompilationGuide)
* Edit `event/{platform}.json` and run `node test/{platform}.js`, where platform is (aws|msa|gcp)
* When switching among the platforms, reinstall the node modules if the runtime supports a different version of Node.js.
* See the platform-specific notes

## Gotchas
- Gzipping videos will cause Safari errors in playback. Don't enable gzip unless you don't care about supporting Safari.

* Gzipping videos will cause Safari errors in playback. Don't enable gzip unless you don't care about supporting Safari.

# Platform-specific notes

## AWS Lambda
- [Version information](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html)
- Pick the largest memory allocation. This is mostly CPU bound, but Lambda bundles memory and CPU allocation together. Memory size is 1536 by default, in the CloudFormation template. Testing with different videos and sizes should give you a good idea if it meets your requirements. Total execution time is limited!
- The object key from the event is URL encoded. Spaces in the filenames might be replaced with `+` so be aware of this and handle errors appropriately. If you try to download the file with the AWS SDK for JavaScript like in this example, without handling this, it will throw an error.
- Not handling errors with `context.fail(error)` will cause the function to run until the timeout is reached.

* [Version information](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html)
* Pick the largest memory allocation. This is mostly CPU bound, but Lambda bundles memory and CPU allocation together. Memory size is 1536 by default, in the CloudFormation template. Testing with different videos and sizes should give you a good idea if it meets your requirements. Total execution time is limited!
* The object key from the event is URL encoded. Spaces in the filenames might be replaced with `+` so be aware of this and handle errors appropriately. If you try to download the file with the AWS SDK for JavaScript like in this example, without handling this, it will throw an error.
* Not handling errors with `context.fail(error)` will cause the function to run until the timeout is reached.

### Example local testing script

```bash
# Environment variables
export AWS_ACCESS_KEY_ID=AKIDEXAMPLE
Expand All @@ -89,12 +104,15 @@ node node_modules/babel-cli/bin/babel-node.js test/aws.js
### Gulp

#### Task: `aws:create-cfn-bucket`

Creates the CloudFormation for your CloudFormation template and Lambda function code. **Run this once**. Set the `CFN_S3_BUCKET` environment variable to the name of the bucket you want to create.

```bash
CFN_S3_BUCKET=cloudformation-bucket gulp aws:create-cfn-bucket
```

#### Environment Settings

The following environment variables must be set prior to using the rest of the gulp commands

```bash
Expand All @@ -109,37 +127,46 @@ export VIDEO_MAX_DURATION='30' # must be a number
```

#### Task: `aws:default`

Everything you need to get started. Note: You can change the stack name by setting environment variable `STACK_NAME`.
- Runs the `aws:build-upload` task
- Runs the `aws:deployStack` task

* Runs the `aws:build-upload` task
* Runs the `aws:deployStack` task

#### Task: `aws:build-upload`
- Builds `dist.zip`
- Downloads and extracts FFmpeg binaries
- Transpiles, installs dependencies, and copies configuration
- Uploads `dist.zip` to the function's S3 bucket

* Builds `dist.zip`
* Downloads and extracts FFmpeg binaries
* Transpiles, installs dependencies, and copies configuration
* Uploads `dist.zip` to the function's S3 bucket

#### Task: `aws:deployStack`
- Creates or updates the CloudFormation stack which includes:
- The lambda function's execution role and policy
- The lambda function
- The source bucket (where videos are uploaded to), including the notification configuration
- The destination bucket (where videos and thumbnails go after they are processed)

* Creates or updates the CloudFormation stack which includes:
* The lambda function's execution role and policy
* The lambda function
* The source bucket (where videos are uploaded to), including the notification configuration
* The destination bucket (where videos and thumbnails go after they are processed)

#### Task: `aws:update`

Run after modifying anything in the function or configuration, if you've already created the stack. This will rebuild `dist.zip`, upload it to S3, and update the lambda function created during the CloudFormation stack creation.

## Google Cloud Functions

See the [quickstart guide](https://cloud.google.com/functions/quickstart).

### Gulp

Note: you must have the gcloud CLI tool installed.

#### Task: `gcp:default`
- Builds everything into the `build/` directory
- Deploys the function. Note: GCF does the `npm install` on the server-side, so there is no need to build a zip file.

* Builds everything into the `build/` directory
* Deploys the function. Note: GCF does the `npm install` on the server-side, so there is no need to build a zip file.

### Example local testing script

```bash
# Environment variables
export GCLOUD_PROJECT=example-project-name
Expand All @@ -152,12 +179,15 @@ node node_modules/babel-cli/bin/babel-node.js --presets es2015 test/gcp.js
```

## IBM OpenWhisk (not started, HELP WANTED)

See [the OpenWhisk repo](/openwhisk/openwhisk)

## Microsoft Azure Functions (in progress, HELP WANTED)

See [Azure functions reference](https://azure.microsoft.com/en-us/documentation/articles/functions-reference-node/).

### Example local testing script

```bash
# Environment variables
export AZURE_STORAGE_CONNECTION_STRING=... # copy from azure console
Expand All @@ -169,6 +199,7 @@ node node_modules/babel-cli/bin/babel-node.js --presets es2015-node5 test/aws.js
```

# Contributing

Submit issues if you find bugs or something is unclear. Pull requests are even better, especially if you can make something more generalized.

**If you use it, :star: it!**
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
"socket.io": "^2.0.3"
},
"devDependencies": {
"eslint": "^4.19.1"
"eslint": "^4.19.1",
"markdownlint-cli": "^0.8.1"
},
"scripts": {
"lint": "eslint --cache *.js lambda models routes scripts",
"lint": "eslint --cache *.js lambda models routes scripts static && markdownlint README.md",
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
Expand Down
38 changes: 19 additions & 19 deletions routes/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,10 @@ module.exports = function(io, db) {
// Get all flavors
function GETflavors(req, res) {
db.Flavors.getFlavors().then(function success(data) {
res.send(data);
}, function error(err) {
res.status(500).send(err);
});
res.send(data);
}, function error(err) {
res.status(500).send(err);
});
}

// Get one flavor by name or id
Expand All @@ -236,32 +236,32 @@ module.exports = function(io, db) {
db.Flavors.getFlavor({ _id: db.ObjectId(req.params.flavorname) }).then(function success(data) {
res.send(data);
}, function error(err) {
res.status(500).send(err);
res.status(500).send(err);
});
} else {
res.send(data);
}
}, function error(err) {
res.status(500).send(err);
});
}, function error(err) {
res.status(500).send(err);
});
}

// Get all tags
function GETtags(req, res) {
db.Tag.getTags().then(function success(data) {
res.send(data);
}, function error(err) {
res.status(500).send(err);
});
}
db.Tag.getTags().then(function success(data) {
res.send(data);
}, function error(err) {
res.status(500).send(err);
});
}

// Get a single tag by id
function GETtag(req, res) {
db.Tag.getTag({ _id: db.ObjectId(req.params.tagid) }).then(function success(data) {
res.send(data);
}, function error(err) {
res.status(500).send(err);
});
db.Tag.getTag({ _id: db.ObjectId(req.params.tagid) }).then(function success(data) {
res.send(data);
}, function error(err) {
res.status(500).send(err);
});
}

router.GETallBobs = GETallBobs;
Expand Down
2 changes: 1 addition & 1 deletion routes/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ module.exports = function (api, rootDir) {
router.route('/views/events').get(ensureAuthenticated, function(req, res) {
res.sendFile(rootDir + '/templates/events.html');
});
router.route('/views/basic').get(ensureAuthenticated, function(req, res) {
router.route('/views/expo').get(ensureAuthenticated, function(req, res) {
res.sendFile(rootDir + '/templates/stream-basic.html');
});
router.route('/upload').get(function (req, res) {
Expand Down
Loading

0 comments on commit 44236d2

Please sign in to comment.