/horizon

Primary LanguageRuby

Horizon

Visual representations of release pipelines.

Quick links

Design

  • Organizations have many Projects
  • Each Project has an associated list of Stages, with their order determined by Stage#position (e.g., master, staging, and production)
  • Stages must describe how to get information about their current state. This takes the form of a #git_remote (e.g., referring to Github or Heroku), optional #branch name (default: master), optional #hokusai environment (e.g., staging or production), or #tag_pattern (e.g., release-*). The releasecop gem is used internally to determine stage diffs, so see that project for more detail.
  • Stages can optionally be associated with a Profile that stores credentials for accessing git providers or AWS.
  • Snapshots capture the complete state of a project's stages at a point in time. Each Snapshot has associated Comparisons between the consecutive stages of a project (e).g., a comparison between master and staging, and a second between staging and production)
  • A cron periodically reevaluates these comparisons, creating a new snapshot if the state has changed at all.
  • A Stage (such as "production") can have a DeployStrategy for automatically triggering releases. Currently only the "github pull request" provider is implemented. When defined, a deploy strategy will automatically start a release (e.g., by opening a pull request) when a diff exceeds a certain threshold.
  • DeployBlocks indicate that a project should not be released. In addition to appearing on dashboards, any unresolved blocks will prevent new releases from being automated.

Setup

hokusai dev run 'bundle exec rake db:migrate'
hokusai dev start

The administrative UI can then be found at http://localhost:3000/admin. Create organizations, projects, profiles, and stages from there. Alternatively, here's an example using the console:

org = Organization.create!(name: 'Acme')
website = org.projects.create!(name: 'acme.org')
heroku = org.profiles.create!(
  name: 'heroku',
  basic_username: 'heroku',
  basic_password: '<heroku_token>'
)
github_aws = org.profiles.create!(
  name: 'github/aws',
  basic_username: 'github',
  basic_password: '<github_token>',
  environment: {'AWS_ACCESS_KEY_ID' => '<aws_id>', 'AWS_SECRET_ACCESS_KEY' => '<aws_secret>'}
)
website.stages.create!(
  name: 'master',
  git_remote: 'https://github.com/acme/website.git',
  profile: github_aws
)
website.stages.create!(
  name: 'staging',
  git_remote: 'https://git.heroku.com/acme-website-staging.git',
  profile: heroku
)
website.stages.create!(
  name: 'production',
  git_remote: 'https://git.heroku.com/acme-website-production.git',
  profile: heroku
)

Once the cron has run, its snapshots are visible from the /projects page.

TO DO

  • Support hokusai
  • Better visual
  • Allow SSH keys to be configured for each org or project (probably like git config --local core.sshCommand "ssh -i ~/.ssh/some_key_file"...). (Maybe not necessary given github/heroku tokens in https URLs)
  • sanitize URLs with tokens/credentials in them
  • instead of including tokens in each git URL, define "profiles" associated with each organization and project
  • Experiment with programmatic git/hokusai access instead of shelling out
  • button to refresh project on-demand
  • Fix ugly AWS credentials -> hokusai flow
  • Make errors [when refreshing projects] visible and avoid short-circuiting entire cron
  • Make sorting and classifying of projects more sophisticated (penalize staleness and number of contributors and not just number of commits)
  • Add tags to projects and enable filtering dashboard/list view by them