shipit-engine 0.14.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -0
  3. data/app/jobs/shipit/deferred_touch_job.rb +9 -0
  4. data/app/jobs/shipit/perform_task_job.rb +1 -1
  5. data/app/jobs/shipit/{update_estimated_deploy_duration.rb → update_estimated_deploy_duration_job.rb} +0 -0
  6. data/app/models/concerns/shipit/deferred_touch.rb +92 -0
  7. data/app/models/shipit/commit.rb +7 -9
  8. data/app/models/shipit/delivery.rb +2 -0
  9. data/app/models/shipit/deploy_spec.rb +8 -0
  10. data/app/models/shipit/deploy_spec/file_system.rb +3 -1
  11. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +37 -0
  12. data/app/models/shipit/deploy_spec/npm_discovery.rb +81 -0
  13. data/app/models/shipit/stack.rb +1 -2
  14. data/app/models/shipit/status.rb +8 -9
  15. data/app/models/shipit/task.rb +5 -1
  16. data/config/secrets.development.example.yml +4 -0
  17. data/config/secrets.development.shopify.yml +4 -0
  18. data/config/secrets.development.yml +1 -1
  19. data/db/migrate/20161205144522_add_indexes_on_deliveries.rb +17 -0
  20. data/db/migrate/20161206104100_delete_orphan_statuses.rb +10 -0
  21. data/db/migrate/20161206104224_denormalize_stack_id_on_statuses.rb +5 -0
  22. data/db/migrate/20161206104817_backfill_stack_id_on_statuses.rb +13 -0
  23. data/db/migrate/20161206105318_makes_stack_id_not_null_on_statuses.rb +5 -0
  24. data/lib/shipit.rb +3 -0
  25. data/lib/shipit/strip_cache_control.rb +40 -0
  26. data/lib/shipit/version.rb +1 -1
  27. data/lib/snippets/assert-npm-version-tag +22 -0
  28. data/lib/snippets/deploy-to-gke +3 -4
  29. data/lib/tasks/cron.rake +7 -0
  30. data/test/dummy/config/environments/development.rb +6 -2
  31. data/test/dummy/config/environments/test.rb +4 -0
  32. data/test/dummy/db/development.sqlite3 +0 -0
  33. data/test/dummy/db/schema.rb +32 -42
  34. data/test/dummy/db/seeds.rb +2 -0
  35. data/test/dummy/db/test.sqlite3 +0 -0
  36. data/test/fixtures/shipit/statuses.yml +10 -0
  37. data/test/models/commits_test.rb +26 -20
  38. data/test/models/deploys_test.rb +2 -2
  39. data/test/models/stacks_test.rb +9 -12
  40. data/test/models/status_test.rb +4 -4
  41. data/test/unit/deploy_spec_test.rb +146 -1
  42. metadata +14 -3
@@ -1,5 +1,7 @@
1
1
  module Shipit
2
2
  class Task < ActiveRecord::Base
3
+ include DeferredTouch
4
+
3
5
  PRESENCE_CHECK_TIMEOUT = 15
4
6
  ACTIVE_STATUSES = %w(pending running aborting).freeze
5
7
  COMPLETED_STATUSES = %w(success error failed flapping aborted).freeze
@@ -10,10 +12,12 @@ module Shipit
10
12
  belongs_to :deploy, foreign_key: :parent_id, required: false # required for fixtures
11
13
 
12
14
  belongs_to :user
13
- belongs_to :stack, touch: true, counter_cache: true
15
+ belongs_to :stack, counter_cache: true
14
16
  belongs_to :until_commit, class_name: 'Commit'
15
17
  belongs_to :since_commit, class_name: 'Commit'
16
18
 
19
+ deferred_touch stack: :updated_at
20
+
17
21
  has_many :chunks, -> { order(:id) }, class_name: 'OutputChunk', dependent: :delete_all
18
22
 
19
23
  serialize :definition, TaskDefinition
@@ -17,3 +17,7 @@ github_oauth:
17
17
  # features:
18
18
  # - bootstrap
19
19
 
20
+ # To work on the kubernetes deploy script
21
+ # env:
22
+ # KUBECONFIG: # Path of the kubeconfig you want to use.
23
+ # GOOGLE_APPLICATION_CREDENTIALS: # Used if your kube auth provider is gcp, in which case it should be path of the service account credentials you want to use. Alternatively, you can run `gcloud auth application-default login` (and remove this variable) to use your own google account locally.
@@ -17,3 +17,7 @@ github_oauth:
17
17
  # features:
18
18
  # - bootstrap
19
19
 
20
+ # To work on the kubernetes deploy script
21
+ # env:
22
+ # KUBECONFIG: # Path of the kubeconfig you want to use.
23
+ # GOOGLE_APPLICATION_CREDENTIALS: # Used if your kube auth provider is gcp, in which case it should be path of the service account credentials you want to use. Alternatively, you can run `gcloud auth application-default login` (and remove this variable) to use your own google account locally.
@@ -2,7 +2,7 @@ host: 'http://shipit-engine.localhost'
2
2
  redis_url: 'redis://shipit-engine.railgun:6379'
3
3
 
4
4
  github_api:
5
- access_token: caa4f8b2bb3d94269291faf9b54b85457db0173b
5
+ access_token: 4cc410d7a8fb04f6095076f519f7e0981d915136
6
6
 
7
7
  # If you want to test GitHub Authentication
8
8
  github_oauth:
@@ -0,0 +1,17 @@
1
+ class AddIndexesOnDeliveries < ActiveRecord::Migration[5.0]
2
+ def up
3
+ change_column :deliveries, :status, :string, limit: 50
4
+ change_column :deliveries, :event, :string, limit: 50
5
+ add_index :deliveries, [:hook_id, :event, :status]
6
+ add_index :deliveries, [:status, :event]
7
+ add_index :deliveries, :created_at
8
+ end
9
+
10
+ def down
11
+ change_column :deliveries, :status, :string, limit: 255
12
+ change_column :deliveries, :event, :string, limit: 255
13
+ remove_index :deliveries, [:hook_id, :event, :status]
14
+ remove_index :deliveries, [:status, :event]
15
+ remove_index :deliveries, :created_at
16
+ end
17
+ end
@@ -0,0 +1,10 @@
1
+ class DeleteOrphanStatuses < ActiveRecord::Migration[5.0]
2
+ def up
3
+ ids = Shipit::Status.left_joins(:commit).where(commits: {id: nil}).pluck(:id)
4
+ say "Found #{ids.size} orphan statuses"
5
+ Shipit::Status.where(id: ids).delete_all
6
+ end
7
+
8
+ def down
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class DenormalizeStackIdOnStatuses < ActiveRecord::Migration[5.0]
2
+ def change
3
+ add_column :statuses, :stack_id, :integer, null: true
4
+ end
5
+ end
@@ -0,0 +1,13 @@
1
+ class BackfillStackIdOnStatuses < ActiveRecord::Migration[5.0]
2
+ def up
3
+ Shipit::Commit.order(stack_id: :asc).find_in_batches do |commits|
4
+ commits.group_by(&:stack_id).each do |stack_id, stack_commits|
5
+ Shipit::Status.where(commit_id: stack_commits.map(&:id)).update_all(stack_id: stack_id)
6
+ end
7
+ print '.'
8
+ end
9
+ end
10
+
11
+ def down
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ class MakesStackIdNotNullOnStatuses < ActiveRecord::Migration[5.0]
2
+ def change
3
+ change_column_null :statuses, :stack_id, false
4
+ end
5
+ end
data/lib/shipit.rb CHANGED
@@ -46,6 +46,7 @@ require 'shipit/deploy_commands'
46
46
  require 'shipit/rollback_commands'
47
47
  require 'shipit/environment_variables'
48
48
  require 'shipit/stat'
49
+ require 'shipit/strip_cache_control'
49
50
 
50
51
  SafeYAML::OPTIONS[:default_mode] = :safe
51
52
  SafeYAML::OPTIONS[:deserialize_symbols] = false
@@ -111,8 +112,10 @@ module Shipit
111
112
  logger: Rails.logger,
112
113
  serializer: NullSerializer,
113
114
  )
115
+ builder.use StripCacheControl
114
116
  builder.use Octokit::Response::RaiseError
115
117
  builder.adapter Faraday.default_adapter
118
+ yield builder if block_given?
116
119
  end
117
120
  end
118
121
 
@@ -0,0 +1,40 @@
1
+ module Shipit
2
+ class StripCacheControl < Faraday::Middleware
3
+ def call(request_env)
4
+ @app.call(request_env).on_complete do |response_env|
5
+ if headers = response_env[:response_headers]
6
+ headers.delete('last-modified')
7
+ directives = parse(headers['cache-control'].to_s)
8
+ directives.delete('max-age')
9
+ directives.delete('s-maxage')
10
+ headers['cache-control'] = dump(directives)
11
+ end
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def dump(directives)
18
+ directives.map do |k, v|
19
+ if v == true
20
+ k
21
+ else
22
+ "#{k}=#{v}"
23
+ end
24
+ end.join(', ')
25
+ end
26
+
27
+ def parse(header)
28
+ directives = {}
29
+
30
+ header.delete(' ').split(',').each do |part|
31
+ next if part.empty?
32
+
33
+ name, value = part.split('=', 2)
34
+ directives[name.downcase] = (value || true) unless name.empty?
35
+ end
36
+
37
+ directives
38
+ end
39
+ end
40
+ end
@@ -1,3 +1,3 @@
1
1
  module Shipit
2
- VERSION = '0.14.0'.freeze
2
+ VERSION = '0.15.0'.freeze
3
3
  end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env bash
2
+
3
+ VERSION=`node --eval "var version = require('./package.json').version; console.log(version)"`
4
+
5
+ echo -e "\033[0;32mTrying to publish version $VERSION\033[0m"
6
+
7
+ git tag | grep "^v$VERSION$" > /dev/null
8
+ if [ $? != '0' ]; then
9
+ echo -e "\033[1;31mYou need to create the \033[0;33mv$VERSION\033[1;31m tag first.\033[0m"
10
+ exit 1
11
+ fi
12
+
13
+ TAG_REV=`git rev-list -n1 v$VERSION`
14
+ HEAD_REV=`git rev-parse HEAD`
15
+
16
+ if [ $TAG_REV != $HEAD_REV ]; then
17
+ echo -e "\033[1;31mYou're attempting to publish \033[0;33m$HEAD_REV\033[1;31m as \033[0;33mv$VERSION\033[1;31m but it already points to \033[0;33m$TAG_REV\033[1;31m.\033[0m"
18
+ exit 1
19
+ fi
20
+
21
+ echo -e "\033[0;32mAll clear!\033[0m"
22
+ exit 0
@@ -21,12 +21,12 @@ require 'tempfile'
21
21
  class GKEDeployment
22
22
  class FatalDeploymentError < StandardError; end
23
23
 
24
- def initialize(namespace:, gcloud_deployment:, gcloud_project:, environment:, current_sha:, key_dir:, template_folder: nil)
24
+ def initialize(namespace:, gcloud_deployment:, gcloud_project:, environment:, current_sha:, key_file:, template_folder: nil)
25
25
  @namespace = namespace
26
26
  @gcloud_deployment = gcloud_deployment
27
27
  @gcloud_project = gcloud_project
28
28
  @current_sha = current_sha
29
- @key_file = "#{key_dir}/#{@gcloud_project}.json"
29
+ @key_file = key_file
30
30
  @template_path = './' + (template_folder || "config/deploy/#{environment}")
31
31
 
32
32
  # Validate params + check existance of auth key and template(s)
@@ -106,7 +106,6 @@ class GKEDeployment
106
106
  end
107
107
 
108
108
  def authorize_gcloud
109
- ENV['GOOGLE_APPLICATION_CREDENTIALS'] = @key_file
110
109
  status = run_command('gcloud', '-q', 'auth', 'activate-service-account', '--key-file', @key_file)
111
110
  status = run_command('gcloud', '-q', 'config', 'set', 'project', @gcloud_project) if status
112
111
  raise FatalDeploymentError, "Failed to set gcloud project #{@gcloud_project}" unless status
@@ -157,6 +156,6 @@ deployment = GKEDeployment.new(
157
156
  environment: ENV['ENVIRONMENT'],
158
157
  template_folder: ENV['K8S_TEMPLATE_FOLDER'],
159
158
  current_sha: ENV['REVISION'],
160
- key_dir: ENV['GCLOUD_CREDENTIALS_DIR']
159
+ key_file: ENV['GOOGLE_APPLICATION_CREDENTIALS']
161
160
  )
162
161
  deployment.run
data/lib/tasks/cron.rake CHANGED
@@ -6,11 +6,18 @@ namespace :cron do
6
6
  Shipit::GithubStatus.refresh_status
7
7
  end
8
8
 
9
+ task hourly: [:rollup, :purge_deliveries, :refresh_users]
10
+
9
11
  desc "Rolls-up output chunks for completed deploys older than an hour"
10
12
  task rollup: :environment do
11
13
  Shipit::Task.due_for_rollup.find_each(&:schedule_rollup_chunks)
12
14
  end
13
15
 
16
+ desc "Delete old hook delivery records"
17
+ task purge_deliveries: :environment do
18
+ Shipit::Delivery.due_for_deletion.delete_all
19
+ end
20
+
14
21
  task refresh_users: :environment do
15
22
  Shipit::User.refresh_shard(Time.now.hour % 24, 24)
16
23
  end
@@ -38,6 +38,10 @@ Rails.application.configure do
38
38
 
39
39
  # Raises error for missing translations
40
40
  # config.action_view.raise_on_missing_translations = true
41
-
42
- config.active_job.queue_adapter = :sucker_punch
41
+ if Rails.application.config_for(:database)['adapter'] == 'sqlite3'
42
+ Shipit::DeferredTouch.enabled = false
43
+ end
44
+ config.active_job.queue_adapter = :async
45
+
46
+ Pubsubstub.use_persistent_connections = false
43
47
  end
@@ -39,4 +39,8 @@ Rails.application.configure do
39
39
 
40
40
  # Raises error for missing translations
41
41
  # config.action_view.raise_on_missing_translations = true
42
+
43
+ config.to_prepare do
44
+ Shipit::DeferredTouch.enabled = false
45
+ end
42
46
  end
Binary file
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -11,7 +10,7 @@
11
10
  #
12
11
  # It's strongly recommended that you check this file into your version control system.
13
12
 
14
- ActiveRecord::Schema.define(version: 20160822131405) do
13
+ ActiveRecord::Schema.define(version: 20161206105318) do
15
14
 
16
15
  create_table "api_clients", force: :cascade do |t|
17
16
  t.text "permissions", limit: 65535
@@ -20,10 +19,9 @@ ActiveRecord::Schema.define(version: 20160822131405) do
20
19
  t.datetime "updated_at", null: false
21
20
  t.string "name", limit: 255, default: ""
22
21
  t.integer "stack_id", limit: 4
22
+ t.index ["creator_id"], name: "index_api_clients_on_creator_id"
23
23
  end
24
24
 
25
- add_index "api_clients", ["creator_id"], name: "index_api_clients_on_creator_id"
26
-
27
25
  create_table "commit_deployment_statuses", force: :cascade do |t|
28
26
  t.integer "commit_deployment_id"
29
27
  t.string "status"
@@ -31,10 +29,9 @@ ActiveRecord::Schema.define(version: 20160822131405) do
31
29
  t.string "api_url"
32
30
  t.datetime "created_at", null: false
33
31
  t.datetime "updated_at", null: false
32
+ t.index ["commit_deployment_id"], name: "index_commit_deployment_statuses_on_commit_deployment_id"
34
33
  end
35
34
 
36
- add_index "commit_deployment_statuses", ["commit_deployment_id"], name: "index_commit_deployment_statuses_on_commit_deployment_id"
37
-
38
35
  create_table "commit_deployments", force: :cascade do |t|
39
36
  t.integer "commit_id"
40
37
  t.integer "task_id"
@@ -42,11 +39,10 @@ ActiveRecord::Schema.define(version: 20160822131405) do
42
39
  t.string "api_url"
43
40
  t.datetime "created_at", null: false
44
41
  t.datetime "updated_at", null: false
42
+ t.index ["commit_id", "task_id"], name: "index_commit_deployments_on_commit_id_and_task_id", unique: true
43
+ t.index ["task_id"], name: "index_commit_deployments_on_task_id"
45
44
  end
46
45
 
47
- add_index "commit_deployments", ["commit_id", "task_id"], name: "index_commit_deployments_on_commit_id_and_task_id", unique: true
48
- add_index "commit_deployments", ["task_id"], name: "index_commit_deployments_on_task_id"
49
-
50
46
  create_table "commits", force: :cascade do |t|
51
47
  t.integer "stack_id", limit: 4, null: false
52
48
  t.integer "author_id", limit: 4, null: false
@@ -60,19 +56,18 @@ ActiveRecord::Schema.define(version: 20160822131405) do
60
56
  t.datetime "committed_at", null: false
61
57
  t.integer "additions", limit: 4
62
58
  t.integer "deletions", limit: 4
59
+ t.index ["author_id"], name: "index_commits_on_author_id"
60
+ t.index ["committer_id"], name: "index_commits_on_committer_id"
61
+ t.index ["created_at"], name: "index_commits_on_created_at"
62
+ t.index ["stack_id"], name: "index_commits_on_stack_id"
63
63
  end
64
64
 
65
- add_index "commits", ["author_id"], name: "index_commits_on_author_id"
66
- add_index "commits", ["committer_id"], name: "index_commits_on_committer_id"
67
- add_index "commits", ["created_at"], name: "index_commits_on_created_at"
68
- add_index "commits", ["stack_id"], name: "index_commits_on_stack_id"
69
-
70
65
  create_table "deliveries", force: :cascade do |t|
71
66
  t.integer "hook_id", limit: 4, null: false
72
- t.string "status", limit: 255, default: "pending", null: false
67
+ t.string "status", limit: 50, default: "pending", null: false
73
68
  t.string "url", limit: 4096, null: false
74
69
  t.string "content_type", limit: 255, null: false
75
- t.string "event", limit: 255, null: false
70
+ t.string "event", limit: 50, null: false
76
71
  t.text "payload", limit: 16777215, null: false
77
72
  t.integer "response_code", limit: 4
78
73
  t.text "response_headers", limit: 65535
@@ -80,6 +75,9 @@ ActiveRecord::Schema.define(version: 20160822131405) do
80
75
  t.datetime "delivered_at"
81
76
  t.datetime "created_at", null: false
82
77
  t.datetime "updated_at", null: false
78
+ t.index ["created_at"], name: "index_deliveries_on_created_at"
79
+ t.index ["hook_id", "event", "status"], name: "index_deliveries_on_hook_id_and_event_and_status"
80
+ t.index ["status", "event"], name: "index_deliveries_on_status_and_event"
83
81
  end
84
82
 
85
83
  create_table "github_hooks", force: :cascade do |t|
@@ -92,11 +90,10 @@ ActiveRecord::Schema.define(version: 20160822131405) do
92
90
  t.string "api_url", limit: 255
93
91
  t.string "type", limit: 255
94
92
  t.string "organization", limit: 39
93
+ t.index ["organization", "event"], name: "index_github_hooks_on_organization_and_event", unique: true
94
+ t.index ["stack_id", "event"], name: "index_github_hooks_on_stack_id_and_event", unique: true
95
95
  end
96
96
 
97
- add_index "github_hooks", ["organization", "event"], name: "index_github_hooks_on_organization_and_event", unique: true
98
- add_index "github_hooks", ["stack_id", "event"], name: "index_github_hooks_on_stack_id_and_event", unique: true
99
-
100
97
  create_table "hooks", force: :cascade do |t|
101
98
  t.integer "stack_id", limit: 4
102
99
  t.string "delivery_url", limit: 4096, null: false
@@ -106,29 +103,26 @@ ActiveRecord::Schema.define(version: 20160822131405) do
106
103
  t.boolean "insecure_ssl", default: false, null: false
107
104
  t.datetime "created_at", null: false
108
105
  t.datetime "updated_at", null: false
106
+ t.index ["stack_id"], name: "index_hooks_on_stack_id"
109
107
  end
110
108
 
111
- add_index "hooks", ["stack_id"], name: "index_hooks_on_stack_id"
112
-
113
109
  create_table "memberships", force: :cascade do |t|
114
110
  t.integer "team_id", limit: 4
115
111
  t.integer "user_id", limit: 4
116
112
  t.datetime "created_at", null: false
117
113
  t.datetime "updated_at", null: false
114
+ t.index ["team_id", "user_id"], name: "index_memberships_on_team_id_and_user_id", unique: true
115
+ t.index ["user_id"], name: "index_memberships_on_user_id"
118
116
  end
119
117
 
120
- add_index "memberships", ["team_id", "user_id"], name: "index_memberships_on_team_id_and_user_id", unique: true
121
- add_index "memberships", ["user_id"], name: "index_memberships_on_user_id"
122
-
123
118
  create_table "output_chunks", force: :cascade do |t|
124
119
  t.integer "task_id", limit: 4
125
120
  t.text "text", limit: 16777215
126
121
  t.datetime "created_at"
127
122
  t.datetime "updated_at"
123
+ t.index ["task_id"], name: "index_output_chunks_on_task_id"
128
124
  end
129
125
 
130
- add_index "output_chunks", ["task_id"], name: "index_output_chunks_on_task_id"
131
-
132
126
  create_table "stacks", force: :cascade do |t|
133
127
  t.string "repo_name", limit: 100, null: false
134
128
  t.string "repo_owner", limit: 39, null: false
@@ -148,10 +142,9 @@ ActiveRecord::Schema.define(version: 20160822131405) do
148
142
  t.integer "estimated_deploy_duration", default: 1, null: false
149
143
  t.datetime "continuous_delivery_delayed_since"
150
144
  t.datetime "locked_since"
145
+ t.index ["repo_owner", "repo_name", "environment"], name: "stack_unicity", unique: true
151
146
  end
152
147
 
153
- add_index "stacks", ["repo_owner", "repo_name", "environment"], name: "stack_unicity", unique: true
154
-
155
148
  create_table "statuses", force: :cascade do |t|
156
149
  t.string "state", limit: 255
157
150
  t.string "target_url", limit: 255
@@ -160,10 +153,10 @@ ActiveRecord::Schema.define(version: 20160822131405) do
160
153
  t.integer "commit_id", limit: 4
161
154
  t.datetime "created_at"
162
155
  t.datetime "updated_at"
156
+ t.integer "stack_id", null: false
157
+ t.index ["commit_id"], name: "index_statuses_on_commit_id"
163
158
  end
164
159
 
165
- add_index "statuses", ["commit_id"], name: "index_statuses_on_commit_id"
166
-
167
160
  create_table "tasks", force: :cascade do |t|
168
161
  t.integer "stack_id", limit: 4, null: false
169
162
  t.integer "since_commit_id", limit: 4, null: false
@@ -185,16 +178,15 @@ ActiveRecord::Schema.define(version: 20160822131405) do
185
178
  t.boolean "allow_concurrency", default: false, null: false
186
179
  t.datetime "started_at"
187
180
  t.datetime "ended_at"
181
+ t.index ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
182
+ t.index ["since_commit_id"], name: "index_tasks_on_since_commit_id"
183
+ t.index ["stack_id", "allow_concurrency", "status"], name: "index_active_tasks"
184
+ t.index ["type", "stack_id", "parent_id"], name: "index_tasks_by_stack_and_parent"
185
+ t.index ["type", "stack_id", "status"], name: "index_tasks_by_stack_and_status"
186
+ t.index ["until_commit_id"], name: "index_tasks_on_until_commit_id"
187
+ t.index ["user_id"], name: "index_tasks_on_user_id"
188
188
  end
189
189
 
190
- add_index "tasks", ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
191
- add_index "tasks", ["since_commit_id"], name: "index_tasks_on_since_commit_id"
192
- add_index "tasks", ["stack_id", "allow_concurrency", "status"], name: "index_active_tasks"
193
- add_index "tasks", ["type", "stack_id", "parent_id"], name: "index_tasks_by_stack_and_parent"
194
- add_index "tasks", ["type", "stack_id", "status"], name: "index_tasks_by_stack_and_status"
195
- add_index "tasks", ["until_commit_id"], name: "index_tasks_on_until_commit_id"
196
- add_index "tasks", ["user_id"], name: "index_tasks_on_user_id"
197
-
198
190
  create_table "teams", force: :cascade do |t|
199
191
  t.integer "github_id", limit: 4
200
192
  t.string "api_url", limit: 255
@@ -203,10 +195,9 @@ ActiveRecord::Schema.define(version: 20160822131405) do
203
195
  t.string "organization", limit: 39
204
196
  t.datetime "created_at", null: false
205
197
  t.datetime "updated_at", null: false
198
+ t.index ["organization", "slug"], name: "index_teams_on_organization_and_slug", unique: true
206
199
  end
207
200
 
208
- add_index "teams", ["organization", "slug"], name: "index_teams_on_organization_and_slug", unique: true
209
-
210
201
  create_table "users", force: :cascade do |t|
211
202
  t.integer "github_id", limit: 4
212
203
  t.string "name", limit: 255, null: false
@@ -218,8 +209,7 @@ ActiveRecord::Schema.define(version: 20160822131405) do
218
209
  t.string "avatar_url", limit: 255
219
210
  t.string "encrypted_github_access_token"
220
211
  t.string "encrypted_github_access_token_iv"
212
+ t.index ["login"], name: "index_users_on_login"
221
213
  end
222
214
 
223
- add_index "users", ["login"], name: "index_users_on_login"
224
-
225
215
  end