summaryrefslogtreecommitdiff
path: root/app/models/ci
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/ci')
-rw-r--r--app/models/ci/build.rb178
-rw-r--r--app/models/ci/commit.rb215
-rw-r--r--app/models/ci/pipeline.rb203
-rw-r--r--app/models/ci/runner.rb39
-rw-r--r--app/models/ci/runner_project.rb12
-rw-r--r--app/models/ci/trigger.rb13
-rw-r--r--app/models/ci/trigger_request.rb14
-rw-r--r--app/models/ci/variable.rb19
8 files changed, 333 insertions, 360 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 7d33838044b..d618c84e983 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1,44 +1,5 @@
-# == Schema Information
-#
-# Table name: ci_builds
-#
-# id :integer not null, primary key
-# project_id :integer
-# status :string(255)
-# finished_at :datetime
-# trace :text
-# created_at :datetime
-# updated_at :datetime
-# started_at :datetime
-# runner_id :integer
-# coverage :float
-# commit_id :integer
-# commands :text
-# job_id :integer
-# name :string(255)
-# deploy :boolean default(FALSE)
-# options :text
-# allow_failure :boolean default(FALSE), not null
-# stage :string(255)
-# trigger_request_id :integer
-# stage_idx :integer
-# tag :boolean
-# ref :string(255)
-# user_id :integer
-# type :string(255)
-# target_url :string(255)
-# description :string(255)
-# artifacts_file :text
-# gl_project_id :integer
-# artifacts_metadata :text
-# erased_by_id :integer
-# erased_at :datetime
-#
-
module Ci
class Build < CommitStatus
- LAZY_ATTRIBUTES = ['trace']
-
belongs_to :runner, class_name: 'Ci::Runner'
belongs_to :trigger_request, class_name: 'Ci::TriggerRequest'
belongs_to :erased_by, class_name: 'User'
@@ -50,25 +11,19 @@ module Ci
scope :unstarted, ->() { where(runner_id: nil) }
scope :ignore_failures, ->() { where(allow_failure: false) }
- scope :similar, ->(build) { where(ref: build.ref, tag: build.tag, trigger_request_id: build.trigger_request_id) }
+ scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
+ scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader
acts_as_taggable
- # To prevent db load megabytes of data from trace
- default_scope -> { select(Ci::Build.columns_without_lazy) }
-
before_destroy { project }
- class << self
- def columns_without_lazy
- (column_names - LAZY_ATTRIBUTES).map do |column_name|
- "#{table_name}.#{column_name}"
- end
- end
+ after_create :execute_hooks
+ class << self
def last_month
where('created_at > ?', Date.today - 1.month)
end
@@ -85,21 +40,23 @@ module Ci
new_build.save
end
- def retry(build)
+ def retry(build, user = nil)
new_build = Ci::Build.new(status: 'pending')
new_build.ref = build.ref
new_build.tag = build.tag
new_build.options = build.options
new_build.commands = build.commands
new_build.tag_list = build.tag_list
- new_build.gl_project_id = build.gl_project_id
- new_build.commit_id = build.commit_id
+ new_build.project = build.project
+ new_build.pipeline = build.pipeline
new_build.name = build.name
new_build.allow_failure = build.allow_failure
new_build.stage = build.stage
new_build.stage_idx = build.stage_idx
new_build.trigger_request = build.trigger_request
+ new_build.user = user
new_build.save
+ MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build)
new_build
end
end
@@ -112,13 +69,24 @@ module Ci
# We use around_transition to create builds for next stage as soon as possible, before the `after_*` is executed
around_transition any => [:success, :failed, :canceled] do |build, block|
block.call
- build.commit.create_next_builds(build) if build.commit
+ build.pipeline.create_next_builds(build) if build.pipeline
end
after_transition any => [:success, :failed, :canceled] do |build|
build.update_coverage
build.execute_hooks
end
+
+ after_transition any => [:success] do |build|
+ if build.environment.present?
+ service = CreateDeploymentService.new(build.project, build.user,
+ environment: build.environment,
+ sha: build.sha,
+ ref: build.ref,
+ tag: build.tag)
+ service.execute(build)
+ end
+ end
end
def retryable?
@@ -126,20 +94,24 @@ module Ci
end
def retried?
- !self.commit.latest_statuses_for_ref(self.ref).include?(self)
+ !self.pipeline.statuses.latest.include?(self)
end
def depends_on_builds
# Get builds of the same type
- latest_builds = self.commit.builds.similar(self).latest
+ latest_builds = self.pipeline.builds.latest
# Return builds from previous stages
latest_builds.where('stage_idx < ?', stage_idx)
end
def trace_html
- html = Ci::Ansi2html::convert(trace) if trace.present?
- html || ''
+ trace_with_state[:html] || ''
+ end
+
+ def trace_with_state(state = nil)
+ trace_with_state = Ci::Ansi2html::convert(trace, state) if trace.present?
+ trace_with_state || {}
end
def timeout
@@ -152,16 +124,16 @@ module Ci
def merge_request
merge_requests = MergeRequest.includes(:merge_request_diff)
- .where(source_branch: ref, source_project_id: commit.gl_project_id)
+ .where(source_branch: ref, source_project_id: pipeline.gl_project_id)
.reorder(iid: :asc)
merge_requests.find do |merge_request|
- merge_request.commits.any? { |ci| ci.id == commit.sha }
+ merge_request.commits.any? { |ci| ci.id == pipeline.sha }
end
end
def project_id
- commit.project.id
+ pipeline.project_id
end
def project_name
@@ -230,12 +202,33 @@ module Ci
end
end
+ def trace_length
+ if raw_trace
+ raw_trace.bytesize
+ else
+ 0
+ end
+ end
+
def trace=(trace)
- unless Dir.exists?(dir_to_trace)
+ recreate_trace_dir
+ File.write(path_to_trace, trace)
+ end
+
+ def recreate_trace_dir
+ unless Dir.exist?(dir_to_trace)
FileUtils.mkdir_p(dir_to_trace)
end
+ end
+ private :recreate_trace_dir
- File.write(path_to_trace, trace)
+ def append_trace(trace_part, offset)
+ recreate_trace_dir
+
+ File.truncate(path_to_trace, offset) if File.exist?(path_to_trace)
+ File.open(path_to_trace, 'ab') do |f|
+ f.write(trace_part)
+ end
end
def dir_to_trace
@@ -303,14 +296,20 @@ module Ci
project.runners_token
end
- def valid_token? token
+ def valid_token?(token)
project.valid_runners_token? token
end
def can_be_served?(runner)
+ return false unless has_tags? || runner.run_untagged?
+
(tag_list - runner.tag_list).empty?
end
+ def has_tags?
+ tag_list.any?
+ end
+
def any_runners_online?
project.any_runners? { |runner| runner.active? && runner.online? && can_be_served?(runner) }
end
@@ -324,10 +323,11 @@ module Ci
build_data = Gitlab::BuildDataBuilder.build(self)
project.execute_hooks(build_data.dup, :build_hooks)
project.execute_services(build_data.dup, :build_hooks)
+ project.running_or_pending_build_count(force: true)
end
def artifacts?
- artifacts_file.exists?
+ !artifacts_expired? && artifacts_file.exists?
end
def artifacts_metadata?
@@ -338,11 +338,16 @@ module Ci
Gitlab::Ci::Build::Artifacts::Metadata.new(artifacts_metadata.path, path, **options).to_entry
end
+ def erase_artifacts!
+ remove_artifacts_file!
+ remove_artifacts_metadata!
+ save
+ end
+
def erase(opts = {})
return false unless erasable?
- remove_artifacts_file!
- remove_artifacts_metadata!
+ erase_artifacts!
erase_trace!
update_erased!(opts[:erased_by])
end
@@ -355,6 +360,25 @@ module Ci
!self.erased_at.nil?
end
+ def artifacts_expired?
+ artifacts_expire_at && artifacts_expire_at < Time.now
+ end
+
+ def artifacts_expire_in
+ artifacts_expire_at - Time.now if artifacts_expire_at
+ end
+
+ def artifacts_expire_in=(value)
+ self.artifacts_expire_at =
+ if value
+ Time.now + ChronicDuration.parse(value)
+ end
+ end
+
+ def keep_artifacts!
+ self.update(artifacts_expire_at: nil)
+ end
+
private
def erase_trace!
@@ -362,14 +386,26 @@ module Ci
end
def update_erased!(user = nil)
- self.update(erased_by: user, erased_at: Time.now)
+ self.update(erased_by: user, erased_at: Time.now, artifacts_expire_at: nil)
end
- private
-
def yaml_variables
- if commit.config_processor
- commit.config_processor.variables.map do |key, value|
+ global_yaml_variables + job_yaml_variables
+ end
+
+ def global_yaml_variables
+ if pipeline.config_processor
+ pipeline.config_processor.global_variables.map do |key, value|
+ { key: key, value: value, public: true }
+ end
+ else
+ []
+ end
+ end
+
+ def job_yaml_variables
+ if pipeline.config_processor
+ pipeline.config_processor.job_variables(name).map do |key, value|
{ key: key, value: value, public: true }
end
else
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
deleted file mode 100644
index f4cf7034b14..00000000000
--- a/app/models/ci/commit.rb
+++ /dev/null
@@ -1,215 +0,0 @@
-# == Schema Information
-#
-# Table name: ci_commits
-#
-# id :integer not null, primary key
-# project_id :integer
-# ref :string(255)
-# sha :string(255)
-# before_sha :string(255)
-# push_data :text
-# created_at :datetime
-# updated_at :datetime
-# tag :boolean default(FALSE)
-# yaml_errors :text
-# committed_at :datetime
-# gl_project_id :integer
-#
-
-module Ci
- class Commit < ActiveRecord::Base
- extend Ci::Model
-
- belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
- has_many :statuses, class_name: 'CommitStatus'
- has_many :builds, class_name: 'Ci::Build'
- has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest'
-
- validates_presence_of :sha
- validate :valid_commit_sha
-
- def self.truncate_sha(sha)
- sha[0...8]
- end
-
- def to_param
- sha
- end
-
- def project_id
- project.id
- end
-
- def valid_commit_sha
- if self.sha == Gitlab::Git::BLANK_SHA
- self.errors.add(:sha, " cant be 00000000 (branch removal)")
- end
- end
-
- def git_author_name
- commit_data.author_name if commit_data
- end
-
- def git_author_email
- commit_data.author_email if commit_data
- end
-
- def git_commit_message
- commit_data.message if commit_data
- end
-
- def short_sha
- Ci::Commit.truncate_sha(sha)
- end
-
- def commit_data
- @commit ||= project.commit(sha)
- rescue
- nil
- end
-
- def stage
- running_or_pending = statuses.latest.running_or_pending.ordered
- running_or_pending.first.try(:stage)
- end
-
- def create_builds(ref, tag, user, trigger_request = nil)
- return unless config_processor
- config_processor.stages.any? do |stage|
- CreateBuildsService.new.execute(self, stage, ref, tag, user, trigger_request, 'success').present?
- end
- end
-
- def create_next_builds(build)
- return unless config_processor
-
- # don't create other builds if this one is retried
- latest_builds = builds.similar(build).latest
- return unless latest_builds.exists?(build.id)
-
- # get list of stages after this build
- next_stages = config_processor.stages.drop_while { |stage| stage != build.stage }
- next_stages.delete(build.stage)
-
- # get status for all prior builds
- prior_builds = latest_builds.reject { |other_build| next_stages.include?(other_build.stage) }
- status = Ci::Status.get_status(prior_builds)
-
- # create builds for next stages based
- next_stages.any? do |stage|
- CreateBuildsService.new.execute(self, stage, build.ref, build.tag, build.user, build.trigger_request, status).present?
- end
- end
-
- def refs
- statuses.order(:ref).pluck(:ref).uniq
- end
-
- def latest_statuses
- @latest_statuses ||= statuses.latest.to_a
- end
-
- def latest_statuses_for_ref(ref)
- latest_statuses.select { |status| status.ref == ref }
- end
-
- def matrix_builds(build = nil)
- matrix_builds = builds.latest.ordered
- matrix_builds = matrix_builds.similar(build) if build
- matrix_builds.to_a
- end
-
- def retried
- @retried ||= (statuses.order(id: :desc) - statuses.latest)
- end
-
- def status
- if yaml_errors.present?
- return 'failed'
- end
-
- @status ||= Ci::Status.get_status(latest_statuses)
- end
-
- def pending?
- status == 'pending'
- end
-
- def running?
- status == 'running'
- end
-
- def success?
- status == 'success'
- end
-
- def failed?
- status == 'failed'
- end
-
- def canceled?
- status == 'canceled'
- end
-
- def active?
- running? || pending?
- end
-
- def complete?
- canceled? || success? || failed?
- end
-
- def duration
- duration_array = statuses.map(&:duration).compact
- duration_array.reduce(:+).to_i
- end
-
- def started_at
- @started_at ||= statuses.order('started_at ASC').first.try(:started_at)
- end
-
- def finished_at
- @finished_at ||= statuses.order('finished_at DESC').first.try(:finished_at)
- end
-
- def coverage
- coverage_array = latest_statuses.map(&:coverage).compact
- if coverage_array.size >= 1
- '%.2f' % (coverage_array.reduce(:+) / coverage_array.size)
- end
- end
-
- def config_processor
- return nil unless ci_yaml_file
- @config_processor ||= Ci::GitlabCiYamlProcessor.new(ci_yaml_file, project.path_with_namespace)
- rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e
- save_yaml_error(e.message)
- nil
- rescue
- save_yaml_error("Undefined error")
- nil
- end
-
- def ci_yaml_file
- @ci_yaml_file ||= begin
- blob = project.repository.blob_at(sha, '.gitlab-ci.yml')
- blob.load_all_data!(project.repository)
- blob.data
- end
- rescue
- nil
- end
-
- def skip_ci?
- git_commit_message =~ /(\[ci skip\])/ if git_commit_message
- end
-
- private
-
- def save_yaml_error(error)
- return if self.yaml_errors?
- self.yaml_errors = error
- save
- end
- end
-end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
new file mode 100644
index 00000000000..5b264ecffc5
--- /dev/null
+++ b/app/models/ci/pipeline.rb
@@ -0,0 +1,203 @@
+module Ci
+ class Pipeline < ActiveRecord::Base
+ extend Ci::Model
+ include Statuseable
+
+ self.table_name = 'ci_commits'
+
+ belongs_to :project, class_name: '::Project', foreign_key: :gl_project_id
+ has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
+ has_many :builds, class_name: 'Ci::Build', foreign_key: :commit_id
+ has_many :trigger_requests, dependent: :destroy, class_name: 'Ci::TriggerRequest', foreign_key: :commit_id
+
+ validates_presence_of :sha
+ validates_presence_of :status
+ validate :valid_commit_sha
+
+ # Invalidate object and save if when touched
+ after_touch :update_state
+
+ def self.truncate_sha(sha)
+ sha[0...8]
+ end
+
+ def self.stages
+ # We use pluck here due to problems with MySQL which doesn't allow LIMIT/OFFSET in queries
+ CommitStatus.where(pipeline: pluck(:id)).stages
+ end
+
+ def project_id
+ project.id
+ end
+
+ def valid_commit_sha
+ if self.sha == Gitlab::Git::BLANK_SHA
+ self.errors.add(:sha, " cant be 00000000 (branch removal)")
+ end
+ end
+
+ def git_author_name
+ commit_data.author_name if commit_data
+ end
+
+ def git_author_email
+ commit_data.author_email if commit_data
+ end
+
+ def git_commit_message
+ commit_data.message if commit_data
+ end
+
+ def short_sha
+ Ci::Pipeline.truncate_sha(sha)
+ end
+
+ def commit_data
+ @commit ||= project.commit(sha)
+ rescue
+ nil
+ end
+
+ def branch?
+ !tag?
+ end
+
+ def retryable?
+ builds.latest.any? do |build|
+ build.failed? && build.retryable?
+ end
+ end
+
+ def cancelable?
+ builds.running_or_pending.any?
+ end
+
+ def cancel_running
+ builds.running_or_pending.each(&:cancel)
+ end
+
+ def retry_failed(user)
+ builds.latest.failed.select(&:retryable?).each do |build|
+ Ci::Build.retry(build, user)
+ end
+ end
+
+ def latest?
+ return false unless ref
+ commit = project.commit(ref)
+ return false unless commit
+ commit.sha == sha
+ end
+
+ def triggered?
+ trigger_requests.any?
+ end
+
+ def create_builds(user, trigger_request = nil)
+ ##
+ # We persist pipeline only if there are builds available
+ #
+ return unless config_processor
+
+ build_builds_for_stages(config_processor.stages, user,
+ 'success', trigger_request) && save
+ end
+
+ def create_next_builds(build)
+ return unless config_processor
+
+ # don't create other builds if this one is retried
+ latest_builds = builds.latest
+ return unless latest_builds.exists?(build.id)
+
+ # get list of stages after this build
+ next_stages = config_processor.stages.drop_while { |stage| stage != build.stage }
+ next_stages.delete(build.stage)
+
+ # get status for all prior builds
+ prior_builds = latest_builds.where.not(stage: next_stages)
+ prior_status = prior_builds.status
+
+ # build builds for next stage that has builds available
+ # and save pipeline if we have builds
+ build_builds_for_stages(next_stages, build.user, prior_status,
+ build.trigger_request) && save
+ end
+
+ def retried
+ @retried ||= (statuses.order(id: :desc) - statuses.latest)
+ end
+
+ def coverage
+ coverage_array = statuses.latest.map(&:coverage).compact
+ if coverage_array.size >= 1
+ '%.2f' % (coverage_array.reduce(:+) / coverage_array.size)
+ end
+ end
+
+ def config_processor
+ return nil unless ci_yaml_file
+ return @config_processor if defined?(@config_processor)
+
+ @config_processor ||= begin
+ Ci::GitlabCiYamlProcessor.new(ci_yaml_file, project.path_with_namespace)
+ rescue Ci::GitlabCiYamlProcessor::ValidationError, Psych::SyntaxError => e
+ self.yaml_errors = e.message
+ nil
+ rescue
+ self.yaml_errors = 'Undefined error'
+ nil
+ end
+ end
+
+ def ci_yaml_file
+ return @ci_yaml_file if defined?(@ci_yaml_file)
+
+ @ci_yaml_file ||= begin
+ blob = project.repository.blob_at(sha, '.gitlab-ci.yml')
+ blob.load_all_data!(project.repository)
+ blob.data
+ rescue
+ nil
+ end
+ end
+
+ def skip_ci?
+ git_commit_message =~ /(\[ci skip\])/ if git_commit_message
+ end
+
+ def environments
+ builds.where.not(environment: nil).success.pluck(:environment).uniq
+ end
+
+ def notes
+ Note.for_commit_id(sha)
+ end
+
+ private
+
+ def build_builds_for_stages(stages, user, status, trigger_request)
+ ##
+ # Note that `Array#any?` implements a short circuit evaluation, so we
+ # build builds only for the first stage that has builds available.
+ #
+ stages.any? do |stage|
+ CreateBuildsService.new(self)
+ .execute(stage, user, status, trigger_request).present?
+ end
+ end
+
+ def update_state
+ statuses.reload
+ self.status = if yaml_errors.blank?
+ statuses.latest.status || 'skipped'
+ else
+ 'failed'
+ end
+ self.started_at = statuses.started_at
+ self.finished_at = statuses.finished_at
+ self.duration = statuses.latest.duration
+ save
+ end
+ end
+end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 90349a07594..adb65292208 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -1,28 +1,10 @@
-# == Schema Information
-#
-# Table name: ci_runners
-#
-# id :integer not null, primary key
-# token :string(255)
-# created_at :datetime
-# updated_at :datetime
-# description :string(255)
-# contacted_at :datetime
-# active :boolean default(TRUE), not null
-# is_shared :boolean default(FALSE)
-# name :string(255)
-# version :string(255)
-# revision :string(255)
-# platform :string(255)
-# architecture :string(255)
-#
-
module Ci
class Runner < ActiveRecord::Base
extend Ci::Model
LAST_CONTACT_TIME = 5.minutes.ago
- AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online']
+ AVAILABLE_SCOPES = %w[specific shared active paused online]
+ FORM_EDITABLE = %i[description tag_list active run_untagged]
has_many :builds, class_name: 'Ci::Build'
has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
@@ -44,6 +26,8 @@ module Ci
.where("ci_runner_projects.gl_project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id)
end
+ validate :tag_constraints
+
acts_as_taggable
# Searches for runners matching the given query.
@@ -76,7 +60,7 @@ module Ci
end
def display_name
- return short_sha unless !description.blank?
+ return short_sha if description.blank?
description
end
@@ -114,5 +98,18 @@ module Ci
def short_sha
token[0...8] if token
end
+
+ def has_tags?
+ tag_list.any?
+ end
+
+ private
+
+ def tag_constraints
+ unless has_tags? || run_untagged?
+ errors.add(:tags_list,
+ 'can not be empty when runner is not allowed to pick untagged jobs')
+ end
+ end
end
end
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 7b16f207a26..4b44ffa886e 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -1,15 +1,3 @@
-# == Schema Information
-#
-# Table name: ci_runner_projects
-#
-# id :integer not null, primary key
-# runner_id :integer not null
-# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# gl_project_id :integer
-#
-
module Ci
class RunnerProject < ActiveRecord::Base
extend Ci::Model
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index 2b9a457c8ab..a0b19b51a12 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -1,16 +1,3 @@
-# == Schema Information
-#
-# Table name: ci_triggers
-#
-# id :integer not null, primary key
-# token :string(255)
-# project_id :integer
-# deleted_at :datetime
-# created_at :datetime
-# updated_at :datetime
-# gl_project_id :integer
-#
-
module Ci
class Trigger < ActiveRecord::Base
extend Ci::Model
diff --git a/app/models/ci/trigger_request.rb b/app/models/ci/trigger_request.rb
index 9973d2e5ade..b69ae37668c 100644
--- a/app/models/ci/trigger_request.rb
+++ b/app/models/ci/trigger_request.rb
@@ -1,21 +1,9 @@
-# == Schema Information
-#
-# Table name: ci_trigger_requests
-#
-# id :integer not null, primary key
-# trigger_id :integer not null
-# variables :text
-# created_at :datetime
-# updated_at :datetime
-# commit_id :integer
-#
-
module Ci
class TriggerRequest < ActiveRecord::Base
extend Ci::Model
belongs_to :trigger, class_name: 'Ci::Trigger'
- belongs_to :commit, class_name: 'Ci::Commit'
+ belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
has_many :builds, class_name: 'Ci::Build'
serialize :variables
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index e786bd7dd93..f8d5d4486fd 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -1,17 +1,3 @@
-# == Schema Information
-#
-# Table name: ci_variables
-#
-# id :integer not null, primary key
-# project_id :integer
-# key :string(255)
-# value :text
-# encrypted_value :text
-# encrypted_value_salt :string(255)
-# encrypted_value_iv :string(255)
-# gl_project_id :integer
-#
-
module Ci
class Variable < ActiveRecord::Base
extend Ci::Model
@@ -25,6 +11,9 @@ module Ci
format: { with: /\A[a-zA-Z0-9_]+\z/,
message: "can contain only letters, digits and '_'." }
- attr_encrypted :value, mode: :per_attribute_iv_and_salt, key: Gitlab::Application.secrets.db_key_base
+ attr_encrypted :value,
+ mode: :per_attribute_iv_and_salt,
+ key: Gitlab::Application.secrets.db_key_base,
+ algorithm: 'aes-256-cbc'
end
end