Skip to content

Ideal Plugin Development Environment

Adam Hooper edited this page Jan 18, 2018 · 2 revisions

Our experience with Overview plugins leads us to these best practices for developing plugins.

These are all guidelines, not rules. They explain how people expect to create, maintain and consume an Overview plugin.

Development environment: ./dev

Users should be able to develop the plugin with two steps:

  1. Download and run overview-server's ./dev
  2. Download and run your plugin's ./dev

The contract:

  • The plugin listens within a Docker container with --network=overviewserver_default.
  • The Docker container is an HTTP server listening on port 80. It's redirected to port 3334 on localhost: that is, ./dev invokes Docker with --publish 127.0.0.1:3334:80.
  • The Docker container has a fixed name, so it can be used by integration-test/run.
  • The Docker container "recompiles" (as in, adjusts its outputs) when you edit source code. The usual way to do this is to mount your source code in read-only --volume arguments. Recompilation should be quick.
  • The Docker container does not write any files.
  • You can cancel the server using Ctrl+C.
  • Bonus points: during recompilation, your Docker container runs unit tests and outputs results to a console.

Integration tests: ./integration-test/run-in-docker-compose

You desperately need integration tests for your plugin. You can install integration tests with a single command: see overview-integration-tester.

See overview-integration-tester for the contract. Basically, this should spin up and shut down an entire Overview environment including your plugin (built using your Dockerfile) and verify that your plugin actually does things. This mimics how your plugin will behave in overview-local.

Dockerfile

We publish all plugins as Docker images on Docker Hub, so overview-local can download and run them locally.

Usually, a production image has very different files than a development image. Make a modest effort not to inflate the image size of the production image.

The contract:

  • It's a multi-stage build.
  • A development stage is there for ./dev
  • A production stage creates a Docker image that runs an HTTP server listening on port 80. This is the final stage, for integration-test/run-in-docker-compose and Docker Hub

./release 1.0.1: push to Git and Docker Hub

The ./release command should push a new version online, so other projects (such as overview-local) can use it.

The contract:

  • The version number should follow semver, and the MAJOR version should always be 1.
  • It should push master and v1.0.1 to GitHub.
  • Docker Hub's Automated Build should have triggers to build major, minor and patch versions. For instance, the "patch" trigger (i.e., the one that creates Docker image version :1.0.1) should have Type=Tag, Name=/^v([0-9]+)\.([0-9]+)\.([0-9]+)$/, Dockerfile Location=/, Docker Tag Name={\1}.{\2}.{\3}.

./deploy: make it live (static sites only)

For a plugin with a server component, ./release is the best you can do. Tell your users to download the new version when it's available.

If your plugin is a static site, though, you don't need a Docker container on production. You can serve your plugin using an S3 bucket to save money.

We recommend using in-memory-website to simplify this workflow. Picture it:

  • ./dev uses the development Dockerfile stage to watch for file changes, write the entire website to a single file, and serve the website from that single file using in-memory-website-http-server.
  • A build Dockerfile stage inherits the development stage and compiles the in-memory website to a file.
  • The production Dockerfile stage inherits adamhooper/in-memory-website-http-server and copies the file from the build stage.
  • ./deploy uploads the in-memory website to S3.

This makes development pleasant because you can be confident that the static site served in production is as similar as possible to the static site served from S3.

Clone this wiki locally