Giter VIP home page Giter VIP logo

origami-build-service's Introduction

Origami Build Service MIT licensed

Use the Origami Build Service to include Origami components in your project with a <script> and <style> tag, no build step required.

To learn more about using the Origami Build Service refer to the API reference and Origami Build Service Tutorial.

Table Of Contents

Requirements

Running Origami Build Service requires Node.js and npm.

Running Locally

Before we can run the application, we'll need to install dependencies:

npm install

Run the application in development mode with

npm start

Now you can access the app over HTTP on port 8080: http://localhost:8080/__origami/service/build/v3

Configuration

We configure Origami Build Service using environment variables. In local development environment configuration is not needed, unless you need to change PORT or NODE_ENV default variables. In production, these are set through Doppler project that will sync variables to Heroku as well.

Required everywhere

  • NODE_ENV: The environment to run the application in. One of production, development (default), or test (for use in automated tests).
  • PORT: The port to run the application on.

Required in Heroku

  • CHANGE_API_KEY: The change-log API key to use when creating and closing change-logs.
  • ORIGAMI_GITHUB_TOKEN: A GitHub token with permission to read the private o-fonts-assets repository.
  • GRAPHITE_API_KEY: The FT's internal Graphite API key
  • GRAPHITE_HOST: The hostname of a Graphite server to gather metrics with.
  • REGION: The region the application is running in. One of QA, EU, or US
  • RELEASE_ENV: The Salesforce environment to include in change-logs. One of Test or Production
  • SENTRY_DSN: The Sentry URL to send error information to
  • ARCHIVE_BUCKET_NAME: The AWS S3 bucket to use to retrieve archived responses. One of origami-build-service-archive-prod (default) or origami-build-service-archive-test.

Optional

  • NPM_REGISTRY_URL: The npm Registry url to use when installing npm dependencies. Defaults to https://registry.npmjs.org.

Testing

The tests are split into unit tests, integration tests, and an old suite of tests that we're migrating. To run tests on your machine you'll need to install Node.js and run make install. Then you can run the following commands:

make test              # run all the tests
make test-unit         # run the unit tests
make test-integration  # run the integration tests

You can run the unit tests with coverage reporting.

make test-unit-coverage verify-coverage

The code will also need to pass linting on CI, you can run the linter locally with:

make verify

We run the tests and linter on CI, you can view [results on CI][ci]. make test and make verify must pass before we merge a pull request.

You can run the integration tests against a URL by setting a HOST environment variable to the URL you want to test. This is useful for testing a Heroku application after it is deployed, which we do on CI.

HOST="https://www.example.com" make test-integration

Deployment

The production (EU/US) and QA applications run on Heroku. We deploy continuously to QA via [CI][ci], you should never need to deploy to QA manually. We use a Heroku pipeline to promote QA deployments to production.

You can promote either through the Heroku interface, or by running the following command locally:

make promote

You may need to clear cdn cache for the release to take immediate effect. For example when updating documentation.

Cache Purge

First, change the hostname in your request to origami-build-service-eu.herokuapp.com. If your update does not appear, an old version is cached on the file system. Clear this by restarting the Heroku dynos:

heroku restart --app origami-build-service-eu

If your change does appear then the old result may be cached by our CDN. You'll need to wait for a while, or clear the CDN cache. To clear CDN cache login to Fastly and find the www.ft.com Fastly service. Clear a specific URL (e.g. for a documentation update) or one or more of the following surrogate keys:

Documentation Cache Purge

All documentation pages e.g. /v2, /v2/api, /v2/migration, /v3/, /v3/api:

  • origami-build-service-website

V3 API Cache Purge

All bundle pages e.g. /v3/bundles/css:

  • origami-build-service-v3-js
  • origami-build-service-v3-css

All fonts i.e. /v3/font:

  • origami-build-service-v3-font

All demo pages e.g. /v3/demo:

  • origami-build-service-v3-demo

V2 API Cache Purge

All bundle pages e.g. /v2/bundles/css:

  • origami-build-service-v2-js
  • origami-build-service-v2-css

All file pages i.e. /v2/files:

  • origami-build-service-v2-files

All demo pages e.g. /v2/demos:

  • origami-build-service-v2-demos

Monitoring

Logging

We use Splunk to store and query our application and CDN log files. Using Splunk we can answer many questions, such as: which product is using our services the most; which components are not being requested (good candidates to deprecate).

Here is an example query which was used to find out if our o-big-number component was being requested.

Here is an example query which shows the last hour of logs from our CDN.

Trouble-Shooting

We've outlined some common issues that can occur when running the Build Service:

What do I do if memory usage is high?

For now, restart the Heroku dynos:

heroku restart --app origami-build-service-eu

If this doesn't help, then a temporary measure could be to add more dynos to the production applications, or switch the existing ones to higher performance dynos.

What if I need to deploy manually?

If you really need to deploy manually, you should only do so to QA. Production deploys should always be a promotion from QA.

You'll need to provide an API key for change request logging. You can get this from the Origami LastPass folder in the note named Change Request API Keys. Now deploy to QA using the following:

CR_API_KEY=<API-KEY> make deploy

What do I do if my updated component is not appearing in bundles?

This is most likely due to the heavy caching we use. See Cache Purge.

License

The Financial Times has published this software under the MIT license.

origami-build-service's People

Contributors

actions-user avatar akomiqaia avatar alicebartlett avatar chee avatar dependabot-preview[bot] avatar dependabot[bot] avatar frshwtr avatar gvonkoss avatar jakechampion avatar kiyagu avatar limess avatar notlee avatar onishiweb avatar origamiserviceuser avatar rowanbeentje avatar rowanmanning avatar snyk-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

origami-build-service's Issues

Script loading callback/event

I'd like to explore using build service for loading a few very stable origami components e.g. o-errors. In order for next's application code to wait for the build service script to load it'd be good to have either a callback or an event fired.

Pros of callback

  • very backwards compatible
  • could be passed the exported bundle so that the application code can store a reference to it as it wishes

Pros of event

  • events feels like a better paradigm to use
  • doesn't require polluting window

Add CORS header to JS build endpoint

So that I can use the crossorigin=anonymous attribute on script tags to get better error info.

Also o-cookie-message uses local storage so doesn't always work with the build service.

Update integration tests when Origami spec v2 components are released

https://origami-npm-registry-prototype.herokuapp.com is not used as the NPM_REGISTRY_URL in production, https://registry.npmjs.com is used. That could lead to errors being missed by our tests.

To catch a similar error in the future, remove https://origami-npm-registry-prototype.herokuapp.com from integration tests when components which follow the proposed Origami v2 specification are released to the official npm registry.

npmRegistryURL: process.env.NPM_REGISTRY_URL || 'https://origami-npm-registry-prototype.herokuapp.com',

Stale while revalidate

For a bundle that has previously been built by the build service, I never want to have to wait for a synchronous build of it again, regardless of how frequently it is requested.

Add task for image sets

Currently, for image sets to appear in the registry, they must have a file could ImageList.json in their root which lists all of the images to show in the registry. See https://github.com/Financial-Times/fticons for the schema.

This imageList has to be kept up to date in order for the registry demo to match up with what's live. This is normally done by people remembering to run the gulp task that creates the list.

This is bad because (1) people forget (2) we have a gulp task across multiple copied across multiple repos (3) we introduce a dependency on gulp which a lot of people who contribute to various image sets don't have installed.

A good solution would be to move this behaviour (generating an index of images in the /src/ folder and putting it in the root) to the build service.

Possible cache issue with demo endpoint

[originally reported by @AlbertoElias]

OBT has a bug where it builds demos indentically when building multiple of them that share the same template. Build service shouldn't have this issue as it only compiles one demo at a time, but with o-header, it generates the core demo for the enhanced one.

Redirect the files and modules routes

For consistency with bundles, should we add the following redirects?

/files/* > /v2/files/*
/v1/files/* > /v2/files/*
/modules/* > /v2/modules/*
/v1/modules/* > /v2/modules/*

The code that handles these is exactly the same. Could we see this causing any issues, apart from the additional load of the redirects. Can we get logs for these routes?

Clarification on polyfills

Need clarification on this:

polyfills (Optional) If present and set to 'none', does not add polyfills to the output. Use this if your bundle is conflicting with other polyfills (e.g. through the Polyfill Service).

Which polyfills are we talking about? What features do I need to get from polyfill service if I set polyfills=none on the build service?

Question: Do multiple separate script tags share the same exported global?

If I have this script tag:

<script async src="https://origami-build.ft.com/v2/bundles/js?modules=o-tracking"></script>

...then later I dynamically add another script tag to load another Origami module:

<script async src="https://origami-build.ft.com/v2/bundles/js?modules=o-expander"></script>

...does the second one overwrite the Origami global exported by the first one? Or does each script check for an existing Origami global and just append its own new properties if found? i.e. will I end up with a single global called Origami with two properties 'o-expander' and 'o-tracking'?

Issue: ESM module support

What

Reading about pika web got me to thinking about how similar moves could make the build service esm module ready, and reduce the need for bundlers.

Description

e.g. could import { oThingy, oGoody } from 'https://build.origami/.... in your script

Raises the question of whether there should be convenience urls for individual modules e.g. https://www.ft.com/__origami/service/build/v2/esm/o-thingy@semver, and that all of these import their deps rather than bundling

Just an idea for discussion rather than a serious feature request at this stage. Though I would happily be a beta tester

Disable adding Babel polyfills by default

We currently have a parameter polyfills which can be used to disable the adding of Babel polyfills. We'd like to make this default behaviour, but this would be a breaking change to the API.

Unversioned urls whitelist to move users to versioned urls

We talked about generating a whitelist based on our logs of users currently using the unversioned build service url (/bundles instead of /v2/bundles) and not allowing any further users to use the unversioned one, forcing them to add the explicit version to the url

Feature: add support for spec v2 origami components

What

Let's make the build service work for spec v2 origami components, which are only install-able from npm and not from bower.

Here is the proposal -- https://github.com/Financial-Times/origami/pull/86/files
Here is the spec v2 draft -- Financial-Times/origami-website#273

Details

We need to have the build service work for our components when they all update to be compliant with the v2 spec.

Currently the build service installs only from bower, we will need to make it be able to install from npm as well.

Additional information

npm installs are trickier than bower install because the npm install can run scripts from the installed packages (and does so by default) which is a potential security risk for the build service. when we run npm install we need to ensure we run it like this:

npm install --production --no-audit --ignore-scripts 

That will only install production dependencies, which should lead to a faster completion of the install. It will also not run the scripts from the packages, which protects us from the potential security risk. Finally it will not run npm audit at the end of the install phase, which should lead to a faster completion of the install.

Use origami-repo-data to fetch list of components to add to the npm cache upon server booting up

Currently the project is using a fixed this.This probably shouldn't exist as a fixed list.
It should use an origami-repo-data api call to get the list similar to origami-component-converter and fallback to a fixed list if the origami-repo-data api call fails.

We can reuse some code in origami component converter which does a similar thing --
https://github.com/Financial-Times/origami-component-converter/blob/10990dac98e980594a329f0cd68537b0e51a6560/lib/npm.js#L8-L17

Originally posted by @JakeChampion in #391 (comment)

Whitelist components allowed to generate demos

Whitelist the components allowed to have demos compiled (Only Origami components). We can probably do this by checking that the component exists on the Origami Bower registry.

Currently it is possible to compile demos for any component on the global Bower registry.

Add migration for the `v3/files` endpoint

  • The main usecase for the files endpoint is to include font files from o-fonts-assets.
  • Other uses appear to be old component assets (file endpoint Splunk statistics).
  • No current component version includes assets in this way. None will in the same way going forward, as it will not work with npm. There's a proposal for handling component assets in the future.
  • If we require a system code to include fonts, and pass through the system code of the project consuming Origami, the client won't cache fonts between pages of the ft (pretty major, fonts are heavy)
  • Instead we decided it would be better to remove the file endpoint from v3 and host fonts in S3. We could do this just for o-fonts-assets in whatever way is easiest, or perhaps we go ahead and implement the asset proposal for all components?

Relates to: #408

Suggestion: Use `.env` for development environment variables instead of `docker-compose.yml`

Currently the README advocates storing confidential environment variables inside docker-compose.yml for local development. This becomes a bit messy because that file is included within git but will become personal to each developer's set-up (API keys, auth tokens, database names etc). A developer may accidentally commit their environment variables into the git history (which is a bad thing tm).

Have you thought about using dotenv instead of placing the environment variables within docker-compose.yml?

docker-compose.yml is commited into the repo whereas .env can be ignored in .gitignore. This means confidential env vars can be stored in it safely and because the file is ignored by git it won't be deployed to production.

Stale on error

If/when github goes down, I still want to be able to request any bundle that has previously been built by the build service.

Auto CTM in the build service

From: Financial-Times/ft-origami#438

Recent stuff like http://git.svc.ft.com/projects/OT/repos/build-service/pull-requests/58/overview has me thinking: it's quite hard to get people to implement a CTM test, particularly so when they are using the build service. If performance is critical to your application you won't be using the OBS anyway because you will be wanting to custom-compile the components with your own JS and CSS, so...

Could we add an endpoint to the build service that layers a CTM on top of the JS bundle call? So you'd do this in your page:

<script src="//build.origami.ft.com/v2/bundles/js?modules=o-fonts,o-header,...&amp;ctm=ft1"></script>

Now instead of returning the bundle you requested, OBS instead returns this, with very generous cache headers:

(function() {
var cutsTheMustard = ('querySelector' in document && 'localStorage' in window && 'addEventListener' in window);
if (cutsTheMustard) {
   document.documentElement.className = document.documentElement.className.replace(/\bcore\b/g, 'enhanced');
   var o = document.createElement('script');
   o.async = o.defer = true;
   o.src = "//build.origami.ft.com/v2/bundles/js?modules=o-fonts,o-header,...";
   var s = document.getElementsByTagName('script')[0];
   s.parentNode.insertBefore(o, s);
}
}());

Surface the babel-runtime disabling flag from OBT

Problem

I want to use polyfill from the Polyfill Service and not the ones given by OBS. Now that the Polyfill Service is adding more ES6 polyfills we are seeing clashes between the polyfills from OBS and the ones from the Polyfill Service. Currently we can sidestep this issue by excluding these polyfills from the Polyfill Service and using the polyfills from OBS however this means that our end-users lose the benefit of the polyfill service as every single user will receive the polyfills given by OBS instead of only the users which require them.

Solution

Have a query parameter which when set, disables the babel-runtime set of polyfills. OBT has had a flag to disable the babel-runtime for a few months, meaning this problem doesn't exist for developers who use OBT directly.

Increase cache time for deprecated bundle redirects

It looks like we are not explicitly setting a cache time for the deprecated bundle redirects. We can probably set a long time to cache the redirect for as we know for certain that bundle will always be redirected.

Memory issues

We seem to have picked up some memory issues between the 3.0.4 and 3.0.5 production deploys. Version 3.0.4 was deployed to production on 2016-03-15, and 3.0.5 was deployed on the 2016-03-18. This graph shows the change in memory usage from 12th–22nd:

Build Service Memory Usage: 12th–22nd March 2016

The drops in usage correspond to Heroku restarting the dynos, I imagine the usage would continue to trend upwards if the restarts weren't happening.

Help with constructing build service urls

[suggestion from the origami expert user forum]
Have a page which throws together the latest versions of components, with the latest version numbers, that a user can select to generate a url which they can then copy/paste into their application. Similar to the image service docs. (suggestion from @wheresrhys )

Refactor the tests to run in the container

Ideally the tests should be runnable in either the container or the developer's machine. Currently they're pretty much only runnable on the dev machine. In CI we probably want to run the integration tests against the container.

Shrinkwrap URLs and non-semver versions

The way that shrinkwrap URLs are calculated doesn’t account for non-semver versions in the bower config (e.g. a git URL or GitHub username/repo).

For example: o-techdocs includes highlight.js, but from our shim version: https://github.com/Financial-Times/o-techdocs/blob/master/bower.json#L7

Currently when the shrinkwrap URL is generated it references highlight.js@undefined rather than Financial-Times/highlight.js-shim@<commit-hash> (which works).

I'm looking into whether I can fix this without breaking other shrinkwrap URLs. Unfortunately this means that current shrinkwraps will never work, unless I add in a specific case to always serve our version of highlight.js (which would be super hacky).

Steps to reproduce:

  1. Visit https://build.origami.ft.com/v2/bundles/css?modules=o-header@^4,o-techdocs@^5,o-colors@^3,o-fonts@^2,o-forms@^2,o-buttons@^3 – this should output a working bundle
  2. Copy the shrinkwrap URL (should be something like this) – this should output a 404 error, outlining that danielditgens/highlight.js doesn't exist

Workaround (temporary)

Replace highlight.js%40undefined in the shrinkwrapped URL with Financial-Times/highlight.js-shim@5eb4727ba777e7683140de72ba01468e81639827 (like this) – this should output a working bundle.

Find a replacement for the diskspace module

The module is unreliable and it gets free space values by parsing a table output by the df command. The df command output is different on different Linux distributions, which caused some issues when moving to Alpine.

Also we currently maintain a forked version of the module and so have to install it through git. We could remove git as a dependency and reduce the container size if we find a good npm-hosted module.

Make the tests less fragile

Currently the tests can fail quite easily for unrelated reasons if, for example, a new version of a component is released. We should probably use Regular Expressions for testing some of the output to ensure that this doesn't happen.

There are probably some other improvements we can make (I'll list here when I think of them)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.