Skip to content
Snippets Groups Projects
Commit af89c610 authored by Allison Browne's avatar Allison Browne :speech_balloon:
Browse files

Add setting to turn off keeping latest artifacts

Add a setting to the application settings page to turn
off keeping the lateset artifacts per pipeline. This will
allow users to control storage.
parent bc6e5559
No related branches found
No related tags found
No related merge requests found
Showing
with 187 additions and 27 deletions
query getKeepLatestArtifactApplicationSetting {
ciApplicationSettings {
keepLatestArtifact
}
}
Loading
Loading
@@ -2,12 +2,22 @@
import { GlAlert, GlFormCheckbox, GlLink } from '@gitlab/ui';
import { __ } from '~/locale';
import GetKeepLatestArtifactProjectSetting from './graphql/queries/get_keep_latest_artifact_project_setting.query.graphql';
import GetKeepLatestArtifactApplicationSetting from './graphql/queries/get_keep_latest_artifact_application_setting.query.graphql';
import UpdateKeepLatestArtifactProjectSetting from './graphql/mutations/update_keep_latest_artifact_project_setting.mutation.graphql';
 
const FETCH_ERROR = __('There was a problem fetching the keep latest artifact setting.');
const UPDATE_ERROR = __('There was a problem updating the keep latest artifact setting.');
export default {
errors: {
fetchError: __('There was a problem fetching the keep latest artifacts setting.'),
updateError: __('There was a problem updating the keep latest artifacts setting.'),
},
i18n: {
enabledHelpText: __(
'The latest artifacts created by jobs in the most recent successful pipeline will be stored.',
),
disabledHelpText: __('This feature is disabled at the instance level.'),
helpLinkText: __('More information'),
checkboxText: __('Keep artifacts from most recent successful jobs'),
},
components: {
GlAlert,
GlFormCheckbox,
Loading
Loading
@@ -33,21 +43,33 @@ export default {
return data.project?.ciCdSettings?.keepLatestArtifact;
},
error() {
this.reportError(FETCH_ERROR);
this.reportError(this.$options.errors.fetchError);
},
},
projectSettingDisabled: {
query: GetKeepLatestArtifactApplicationSetting,
update(data) {
return !data.ciApplicationSettings?.keepLatestArtifact;
},
},
},
data() {
return {
keepLatestArtifact: true,
keepLatestArtifact: null,
errorMessage: '',
isAlertDismissed: false,
projectSettingDisabled: true,
};
},
computed: {
shouldShowAlert() {
return this.errorMessage && !this.isAlertDismissed;
},
helpText() {
return this.projectSettingDisabled
? this.$options.i18n.disabledHelpText
: this.$options.i18n.enabledHelpText;
},
},
methods: {
reportError(error) {
Loading
Loading
@@ -65,10 +87,10 @@ export default {
});
 
if (data.ciCdSettingsUpdate.errors.length) {
this.reportError(UPDATE_ERROR);
this.reportError(this.$options.errors.updateError);
}
} catch (error) {
this.reportError(UPDATE_ERROR);
this.reportError(this.$options.errors.updateError);
}
},
},
Loading
Loading
@@ -84,16 +106,13 @@ export default {
@dismiss="isAlertDismissed = true"
>{{ errorMessage }}</gl-alert
>
<gl-form-checkbox v-model="keepLatestArtifact" @change="updateSetting"
><b class="gl-mr-3">{{ __('Keep artifacts from most recent successful jobs') }}</b>
<gl-link :href="helpPagePath">{{ __('More information') }}</gl-link></gl-form-checkbox
>
<p>
{{
__(
'The latest artifacts created by jobs in the most recent successful pipeline will be stored.',
)
}}
</p>
<gl-form-checkbox
v-model="keepLatestArtifact"
:disabled="projectSettingDisabled"
@change="updateSetting"
><strong class="gl-mr-3">{{ $options.i18n.checkboxText }}</strong>
<gl-link :href="helpPagePath">{{ $options.i18n.helpLinkText }}</gl-link>
<template v-if="!$apollo.loading" #help>{{ helpText }}</template>
</gl-form-checkbox>
</div>
</template>
# frozen_string_literal: true
module Types
module Ci
class ApplicationSettingType < BaseObject
graphql_name 'CiApplicationSettings'
authorize :read_application_setting
field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Whether to keep the latest jobs artifacts.'
end
end
end
Loading
Loading
@@ -14,7 +14,8 @@ class CiCdSettingType < BaseObject
description: 'Whether merge trains are enabled.',
method: :merge_trains_enabled?
field :keep_latest_artifact, GraphQL::BOOLEAN_TYPE, null: true,
description: 'Whether to keep the latest builds artifacts.'
description: 'Whether to keep the latest builds artifacts.',
method: :keep_latest_artifacts_available?
field :project, Types::ProjectType, null: true,
description: 'Project the CI/CD settings belong to.'
end
Loading
Loading
Loading
Loading
@@ -87,6 +87,10 @@ class QueryType < ::Types::BaseObject
description: 'Get statistics on the instance.',
resolver: Resolvers::Admin::Analytics::InstanceStatistics::MeasurementsResolver
 
field :ci_application_settings, Types::Ci::ApplicationSettingType,
null: true,
description: 'CI related settings that apply to the entire instance.'
field :runner_platforms, Types::Ci::RunnerPlatformType.connection_type,
null: true, description: 'Supported runner platforms.',
resolver: Resolvers::Ci::RunnerPlatformsResolver
Loading
Loading
@@ -128,6 +132,14 @@ def container_repository(id:)
def current_user
context[:current_user]
end
def ci_application_settings
application_settings
end
def application_settings
Gitlab::CurrentSettings.current_application_settings
end
end
end
 
Loading
Loading
Loading
Loading
@@ -339,7 +339,8 @@ def visible_attributes
:container_registry_delete_tags_service_timeout,
:rate_limiting_response_text,
:container_registry_expiration_policies_worker_capacity,
:container_registry_cleanup_tags_service_max_list_size
:container_registry_cleanup_tags_service_max_list_size,
:keep_latest_artifact
]
end
 
Loading
Loading
Loading
Loading
@@ -525,6 +525,10 @@ def self.create_from_defaults
current_without_cache
end
 
def self.find_or_create_without_cache
current_without_cache || create_from_defaults
end
# Due to the frequency with which settings are accessed, it is
# likely that during a backup restore a running GitLab process
# will insert a new `application_settings` row before the
Loading
Loading
Loading
Loading
@@ -411,7 +411,7 @@ class Project < ApplicationRecord
delegate :dashboard_timezone, to: :metrics_setting, allow_nil: true, prefix: true
delegate :default_git_depth, :default_git_depth=, to: :ci_cd_settings, prefix: :ci
delegate :forward_deployment_enabled, :forward_deployment_enabled=, :forward_deployment_enabled?, to: :ci_cd_settings, prefix: :ci
delegate :keep_latest_artifact, :keep_latest_artifact=, :keep_latest_artifact?, to: :ci_cd_settings, prefix: :ci
delegate :keep_latest_artifact, :keep_latest_artifact=, :keep_latest_artifact?, :keep_latest_artifacts_available?, to: :ci_cd_settings
delegate :restrict_user_defined_variables, :restrict_user_defined_variables=, :restrict_user_defined_variables?,
to: :ci_cd_settings
delegate :actual_limits, :actual_plan_name, to: :namespace, allow_nil: true
Loading
Loading
@@ -837,8 +837,12 @@ def active_webide_pipelines(user:)
webide_pipelines.running_or_pending.for_user(user)
end
 
def latest_pipeline_locked
ci_keep_latest_artifact? ? :artifacts_locked : :unlocked
def default_pipeline_lock
if keep_latest_artifacts_available?
return :artifacts_locked
end
:unlocked
end
 
def autoclose_referenced_issues
Loading
Loading
Loading
Loading
@@ -21,6 +21,11 @@ def forward_deployment_enabled?
super && ::Feature.enabled?(:forward_deployment_enabled, project, default_enabled: true)
end
 
def keep_latest_artifacts_available?
# The project level feature can only be enabled when the feature is enabled instance wide
Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact? && keep_latest_artifact?
end
private
 
def set_default_git_depth
Loading
Loading
# frozen_string_literal: true
class ApplicationSettingPolicy < BasePolicy # rubocop:disable Gitlab/NamespacedClass
rule { admin }.enable :read_application_setting
end
Loading
Loading
@@ -41,6 +41,14 @@
.form-text.text-muted
= html_escape(_("Set the default expiration time for each job's artifacts. 0 for unlimited. The default unit is in seconds, but you can define an alternative. For example: %{code_open}4 mins 2 sec%{code_close}, %{code_open}2h42min%{code_close}.")) % { code_open: '<code>'.html_safe, code_close: '</code>'.html_safe }
= link_to sprite_icon('question-o'), help_page_path('user/admin_area/settings/continuous_integration', anchor: 'default-artifacts-expiration')
.form-group
.form-check
= f.check_box :keep_latest_artifact, class: 'form-check-input'
= f.label :keep_latest_artifact, class: 'form-check-label' do
%strong
= s_('AdminSettings|Keep the latest artifacts for all jobs in the latest successful pipelines')
.form-text.text-muted
= s_('AdminSettings|The latest artifacts for all jobs in the most recent successful pipelines in each project are stored and do not expire.')
.form-group
= f.label :archive_builds_in_human_readable, _('Archive jobs'), class: 'label-bold'
= f.text_field :archive_builds_in_human_readable, class: 'form-control gl-form-input', placeholder: 'never'
Loading
Loading
@@ -51,8 +59,8 @@
= f.check_box :protected_ci_variables, class: 'form-check-input'
= f.label :protected_ci_variables, class: 'form-check-label' do
= s_('AdminSettings|Environment variables are protected by default')
.form-text.text-muted
= s_('AdminSettings|When creating a new environment variable it will be protected by default.')
.form-text.text-muted
= s_('AdminSettings|When creating a new environment variable it will be protected by default.')
.form-group
= f.label :ci_config_path, _('Default CI configuration path'), class: 'label-bold'
= f.text_field :default_ci_config_path, class: 'form-control gl-form-input', placeholder: '.gitlab-ci.yml'
Loading
Loading
---
title: Add keep latest artifact option for instances
merge_request: 50889
author:
type: added
# frozen_string_literal: true
class AddKeepLatestArtifactsToApplicationSettings < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
# This is named keep_latest_artifact for consistency with the project level setting but
# turning it on keeps all (multiple) artifacts on the latest pipeline per ref
add_column :application_settings, :keep_latest_artifact, :boolean, default: true, null: false
end
end
a0561e52982756aded22563e833ab8005b4f45b84c81e872dd8c7188aeb84434
\ No newline at end of file
Loading
Loading
@@ -9412,6 +9412,7 @@ CREATE TABLE application_settings (
enforce_ssh_key_expiration boolean DEFAULT false NOT NULL,
git_two_factor_session_expiry integer DEFAULT 15 NOT NULL,
asset_proxy_allowlist text,
keep_latest_artifact boolean DEFAULT true NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_registry_exp_policies_worker_capacity_positive CHECK ((container_registry_expiration_policies_worker_capacity >= 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),
Loading
Loading
Loading
Loading
@@ -2483,6 +2483,13 @@ type BurnupChartDailyTotals {
scopeWeight: Int!
}
 
type CiApplicationSettings {
"""
Whether to keep the latest jobs artifacts.
"""
keepLatestArtifact: Boolean
}
type CiBuildNeed {
"""
Name of the job we need to complete.
Loading
Loading
@@ -20797,6 +20804,11 @@ type PromoteToEpicPayload {
}
 
type Query {
"""
CI related settings that apply to the entire instance.
"""
ciApplicationSettings: CiApplicationSettings
"""
Get linted and processed contents of a CI config. Should not be requested more than once per request.
"""
Loading
Loading
Loading
Loading
@@ -6546,6 +6546,33 @@
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "CiApplicationSettings",
"description": null,
"fields": [
{
"name": "keepLatestArtifact",
"description": "Whether to keep the latest jobs artifacts.",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "Boolean",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
],
"enumValues": null,
"possibleTypes": null
},
{
"kind": "OBJECT",
"name": "CiBuildNeed",
Loading
Loading
@@ -60509,6 +60536,20 @@
"name": "Query",
"description": null,
"fields": [
{
"name": "ciApplicationSettings",
"description": "CI related settings that apply to the entire instance.",
"args": [
],
"type": {
"kind": "OBJECT",
"name": "CiApplicationSettings",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "ciConfig",
"description": "Get linted and processed contents of a CI config. Should not be requested more than once per request.",
Loading
Loading
@@ -388,6 +388,12 @@ Represents the total number of issues and their weights for a particular day.
| `scopeCount` | Int! | Number of issues as of this day |
| `scopeWeight` | Int! | Total weight of issues as of this day |
 
### CiApplicationSettings
| Field | Type | Description |
| ----- | ---- | ----------- |
| `keepLatestArtifact` | Boolean | Whether to keep the latest jobs artifacts. |
### CiBuildNeed
 
| Field | Type | Description |
Loading
Loading
Loading
Loading
@@ -85,7 +85,8 @@ Example response:
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
"personal_access_token_prefix": "GL-",
"rate_limiting_response_text": null
"rate_limiting_response_text": null,
"keep_latest_artifact": true
}
```
 
Loading
Loading
@@ -179,7 +180,8 @@ Example response:
"wiki_page_max_content_bytes": 52428800,
"require_admin_approval_after_user_signup": false,
"personal_access_token_prefix": "GL-",
"rate_limiting_response_text": null
"rate_limiting_response_text": null,
"keep_latest_artifact": true
}
```
 
Loading
Loading
Loading
Loading
@@ -484,6 +484,9 @@ a project, you can disable this behavior to save space:
1. Navigate to **Settings > CI/CD > Artifacts**.
1. Uncheck **Keep artifacts from most recent successful jobs**.
 
You can disable this behavior for all projects on a self-managed instance in the
[instance's CI/CD settings](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines). **(CORE ONLY)**
When you disable the feature, the latest artifacts do not immediately expire.
A new pipeline must run before the latest artifacts can expire and be deleted.
 
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment