Skip to content

artsy/horizon

Repository files navigation

Horizon CircleCI

Visual representations of release pipelines.

Quick links

Setup

Local development depends on a .env.shared file (sourced from S3) and a .env file for any overrides or additions. The setup script will initialize these in addition to installing prerequisites and generating seed data:

./bin/setup

Then, to develop with docker:

hokusai dev run 'bundle exec rake db:prepare db:seed:replant'
hokusai dev start

Or on localhost:

yarn install
foreman run bundle exec rails server

# run the webpack-dev-server in a seperate terminal window for hot reloading and faster compilation:
./bin/webpack-dev-server

The UI can then be found at http://localhost:3000.

Design

  • Organizations have many Projects
  • Each Project has an associated list of Stages, with their order determined by Stage#position (e.g., main, 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: main), 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 main 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.

Adding a new project

  • Navigate to the new project form and specify the name, description, and any tags (often teams) associated with the project.
  • Follow the stages link and click to create a new stage:
    • Choose a "profile" granting access to the repository or deployment (e.g., github...)
    • Enter a name, usually main to start
    • Enter a git remote (e.g., https://github.com/artsy/delta.git)
    • Enter a tag pattern, branch, or hokusai environment associated with the deployment. For "main," these are usually blank.
  • Create additional stages for staging (usually specifying the staging hokusai environment), and production (usually specifying the production hokusai environment), if applicable.
  • After defining the production stage, follow the link to create a new deploy strategy.
    • Choose github pull request as the provider
    • Choose a profile granting necessary access (usually github...)
    • Check the Automatic box so that new release pull requests are opened automatically upon changes being pushed to staging.
    • Provide arguments specifying the relevant branches (usually {"base":"release","head":"staging"})
      • base is the branch name that this deploy PR will merge onto.
      • head is the horizon stage name that this deploy PR will start from.
  • To merge release pull requests automatically, specify the additional merge_after (in seconds) and--for an optional notification--slack_webhook_url (from Horizon's slack settings). E.g.:
{
  "base": "release",
  "head": "staging",
  "merge_after": 86400,
  "slack_webhook_url": ["https://hooks.slack.com/services/T.../B.../Q...", "https://hooks.slack.com/services/O.../C.../U..."],
  "blocked_time_buckets": ["* 1-2 * * *"]

}

Adding a "deploy block"

  • Navigate to the new deploy block form.
  • Choose a project and describe the reason for blocking deploys. Leave "resolved at" blank.
  • While the block is unresolved, Horizon will not open new release pull requests or merge existing ones, but manual merges or deploys are still possible. CircleCI release workflows can use the block step defined in the artsy/release orb to short-circuit release builds.
  • Once resolved, click edit in the list of deploy blocks and specify a "resolved at" time.

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
  • 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
  • re-expose comparison errors in UI
  • Experiment with programmatic git/hokusai access instead of shelling out
  • button to refresh project on-demand