diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2018-11-29 12:19:28 +0100 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2019-01-23 15:10:37 +0100 |
commit | 25dbc85f69db43957610813dfe8360ff16b5a591 (patch) | |
tree | 7c87ea69d5ce47b8bc42c1fb62bd3845a84beeb3 | |
parent | c243b154abf5c29ba35fd2fab2ca3bc010fdc324 (diff) | |
download | gitlab-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.rb | 13 | ||||
-rw-r--r-- | app/models/concerns/deployable.rb | 4 | ||||
-rw-r--r-- | app/models/deployment.rb | 14 | ||||
-rw-r--r-- | changelogs/unreleased/environment-rollout.yml | 5 | ||||
-rw-r--r-- | db/fixtures/development/19_environments.rb | 4 | ||||
-rw-r--r-- | db/migrate/20180906083218_add_rollout_to_deployment.rb | 20 | ||||
-rw-r--r-- | db/migrate/20181120102849_add_track_to_deployment.rb | 20 | ||||
-rw-r--r-- | db/post_migrate/20181120103003_change_default_of_track_deployment.rb | 15 | ||||
-rw-r--r-- | db/schema.rb | 2 | ||||
-rw-r--r-- | doc/ci/variables/README.md | 3 | ||||
-rw-r--r-- | doc/ci/yaml/README.md | 31 | ||||
-rw-r--r-- | lib/gitlab/ci/config/entry/environment.rb | 17 | ||||
-rw-r--r-- | spec/factories/deployments.rb | 1 | ||||
-rw-r--r-- | spec/lib/gitlab/ci/config/entry/environment_spec.rb | 24 |
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 |