summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2018-11-29 12:19:28 +0100
committerKamil Trzciński <ayufan@ayufan.eu>2019-01-23 15:10:37 +0100
commit25dbc85f69db43957610813dfe8360ff16b5a591 (patch)
tree7c87ea69d5ce47b8bc42c1fb62bd3845a84beeb3
parentc243b154abf5c29ba35fd2fab2ca3bc010fdc324 (diff)
downloadgitlab-ce-environment-rollout.tar.gz
Add deployment track/rolloutenvironment-rollout
This extends .gitlab-ci.yml with: ``` rollout 10%: environment: name: production rollout: 10 ```
-rw-r--r--app/models/ci/build.rb13
-rw-r--r--app/models/concerns/deployable.rb4
-rw-r--r--app/models/deployment.rb14
-rw-r--r--changelogs/unreleased/environment-rollout.yml5
-rw-r--r--db/fixtures/development/19_environments.rb4
-rw-r--r--db/migrate/20180906083218_add_rollout_to_deployment.rb20
-rw-r--r--db/migrate/20181120102849_add_track_to_deployment.rb20
-rw-r--r--db/post_migrate/20181120103003_change_default_of_track_deployment.rb15
-rw-r--r--db/schema.rb2
-rw-r--r--doc/ci/variables/README.md3
-rw-r--r--doc/ci/yaml/README.md31
-rw-r--r--lib/gitlab/ci/config/entry/environment.rb17
-rw-r--r--spec/factories/deployments.rb1
-rw-r--r--spec/lib/gitlab/ci/config/entry/environment_spec.rb24
14 files changed, 169 insertions, 4 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index cfdb3c0d719..524ca33b0c5 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -377,7 +377,15 @@ module Ci
end
def environment_action
- self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options
+ self.options.dig(:environment, :action) || 'start'
+ end
+
+ def environment_track
+ self.options.dig(:environment, :track) || 'stable'
+ end
+
+ def environment_rollout
+ self.options.dig(:environment, :rollout) || 100
end
def has_deployment?
@@ -881,6 +889,9 @@ module Ci
variables.append(key: "CI_JOB_MANUAL", value: 'true') if action?
variables.append(key: "CI_NODE_INDEX", value: self.options[:instance].to_s) if self.options&.include?(:instance)
variables.append(key: "CI_NODE_TOTAL", value: (self.options&.dig(:parallel) || 1).to_s)
+ variables.append(key: "CI_ENVIRONMENT_TRACK", value: self.environment_track) if self.environment_track
+ variables.append(key: "CI_ENVIRONMENT_ROLLOUT", value: self.environment_rollout.to_s) if self.environment_rollout
+ variables.append(key: "CI_ENVIRONMENT_ACTION", value: self.environment_action) if self.environment_action
variables.concat(legacy_variables)
end
end
diff --git a/app/models/concerns/deployable.rb b/app/models/concerns/deployable.rb
index bc12b06b5af..bbbf6f36829 100644
--- a/app/models/concerns/deployable.rb
+++ b/app/models/concerns/deployable.rb
@@ -24,7 +24,9 @@ module Deployable
tag: tag,
sha: sha,
user: user,
- on_stop: on_stop)
+ on_stop: on_stop,
+ track: environment_track,
+ rollout: environment_rollout)
end
end
end
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 811e623b7f7..9e46b3938cf 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -16,6 +16,11 @@ class Deployment < ActiveRecord::Base
validates :sha, presence: true
validates :ref, presence: true
+ validates :track, presence: true
+ validates :rollout, presence: true, if: :rollout?,
+ numericality: { greater_than: 0, less_than: 100 }
+ validates :rollout, presence: true, unless: :rollout?,
+ numericality: { equal_to: 100 }
delegate :name, to: :environment, prefix: true
@@ -66,6 +71,15 @@ class Deployment < ActiveRecord::Base
find(ids)
end
+ enum track: {
+ stable: 0,
+ rollout: 1
+ }
+
+ def incremental_rollout?
+ rollout? && rollout.to_i < 100
+ end
+
def commit
project.commit(sha)
end
diff --git a/changelogs/unreleased/environment-rollout.yml b/changelogs/unreleased/environment-rollout.yml
new file mode 100644
index 00000000000..ea37bab1b05
--- /dev/null
+++ b/changelogs/unreleased/environment-rollout.yml
@@ -0,0 +1,5 @@
+---
+title: Make incremental rollout to be first-class thing in GitLab
+merge_request: 21554
+author:
+type: added
diff --git a/db/fixtures/development/19_environments.rb b/db/fixtures/development/19_environments.rb
index 3e227928a29..9743fa6d9ee 100644
--- a/db/fixtures/development/19_environments.rb
+++ b/db/fixtures/development/19_environments.rb
@@ -51,7 +51,9 @@ class Gitlab::Seeder::Environments
ref: ref,
sha: sha,
tag: false,
- deployable: find_deployable(project, name)
+ deployable: find_deployable(project, name),
+ track: 'stable',
+ rollout: 100
)
end
diff --git a/db/migrate/20180906083218_add_rollout_to_deployment.rb b/db/migrate/20180906083218_add_rollout_to_deployment.rb
new file mode 100644
index 00000000000..a22fd8c5cd9
--- /dev/null
+++ b/db/migrate/20180906083218_add_rollout_to_deployment.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddRolloutToDeployment < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ ROLLOUT_PERCENTAGE = 100
+
+ def up
+ add_column_with_default(:deployments, :rollout, :integer,
+ limit: 2, default: ROLLOUT_PERCENTAGE)
+ end
+
+ def down
+ remove_column(:deployments, :rollout)
+ end
+end
diff --git a/db/migrate/20181120102849_add_track_to_deployment.rb b/db/migrate/20181120102849_add_track_to_deployment.rb
new file mode 100644
index 00000000000..e62c5d16511
--- /dev/null
+++ b/db/migrate/20181120102849_add_track_to_deployment.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddTrackToDeployment < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ STABLE_TRACK = 0
+
+ def up
+ add_column_with_default(:deployments, :track, :integer,
+ limit: 2, default: STABLE_TRACK)
+ end
+
+ def down
+ remove_column(:deployments, :track)
+ end
+end
diff --git a/db/post_migrate/20181120103003_change_default_of_track_deployment.rb b/db/post_migrate/20181120103003_change_default_of_track_deployment.rb
new file mode 100644
index 00000000000..d6846dcadd2
--- /dev/null
+++ b/db/post_migrate/20181120103003_change_default_of_track_deployment.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class ChangeDefaultOfTrackDeployment < ActiveRecord::Migration
+ DOWNTIME = false
+
+ STABLE_TRACK = 0
+
+ def up
+ change_column_default(:deployments, :track, nil)
+ end
+
+ def down
+ change_column_default(:deployments, :track, STABLE_TRACK)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index cd502d06bf4..0eaf80565eb 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -833,6 +833,8 @@ ActiveRecord::Schema.define(version: 20190115054216) do
t.string "on_stop"
t.integer "status", limit: 2, null: false
t.datetime_with_timezone "finished_at"
+ t.integer "rollout", limit: 2, default: 100, null: false
+ t.integer "track", limit: 2, null: false
t.index ["created_at"], name: "index_deployments_on_created_at", using: :btree
t.index ["deployable_type", "deployable_id"], name: "index_deployments_on_deployable_type_and_deployable_id", using: :btree
t.index ["environment_id", "id"], name: "index_deployments_on_environment_id_and_id", using: :btree
diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md
index 25d189afb24..8abf3b0ba04 100644
--- a/doc/ci/variables/README.md
+++ b/doc/ci/variables/README.md
@@ -61,6 +61,9 @@ future GitLab releases.**
| **CI_ENVIRONMENT_NAME** | 8.15 | all | The name of the environment for this job |
| **CI_ENVIRONMENT_SLUG** | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. |
| **CI_ENVIRONMENT_URL** | 9.3 | all | The URL of the environment for this job |
+| **CI_ENVIRONMENT_TRACK** | 11.6 | all | The environment deployment track, default `stable` |
+| **CI_ENVIRONMENT_ROLLOUT** | 11.6 | all | The environment deployment rollout percentage, when track==rollout |
+| **CI_ENVIRONMENT_ACTION** | 11.6 | all | The environment deployment action: `start` or `stop` |
| **CI_JOB_ID** | 9.0 | all | The unique id of the current job that GitLab CI uses internally |
| **CI_JOB_MANUAL** | 8.12 | all | The flag to indicate that job was manually started |
| **CI_JOB_NAME** | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` |
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index fb69d888b94..5192a8502ac 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -787,6 +787,36 @@ The `stop_review_app` job is **required** to have the following keywords defined
- `stage` should be the same as the `review_app` in order for the environment
to stop automatically when the branch is deleted
+### `environment:rollout`
+
+> [Introduced][ce-21554] in GitLab 11.7.
+
+The `rollout` keyword defines the rollout deployment percentage.
+The `rollout` accepts values between 1 and 99 (%).
+
+For values between 1 and 99 the `CI_ENVIRONMENT_TRACK=rollout` track is being deployed.
+The value of `rollout` is passed as `CI_ENVIRONMENT_ROLLOUT` variable to CI job.
+
+Otherwise, when the `rollout:` is not defined the `CI_ENVIRONMENT_TRACK=stable`
+is being deployed with `CI_ENVIRONMENT_ROLLOUT=100` set.
+
+```
+rollout 10%:
+ stage: incremental-deploy
+ script: echo "Rolling out $CI_ENVIRONMENT_TRACK / $CI_ENVIRONMENT_ROLLOUT ..."
+ environment:
+ name: production
+ rollout: 10
+
+rollout 100%:
+ stage: deploy
+ script: echo "Rolling out $CI_ENVIRONMENT_TRACK / $CI_ENVIRONMENT_ROLLOUT ..."
+ environment:
+ name: production
+ rollout: 100
+```
+
+
### Dynamic environments
> **Notes:**
@@ -2351,6 +2381,7 @@ GitLab CI/CD with various languages.
[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
[ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447
[ce-12909]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/12909
+[ce-21554]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/21554
[environment]: ../environments.md "CI/CD environments"
[schedules]: ../../user/project/pipelines/schedules.md "Pipelines schedules"
[variables]: ../variables/README.md "CI/CD variables"
diff --git a/lib/gitlab/ci/config/entry/environment.rb b/lib/gitlab/ci/config/entry/environment.rb
index 69a3a1aedef..da4cdffb3a0 100644
--- a/lib/gitlab/ci/config/entry/environment.rb
+++ b/lib/gitlab/ci/config/entry/environment.rb
@@ -10,7 +10,7 @@ module Gitlab
class Environment < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
- ALLOWED_KEYS = %i[name url action on_stop].freeze
+ ALLOWED_KEYS = %i[name rollout url action on_stop].freeze
validations do
validate do
@@ -44,6 +44,13 @@ module Gitlab
allow_nil: true
validates :on_stop, type: String, allow_nil: true
+
+ validates :rollout,
+ presence: true,
+ numericality: { only_integer: true,
+ greater_than: 0,
+ less_than_or_equal_to: 100 },
+ allow_nil: true
end
end
@@ -63,6 +70,14 @@ module Gitlab
value[:url]
end
+ def track
+ rollout < 100 ? 'rollout' : 'stable'
+ end
+
+ def rollout
+ value[:rollout].to_i.nonzero? || 100
+ end
+
def action
value[:action] || 'start'
end
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index 011c98599a3..f4ba5b08e40 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -7,6 +7,7 @@ FactoryBot.define do
project nil
deployable factory: :ci_build
environment factory: :environment
+ track { Deployment.tracks[:stable] }
after(:build) do |deployment, evaluator|
deployment.project ||= deployment.environment.project
diff --git a/spec/lib/gitlab/ci/config/entry/environment_spec.rb b/spec/lib/gitlab/ci/config/entry/environment_spec.rb
index 3c0007f4d57..b8435e4d680 100644
--- a/spec/lib/gitlab/ci/config/entry/environment_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/environment_spec.rb
@@ -87,6 +87,30 @@ describe Gitlab::Ci::Config::Entry::Environment do
expect(entry.url).to eq 'https://example.gitlab.com'
end
end
+
+ describe '#rollout' do
+ context 'when rollout is defined' do
+ before do
+ config.merge!(rollout: 50)
+ end
+
+ it { expect(entry.rollout).to eq(50) }
+ it { expect(entry.track).to eq('rollout') }
+ end
+
+ context 'when rollout is 100%' do
+ before do
+ config.merge!(rollout: 100)
+ end
+
+ it { expect(entry.track).to eq('stable') }
+ end
+
+ context 'when rollout is not defined' do
+ it { expect(entry.rollout).to eq(100) }
+ it { expect(entry.track).to eq('stable') }
+ end
+ end
end
context 'when valid action is used' do