Merge branch '27762-add-default-artifacts-expiration' into 'master'
Artifact Expiration Defaults Closes #27762 See merge request !9219
This commit is contained in:
commit
e055f5cd4b
18 changed files with 178 additions and 16 deletions
|
@ -83,6 +83,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
|
|||
:akismet_api_key,
|
||||
:akismet_enabled,
|
||||
:container_registry_token_expire_delay,
|
||||
:default_artifacts_expire_in,
|
||||
:default_branch_protection,
|
||||
:default_group_visibility,
|
||||
:default_project_visibility,
|
||||
|
|
|
@ -76,6 +76,12 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
presence: true,
|
||||
numericality: { only_integer: true, greater_than: 0 }
|
||||
|
||||
validates :max_artifacts_size,
|
||||
presence: true,
|
||||
numericality: { only_integer: true, greater_than: 0 }
|
||||
|
||||
validates :default_artifacts_expire_in, presence: true, duration: true
|
||||
|
||||
validates :container_registry_token_expire_delay,
|
||||
presence: true,
|
||||
numericality: { only_integer: true, greater_than: 0 }
|
||||
|
@ -168,6 +174,7 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
after_sign_up_text: nil,
|
||||
akismet_enabled: false,
|
||||
container_registry_token_expire_delay: 5,
|
||||
default_artifacts_expire_in: '30 days',
|
||||
default_branch_protection: Settings.gitlab['default_branch_protection'],
|
||||
default_project_visibility: Settings.gitlab.default_projects_features['visibility_level'],
|
||||
default_projects_limit: Settings.gitlab['default_projects_limit'],
|
||||
|
@ -201,9 +208,9 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
sign_in_text: nil,
|
||||
signin_enabled: Settings.gitlab['signin_enabled'],
|
||||
signup_enabled: Settings.gitlab['signup_enabled'],
|
||||
terminal_max_session_time: 0,
|
||||
two_factor_grace_period: 48,
|
||||
user_default_external: false,
|
||||
terminal_max_session_time: 0
|
||||
user_default_external: false
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -215,6 +222,14 @@ class ApplicationSetting < ActiveRecord::Base
|
|||
create(defaults)
|
||||
end
|
||||
|
||||
def self.human_attribute_name(attr, _options = {})
|
||||
if attr == :default_artifacts_expire_in
|
||||
'Default artifacts expiration'
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def home_page_url_column_exist
|
||||
ActiveRecord::Base.connection.column_exists?(:application_settings, :home_page_url)
|
||||
end
|
||||
|
|
|
@ -484,7 +484,7 @@ module Ci
|
|||
def artifacts_expire_in=(value)
|
||||
self.artifacts_expire_at =
|
||||
if value
|
||||
Time.now + ChronicDuration.parse(value)
|
||||
ChronicDuration.parse(value)&.seconds&.from_now
|
||||
end
|
||||
end
|
||||
|
||||
|
|
17
app/validators/duration_validator.rb
Normal file
17
app/validators/duration_validator.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
# DurationValidator
|
||||
#
|
||||
# Validate the format conforms with ChronicDuration
|
||||
#
|
||||
# Example:
|
||||
#
|
||||
# class ApplicationSetting < ActiveRecord::Base
|
||||
# validates :default_artifacts_expire_in, presence: true, duration: true
|
||||
# end
|
||||
#
|
||||
class DurationValidator < ActiveModel::EachValidator
|
||||
def validate_each(record, attribute, value)
|
||||
ChronicDuration.parse(value)
|
||||
rescue ChronicDuration::DurationParseError
|
||||
record.errors.add(attribute, "is not a correct duration")
|
||||
end
|
||||
end
|
|
@ -212,8 +212,16 @@
|
|||
.col-sm-10
|
||||
= f.number_field :max_artifacts_size, class: 'form-control'
|
||||
.help-block
|
||||
Set the maximum file size each jobs's artifacts can have
|
||||
= link_to "(?)", help_page_path("user/admin_area/settings/continuous_integration", anchor: "maximum-artifacts-size")
|
||||
Set the maximum file size for each job's artifacts
|
||||
= link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'maximum-artifacts-size')
|
||||
.form-group
|
||||
= f.label :default_artifacts_expire_in, 'Default artifacts expiration', class: 'control-label col-sm-2'
|
||||
.col-sm-10
|
||||
= f.text_field :default_artifacts_expire_in, class: 'form-control'
|
||||
.help-block
|
||||
Set the default expiration time for each job's artifacts.
|
||||
0 for unlimited.
|
||||
= link_to icon('question-circle'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'default-artifacts-expiration')
|
||||
|
||||
- if Gitlab.config.registry.enabled
|
||||
%fieldset
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add admin setting for default artifacts expiration
|
||||
merge_request: 9219
|
||||
author:
|
|
@ -0,0 +1,11 @@
|
|||
class AddDefaultArtifactsExpirationToApplicationSettings < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def change
|
||||
add_column :application_settings,
|
||||
:default_artifacts_expire_in, :string,
|
||||
null: false, default: '0'
|
||||
end
|
||||
end
|
|
@ -111,6 +111,7 @@ ActiveRecord::Schema.define(version: 20170216141440) do
|
|||
t.boolean "plantuml_enabled"
|
||||
t.integer "max_pages_size", default: 100, null: false
|
||||
t.integer "terminal_max_session_time", default: 0, null: false
|
||||
t.string "default_artifacts_expire_in", default: '0', null: false
|
||||
end
|
||||
|
||||
create_table "audit_events", force: :cascade do |t|
|
||||
|
|
|
@ -3,18 +3,38 @@
|
|||
## Maximum artifacts size
|
||||
|
||||
The maximum size of the [job artifacts][art-yml] can be set in the Admin area
|
||||
of your GitLab instance. The value is in MB and the default is 100MB. Note that
|
||||
this setting is set for each job.
|
||||
of your GitLab instance. The value is in *MB* and the default is 100MB. Note
|
||||
that this setting is set for each job.
|
||||
|
||||
1. Go to **Admin area > Settings** (`/admin/application_settings`).
|
||||
|
||||
![Admin area settings button](img/admin_area_settings_button.png)
|
||||
|
||||
1. Change the value of the maximum artifacts size (in MB):
|
||||
1. Change the value of maximum artifacts size (in MB):
|
||||
|
||||
![Admin area maximum artifacts size](img/admin_area_maximum_artifacts_size.png)
|
||||
|
||||
1. Hit **Save** for the changes to take effect.
|
||||
|
||||
[art-yml]: ../../../administration/build_artifacts
|
||||
|
||||
[art-yml]: ../../../administration/job_artifacts.md
|
||||
## Default artifacts expiration
|
||||
|
||||
The default expiration time of the [job artifacts][art-yml] can be set in
|
||||
the Admin area of your GitLab instance. The syntax of duration is described
|
||||
in [artifacts:expire_in][duration-syntax]. The default is `30 days`. Note that
|
||||
this setting is set for each job. Set it to 0 if you don't want default
|
||||
expiration.
|
||||
|
||||
1. Go to **Admin area > Settings** (`/admin/application_settings`).
|
||||
|
||||
![Admin area settings button](img/admin_area_settings_button.png)
|
||||
|
||||
1. Change the value of default expiration time ([syntax][duration-syntax]):
|
||||
|
||||
![Admin area default artifacts expiration](img/admin_area_default_artifacts_expiration.png)
|
||||
|
||||
1. Hit **Save** for the changes to take effect.
|
||||
|
||||
[art-yml]: ../../../administration/job_artifacts
|
||||
[duration-syntax]: ../../../ci/yaml/README#artifactsexpire_in
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 13 KiB |
|
@ -557,6 +557,7 @@ module API
|
|||
expose :default_project_visibility
|
||||
expose :default_snippet_visibility
|
||||
expose :default_group_visibility
|
||||
expose :default_artifacts_expire_in
|
||||
expose :domain_whitelist
|
||||
expose :domain_blacklist_enabled
|
||||
expose :domain_blacklist
|
||||
|
|
|
@ -56,7 +56,8 @@ module API
|
|||
given shared_runners_enabled: ->(val) { val } do
|
||||
requires :shared_runners_text, type: String, desc: 'Shared runners text '
|
||||
end
|
||||
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size each build's artifacts can have"
|
||||
optional :max_artifacts_size, type: Integer, desc: "Set the maximum file size for each job's artifacts"
|
||||
optional :default_artifacts_expire_in, type: String, desc: "Set the default expiration time for each job's artifacts"
|
||||
optional :max_pages_size, type: Integer, desc: 'Maximum size of pages in MB'
|
||||
optional :container_registry_token_expire_delay, type: Integer, desc: 'Authorization token duration (minutes)'
|
||||
optional :metrics_enabled, type: Boolean, desc: 'Enable the InfluxDB metrics'
|
||||
|
@ -117,7 +118,9 @@ module API
|
|||
:send_user_confirmation_email, :domain_whitelist, :domain_blacklist_enabled,
|
||||
:after_sign_up_text, :signin_enabled, :require_two_factor_authentication,
|
||||
:home_page_url, :after_sign_out_path, :sign_in_text, :help_page_text,
|
||||
:shared_runners_enabled, :max_artifacts_size, :max_pages_size, :container_registry_token_expire_delay,
|
||||
:shared_runners_enabled, :max_artifacts_size,
|
||||
:default_artifacts_expire_in, :max_pages_size,
|
||||
:container_registry_token_expire_delay,
|
||||
:metrics_enabled, :sidekiq_throttling_enabled, :recaptcha_enabled,
|
||||
:akismet_enabled, :admin_notification_email, :sentry_enabled,
|
||||
:repository_storage, :repository_checks_enabled, :koding_enabled, :plantuml_enabled,
|
||||
|
|
|
@ -167,7 +167,10 @@ module Ci
|
|||
|
||||
build.artifacts_file = artifacts
|
||||
build.artifacts_metadata = metadata
|
||||
build.artifacts_expire_in = params['expire_in']
|
||||
build.artifacts_expire_in =
|
||||
params['expire_in'] ||
|
||||
Gitlab::CurrentSettings.current_application_settings
|
||||
.default_artifacts_expire_in
|
||||
|
||||
if build.save
|
||||
present(build, with: Entities::BuildDetails)
|
||||
|
|
|
@ -29,6 +29,40 @@ describe ApplicationSetting, models: true do
|
|||
it { is_expected.not_to allow_value(['test']).for(:disabled_oauth_sign_in_sources) }
|
||||
end
|
||||
|
||||
describe 'default_artifacts_expire_in' do
|
||||
it 'sets an error if it cannot parse' do
|
||||
setting.update(default_artifacts_expire_in: 'a')
|
||||
|
||||
expect_invalid
|
||||
end
|
||||
|
||||
it 'sets an error if it is blank' do
|
||||
setting.update(default_artifacts_expire_in: ' ')
|
||||
|
||||
expect_invalid
|
||||
end
|
||||
|
||||
it 'sets the value if it is valid' do
|
||||
setting.update(default_artifacts_expire_in: '30 days')
|
||||
|
||||
expect(setting).to be_valid
|
||||
expect(setting.default_artifacts_expire_in).to eq('30 days')
|
||||
end
|
||||
|
||||
it 'sets the value if it is 0' do
|
||||
setting.update(default_artifacts_expire_in: '0')
|
||||
|
||||
expect(setting).to be_valid
|
||||
expect(setting.default_artifacts_expire_in).to eq('0')
|
||||
end
|
||||
|
||||
def expect_invalid
|
||||
expect(setting).to be_invalid
|
||||
expect(setting.errors.messages)
|
||||
.to have_key(:default_artifacts_expire_in)
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to validate_presence_of(:max_attachment_size) }
|
||||
|
||||
it do
|
||||
|
|
|
@ -162,11 +162,17 @@ describe Ci::Build, :models do
|
|||
is_expected.to be_nil
|
||||
end
|
||||
|
||||
it 'when resseting value' do
|
||||
it 'when resetting value' do
|
||||
build.artifacts_expire_in = nil
|
||||
|
||||
is_expected.to be_nil
|
||||
end
|
||||
|
||||
it 'when setting to 0' do
|
||||
build.artifacts_expire_in = '0'
|
||||
|
||||
is_expected.to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe '#commit' do
|
||||
|
|
|
@ -30,8 +30,14 @@ describe API::Settings, 'Settings', api: true do
|
|||
|
||||
it "updates application settings" do
|
||||
put api("/application/settings", admin),
|
||||
default_projects_limit: 3, signin_enabled: false, repository_storage: 'custom', koding_enabled: true, koding_url: 'http://koding.example.com',
|
||||
plantuml_enabled: true, plantuml_url: 'http://plantuml.example.com'
|
||||
default_projects_limit: 3,
|
||||
signin_enabled: false,
|
||||
repository_storage: 'custom',
|
||||
koding_enabled: true,
|
||||
koding_url: 'http://koding.example.com',
|
||||
plantuml_enabled: true,
|
||||
plantuml_url: 'http://plantuml.example.com',
|
||||
default_artifacts_expire_in: '2 days'
|
||||
expect(response).to have_http_status(200)
|
||||
expect(json_response['default_projects_limit']).to eq(3)
|
||||
expect(json_response['signin_enabled']).to be_falsey
|
||||
|
@ -41,6 +47,7 @@ describe API::Settings, 'Settings', api: true do
|
|||
expect(json_response['koding_url']).to eq('http://koding.example.com')
|
||||
expect(json_response['plantuml_enabled']).to be_truthy
|
||||
expect(json_response['plantuml_url']).to eq('http://plantuml.example.com')
|
||||
expect(json_response['default_artifacts_expire_in']).to eq('2 days')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -630,6 +630,7 @@ describe Ci::API::Builds do
|
|||
|
||||
context 'with an expire date' do
|
||||
let!(:artifacts) { file_upload }
|
||||
let(:default_artifacts_expire_in) {}
|
||||
|
||||
let(:post_data) do
|
||||
{ 'file.path' => artifacts.path,
|
||||
|
@ -638,6 +639,9 @@ describe Ci::API::Builds do
|
|||
end
|
||||
|
||||
before do
|
||||
stub_application_setting(
|
||||
default_artifacts_expire_in: default_artifacts_expire_in)
|
||||
|
||||
post(post_url, post_data, headers_with_token)
|
||||
end
|
||||
|
||||
|
@ -648,7 +652,8 @@ describe Ci::API::Builds do
|
|||
build.reload
|
||||
expect(response).to have_http_status(201)
|
||||
expect(json_response['artifacts_expire_at']).not_to be_empty
|
||||
expect(build.artifacts_expire_at).to be_within(5.minutes).of(Time.now + 7.days)
|
||||
expect(build.artifacts_expire_at).
|
||||
to be_within(5.minutes).of(7.days.from_now)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -661,6 +666,32 @@ describe Ci::API::Builds do
|
|||
expect(json_response['artifacts_expire_at']).to be_nil
|
||||
expect(build.artifacts_expire_at).to be_nil
|
||||
end
|
||||
|
||||
context 'with application default' do
|
||||
context 'default to 5 days' do
|
||||
let(:default_artifacts_expire_in) { '5 days' }
|
||||
|
||||
it 'sets to application default' do
|
||||
build.reload
|
||||
expect(response).to have_http_status(201)
|
||||
expect(json_response['artifacts_expire_at'])
|
||||
.not_to be_empty
|
||||
expect(build.artifacts_expire_at)
|
||||
.to be_within(5.minutes).of(5.days.from_now)
|
||||
end
|
||||
end
|
||||
|
||||
context 'default to 0' do
|
||||
let(:default_artifacts_expire_in) { '0' }
|
||||
|
||||
it 'does not set expire_in' do
|
||||
build.reload
|
||||
expect(response).to have_http_status(201)
|
||||
expect(json_response['artifacts_expire_at']).to be_nil
|
||||
expect(build.artifacts_expire_at).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue