Add latest changes from gitlab-org/gitlab@master
|
@ -1 +1 @@
|
||||||
c6ba78e87bed03254417fe4cd52d377d88ac0b60
|
0926b9f8ff2215874eef0e22f750a74da5fe4321
|
||||||
|
|
2
Gemfile
|
@ -372,7 +372,7 @@ group :development, :test do
|
||||||
|
|
||||||
gem 'gitlab-styles', '~> 5.0.0', require: false
|
gem 'gitlab-styles', '~> 5.0.0', require: false
|
||||||
|
|
||||||
gem 'scss_lint', '~> 0.56.0', require: false
|
gem 'scss_lint', '~> 0.59.0', require: false
|
||||||
gem 'haml_lint', '~> 0.36.0', require: false
|
gem 'haml_lint', '~> 0.36.0', require: false
|
||||||
gem 'bundler-audit', '~> 0.6.1', require: false
|
gem 'bundler-audit', '~> 0.6.1', require: false
|
||||||
|
|
||||||
|
|
|
@ -1081,9 +1081,8 @@ GEM
|
||||||
sawyer (0.8.2)
|
sawyer (0.8.2)
|
||||||
addressable (>= 2.3.5)
|
addressable (>= 2.3.5)
|
||||||
faraday (> 0.8, < 2.0)
|
faraday (> 0.8, < 2.0)
|
||||||
scss_lint (0.56.0)
|
scss_lint (0.59.0)
|
||||||
rake (>= 0.9, < 13)
|
sass (~> 3.5, >= 3.5.5)
|
||||||
sass (~> 3.5.3)
|
|
||||||
securecompare (1.0.0)
|
securecompare (1.0.0)
|
||||||
seed-fu (2.3.7)
|
seed-fu (2.3.7)
|
||||||
activerecord (>= 3.1)
|
activerecord (>= 3.1)
|
||||||
|
@ -1484,7 +1483,7 @@ DEPENDENCIES
|
||||||
rugged (~> 0.28)
|
rugged (~> 0.28)
|
||||||
sanitize (~> 5.2.1)
|
sanitize (~> 5.2.1)
|
||||||
sassc-rails (~> 2.1.0)
|
sassc-rails (~> 2.1.0)
|
||||||
scss_lint (~> 0.56.0)
|
scss_lint (~> 0.59.0)
|
||||||
seed-fu (~> 2.3.7)
|
seed-fu (~> 2.3.7)
|
||||||
selenium-webdriver (~> 3.142)
|
selenium-webdriver (~> 3.142)
|
||||||
sentry-raven (~> 3.0)
|
sentry-raven (~> 3.0)
|
||||||
|
|
|
@ -58,7 +58,7 @@ export default {
|
||||||
</gl-link>
|
</gl-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="blob-viewer" data-qa-selector="blob_viewer_content">
|
<div class="blob-viewer" data-qa-selector="blob_viewer_content" itemprop="about">
|
||||||
<gl-loading-icon v-if="loading > 0" size="md" color="dark" class="my-4 mx-auto" />
|
<gl-loading-icon v-if="loading > 0" size="md" color="dark" class="my-4 mx-auto" />
|
||||||
<div v-else-if="readme" ref="readme" v-html="readme.html"></div>
|
<div v-else-if="readme" ref="readme" v-html="readme.html"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { GlButton } from '@gitlab/ui';
|
import { GlButton } from '@gitlab/ui';
|
||||||
|
import { produce } from 'immer';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
import { deprecatedCreateFlash as createFlash } from '~/flash';
|
||||||
import MergeRequest from '~/merge_request';
|
import MergeRequest from '~/merge_request';
|
||||||
|
@ -80,12 +81,18 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = store.readQuery({
|
const sourceData = store.readQuery({
|
||||||
query: getStateQuery,
|
query: getStateQuery,
|
||||||
variables: mergeRequestQueryVariables,
|
variables: mergeRequestQueryVariables,
|
||||||
});
|
});
|
||||||
data.project.mergeRequest.workInProgress = workInProgress;
|
|
||||||
data.project.mergeRequest.title = title;
|
const data = produce(sourceData, draftState => {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
draftState.project.mergeRequest.workInProgress = workInProgress;
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
draftState.project.mergeRequest.title = title;
|
||||||
|
});
|
||||||
|
|
||||||
store.writeQuery({
|
store.writeQuery({
|
||||||
query: getStateQuery,
|
query: getStateQuery,
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -10,7 +10,12 @@ Vue.use(Translate);
|
||||||
Vue.use(VueApollo);
|
Vue.use(VueApollo);
|
||||||
|
|
||||||
const apolloProvider = new VueApollo({
|
const apolloProvider = new VueApollo({
|
||||||
defaultClient: createDefaultClient(),
|
defaultClient: createDefaultClient(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
assumeImmutableResults: true,
|
||||||
|
},
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import * as types from './mutation_types';
|
||||||
|
import { fetchDiffData } from '../../utils';
|
||||||
|
|
||||||
|
export const setDiffEndpoint = ({ commit }, path) => commit(types.SET_DIFF_ENDPOINT, path);
|
||||||
|
|
||||||
|
export const requestDiff = ({ commit }) => commit(types.REQUEST_DIFF);
|
||||||
|
|
||||||
|
export const receiveDiffSuccess = ({ commit }, response) =>
|
||||||
|
commit(types.RECEIVE_DIFF_SUCCESS, response);
|
||||||
|
|
||||||
|
export const receiveDiffError = ({ commit }, response) =>
|
||||||
|
commit(types.RECEIVE_DIFF_ERROR, response);
|
||||||
|
|
||||||
|
export const fetchDiff = ({ state, rootState, dispatch }) => {
|
||||||
|
dispatch('requestDiff');
|
||||||
|
|
||||||
|
return fetchDiffData(rootState, state.paths.diffEndpoint, 'sast')
|
||||||
|
.then(data => {
|
||||||
|
dispatch('receiveDiffSuccess', data);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
dispatch('receiveDiffError');
|
||||||
|
});
|
||||||
|
};
|
|
@ -0,0 +1,10 @@
|
||||||
|
import state from './state';
|
||||||
|
import mutations from './mutations';
|
||||||
|
import * as actions from './actions';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions,
|
||||||
|
};
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const RECEIVE_DIFF_SUCCESS = 'RECEIVE_DIFF_SUCCESS';
|
||||||
|
export const RECEIVE_DIFF_ERROR = 'RECEIVE_DIFF_ERROR';
|
||||||
|
export const REQUEST_DIFF = 'REQUEST_DIFF';
|
||||||
|
export const SET_DIFF_ENDPOINT = 'SET_DIFF_ENDPOINT';
|
|
@ -0,0 +1,31 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
import * as types from './mutation_types';
|
||||||
|
import { parseDiff } from '../../utils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
[types.SET_DIFF_ENDPOINT](state, path) {
|
||||||
|
Vue.set(state.paths, 'diffEndpoint', path);
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.REQUEST_DIFF](state) {
|
||||||
|
state.isLoading = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.RECEIVE_DIFF_SUCCESS](state, { diff, enrichData }) {
|
||||||
|
const { added, fixed, existing } = parseDiff(diff, enrichData);
|
||||||
|
const baseReportOutofDate = diff.base_report_out_of_date || false;
|
||||||
|
const hasBaseReport = Boolean(diff.base_report_created_at);
|
||||||
|
|
||||||
|
state.isLoading = false;
|
||||||
|
state.newIssues = added;
|
||||||
|
state.resolvedIssues = fixed;
|
||||||
|
state.allIssues = existing;
|
||||||
|
state.baseReportOutofDate = baseReportOutofDate;
|
||||||
|
state.hasBaseReport = hasBaseReport;
|
||||||
|
},
|
||||||
|
|
||||||
|
[types.RECEIVE_DIFF_ERROR](state) {
|
||||||
|
state.isLoading = false;
|
||||||
|
state.hasError = true;
|
||||||
|
},
|
||||||
|
};
|
|
@ -0,0 +1,16 @@
|
||||||
|
export default () => ({
|
||||||
|
paths: {
|
||||||
|
head: null,
|
||||||
|
base: null,
|
||||||
|
diffEndpoint: null,
|
||||||
|
},
|
||||||
|
|
||||||
|
isLoading: false,
|
||||||
|
hasError: false,
|
||||||
|
|
||||||
|
newIssues: [],
|
||||||
|
resolvedIssues: [],
|
||||||
|
allIssues: [],
|
||||||
|
baseReportOutofDate: false,
|
||||||
|
hasBaseReport: false,
|
||||||
|
});
|
|
@ -0,0 +1,70 @@
|
||||||
|
import pollUntilComplete from '~/lib/utils/poll_until_complete';
|
||||||
|
import axios from '~/lib/utils/axios_utils';
|
||||||
|
|
||||||
|
export const fetchDiffData = (state, endpoint, category) => {
|
||||||
|
const requests = [pollUntilComplete(endpoint)];
|
||||||
|
|
||||||
|
if (state.canReadVulnerabilityFeedback) {
|
||||||
|
requests.push(axios.get(state.vulnerabilityFeedbackPath, { params: { category } }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(requests).then(([diffResponse, enrichResponse]) => ({
|
||||||
|
diff: diffResponse.data,
|
||||||
|
enrichData: enrichResponse?.data ?? [],
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns given vulnerability enriched with the corresponding
|
||||||
|
* feedback (`dismissal` or `issue` type)
|
||||||
|
* @param {Object} vulnerability
|
||||||
|
* @param {Array} feedback
|
||||||
|
*/
|
||||||
|
export const enrichVulnerabilityWithFeedback = (vulnerability, feedback = []) =>
|
||||||
|
feedback
|
||||||
|
.filter(fb => fb.project_fingerprint === vulnerability.project_fingerprint)
|
||||||
|
.reduce((vuln, fb) => {
|
||||||
|
if (fb.feedback_type === 'dismissal') {
|
||||||
|
return {
|
||||||
|
...vuln,
|
||||||
|
isDismissed: true,
|
||||||
|
dismissalFeedback: fb,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (fb.feedback_type === 'issue' && fb.issue_iid) {
|
||||||
|
return {
|
||||||
|
...vuln,
|
||||||
|
hasIssue: true,
|
||||||
|
issue_feedback: fb,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (fb.feedback_type === 'merge_request' && fb.merge_request_iid) {
|
||||||
|
return {
|
||||||
|
...vuln,
|
||||||
|
hasMergeRequest: true,
|
||||||
|
merge_request_feedback: fb,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return vuln;
|
||||||
|
}, vulnerability);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the added, fixed, and existing vulnerabilities from the API report.
|
||||||
|
*
|
||||||
|
* @param {Object} diff The original reports.
|
||||||
|
* @param {Object} enrichData Feedback data to add to the reports.
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
export const parseDiff = (diff, enrichData) => {
|
||||||
|
const enrichVulnerability = vulnerability => ({
|
||||||
|
...enrichVulnerabilityWithFeedback(vulnerability, enrichData),
|
||||||
|
category: vulnerability.report_type,
|
||||||
|
title: vulnerability.message || vulnerability.name,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
added: diff.added ? diff.added.map(enrichVulnerability) : [],
|
||||||
|
fixed: diff.fixed ? diff.fixed.map(enrichVulnerability) : [],
|
||||||
|
existing: diff.existing ? diff.existing.map(enrichVulnerability) : [],
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module StatAnchorsHelper
|
||||||
|
def stat_anchor_attrs(anchor)
|
||||||
|
{}.tap do |attrs|
|
||||||
|
attrs[:class] = %w(nav-link gl-display-flex gl-align-items-center) << extra_classes(anchor)
|
||||||
|
attrs[:itemprop] = anchor.itemprop if anchor.itemprop
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def button_attribute(anchor)
|
||||||
|
"btn-#{anchor.class_modifier || 'missing'}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def extra_classes(anchor)
|
||||||
|
if anchor.is_link
|
||||||
|
'stat-link'
|
||||||
|
else
|
||||||
|
"btn #{button_attribute(anchor)}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -7,6 +7,7 @@ module Ci
|
||||||
include Importable
|
include Importable
|
||||||
include AfterCommitQueue
|
include AfterCommitQueue
|
||||||
include Ci::HasRef
|
include Ci::HasRef
|
||||||
|
extend ::Gitlab::Utils::Override
|
||||||
|
|
||||||
InvalidBridgeTypeError = Class.new(StandardError)
|
InvalidBridgeTypeError = Class.new(StandardError)
|
||||||
InvalidTransitionError = Class.new(StandardError)
|
InvalidTransitionError = Class.new(StandardError)
|
||||||
|
@ -203,8 +204,11 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
override :dependency_variables
|
||||||
def dependency_variables
|
def dependency_variables
|
||||||
[]
|
return [] unless ::Feature.enabled?(:ci_bridge_dependency_variables, project)
|
||||||
|
|
||||||
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
def target_revision_ref
|
def target_revision_ref
|
||||||
|
|
|
@ -571,14 +571,6 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependency_variables
|
|
||||||
return [] if all_dependencies.empty?
|
|
||||||
|
|
||||||
Gitlab::Ci::Variables::Collection.new.concat(
|
|
||||||
Ci::JobVariable.where(job: all_dependencies).dotenv_source
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def features
|
def features
|
||||||
{ trace_sections: true }
|
{ trace_sections: true }
|
||||||
end
|
end
|
||||||
|
@ -828,10 +820,6 @@ module Ci
|
||||||
Gitlab::Ci::Build::Credentials::Factory.new(self).create!
|
Gitlab::Ci::Build::Credentials::Factory.new(self).create!
|
||||||
end
|
end
|
||||||
|
|
||||||
def all_dependencies
|
|
||||||
dependencies.all
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_valid_build_dependencies?
|
def has_valid_build_dependencies?
|
||||||
dependencies.valid?
|
dependencies.valid?
|
||||||
end
|
end
|
||||||
|
@ -994,12 +982,6 @@ module Ci
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def dependencies
|
|
||||||
strong_memoize(:dependencies) do
|
|
||||||
Ci::BuildDependencies.new(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_data
|
def build_data
|
||||||
@build_data ||= Gitlab::DataBuilder::Build.build(self)
|
@build_data ||= Gitlab::DataBuilder::Build.build(self)
|
||||||
end
|
end
|
||||||
|
|
|
@ -103,5 +103,25 @@ module Ci
|
||||||
pipeline.ensure_scheduling_type!
|
pipeline.ensure_scheduling_type!
|
||||||
reset
|
reset
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def dependency_variables
|
||||||
|
return [] if all_dependencies.empty?
|
||||||
|
|
||||||
|
Gitlab::Ci::Variables::Collection.new.concat(
|
||||||
|
Ci::JobVariable.where(job: all_dependencies).dotenv_source
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def all_dependencies
|
||||||
|
dependencies.all
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def dependencies
|
||||||
|
strong_memoize(:dependencies) do
|
||||||
|
Ci::BuildDependencies.new(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,7 +13,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
|
||||||
|
|
||||||
presents :project
|
presents :project
|
||||||
|
|
||||||
AnchorData = Struct.new(:is_link, :label, :link, :class_modifier, :icon)
|
AnchorData = Struct.new(:is_link, :label, :link, :class_modifier, :icon, :itemprop)
|
||||||
MAX_TOPICS_TO_SHOW = 3
|
MAX_TOPICS_TO_SHOW = 3
|
||||||
|
|
||||||
def statistic_icon(icon_name = 'plus-square-o')
|
def statistic_icon(icon_name = 'plus-square-o')
|
||||||
|
@ -277,7 +277,9 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
|
||||||
AnchorData.new(false,
|
AnchorData.new(false,
|
||||||
icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
|
icon + content_tag(:span, license_short_name, class: 'project-stat-value'),
|
||||||
license_path,
|
license_path,
|
||||||
'default')
|
'default',
|
||||||
|
nil,
|
||||||
|
'license')
|
||||||
else
|
else
|
||||||
if current_user && can_current_user_push_to_default_branch?
|
if current_user && can_current_user_push_to_default_branch?
|
||||||
AnchorData.new(false,
|
AnchorData.new(false,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
- page_description @project.description_html unless page_description
|
- page_description @project.description_html unless page_description
|
||||||
- header_title project_title(@project) unless header_title
|
- header_title project_title(@project) unless header_title
|
||||||
- nav "project"
|
- nav "project"
|
||||||
|
- page_itemtype 'http://schema.org/SoftwareSourceCode'
|
||||||
- display_subscription_banner!
|
- display_subscription_banner!
|
||||||
- display_namespace_storage_limit_alert!
|
- display_namespace_storage_limit_alert!
|
||||||
- @left_sidebar = true
|
- @left_sidebar = true
|
||||||
|
|
|
@ -7,17 +7,17 @@
|
||||||
.row.gl-mb-3
|
.row.gl-mb-3
|
||||||
.home-panel-title-row.col-md-12.col-lg-6.d-flex
|
.home-panel-title-row.col-md-12.col-lg-6.d-flex
|
||||||
.avatar-container.rect-avatar.s64.home-panel-avatar.gl-flex-shrink-0.gl-w-11.gl-h-11.gl-mr-3.float-none
|
.avatar-container.rect-avatar.s64.home-panel-avatar.gl-flex-shrink-0.gl-w-11.gl-h-11.gl-mr-3.float-none
|
||||||
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64)
|
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s64', width: 64, height: 64, itemprop: 'image')
|
||||||
.d-flex.flex-column.flex-wrap.align-items-baseline
|
.d-flex.flex-column.flex-wrap.align-items-baseline
|
||||||
.d-inline-flex.align-items-baseline
|
.d-inline-flex.align-items-baseline
|
||||||
%h1.home-panel-title.gl-mt-3.gl-mb-2.gl-font-size-h1.gl-line-height-24.gl-font-weight-bold{ data: { qa_selector: 'project_name_content' } }
|
%h1.home-panel-title.gl-mt-3.gl-mb-2.gl-font-size-h1.gl-line-height-24.gl-font-weight-bold{ data: { qa_selector: 'project_name_content' }, itemprop: 'name' }
|
||||||
= @project.name
|
= @project.name
|
||||||
%span.visibility-icon.text-secondary.gl-ml-2.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
|
%span.visibility-icon.text-secondary.gl-ml-2.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@project) }
|
||||||
= visibility_level_icon(@project.visibility_level, options: { class: 'icon' })
|
= visibility_level_icon(@project.visibility_level, options: { class: 'icon' })
|
||||||
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: @project
|
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: @project
|
||||||
.home-panel-metadata.d-flex.flex-wrap.text-secondary.gl-font-base.gl-font-weight-normal.gl-line-height-normal
|
.home-panel-metadata.d-flex.flex-wrap.text-secondary.gl-font-base.gl-font-weight-normal.gl-line-height-normal
|
||||||
- if can?(current_user, :read_project, @project)
|
- if can?(current_user, :read_project, @project)
|
||||||
%span.text-secondary
|
%span.text-secondary{ itemprop: 'identifier' }
|
||||||
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
|
= s_('ProjectPage|Project ID: %{project_id}') % { project_id: @project.id }
|
||||||
- if current_user
|
- if current_user
|
||||||
%span.access-request-links.gl-ml-3
|
%span.access-request-links.gl-ml-3
|
||||||
|
@ -30,10 +30,10 @@
|
||||||
- project_topics_classes = "badge badge-pill badge-secondary gl-mr-2"
|
- project_topics_classes = "badge badge-pill badge-secondary gl-mr-2"
|
||||||
- explore_project_topic_path = explore_projects_path(tag: topic)
|
- explore_project_topic_path = explore_projects_path(tag: topic)
|
||||||
- if topic.length > max_project_topic_length
|
- if topic.length > max_project_topic_length
|
||||||
%a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path }
|
%a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
|
||||||
= topic.titleize
|
= topic.titleize
|
||||||
- else
|
- else
|
||||||
%a{ class: project_topics_classes, href: explore_project_topic_path }
|
%a{ class: project_topics_classes, href: explore_project_topic_path, itemprop: 'keywords' }
|
||||||
= topic.titleize
|
= topic.titleize
|
||||||
|
|
||||||
- if @project.has_extra_topics?
|
- if @project.has_extra_topics?
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
.home-panel-home-desc.mt-1
|
.home-panel-home-desc.mt-1
|
||||||
- if @project.description.present?
|
- if @project.description.present?
|
||||||
.home-panel-description.text-break
|
.home-panel-description.text-break
|
||||||
.home-panel-description-markdown.read-more-container
|
.home-panel-description-markdown.read-more-container{ itemprop: 'abstract' }
|
||||||
= markdown_field(@project, :description)
|
= markdown_field(@project, :description)
|
||||||
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
|
%button.btn.btn-blank.btn-link.js-read-more-trigger.d-lg-none{ type: "button" }
|
||||||
= _("Read more")
|
= _("Read more")
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
%ul.nav
|
%ul.nav
|
||||||
- anchors.each do |anchor|
|
- anchors.each do |anchor|
|
||||||
%li.nav-item
|
%li.nav-item
|
||||||
= link_to_if anchor.link, anchor.label, anchor.link, class: anchor.is_link ? 'nav-link stat-link d-flex align-items-center' : "nav-link btn btn-#{anchor.class_modifier || 'missing'} d-flex align-items-center" do
|
= link_to_if(anchor.link, anchor.label, anchor.link, stat_anchor_attrs(anchor)) do
|
||||||
.stat-text.d-flex.align-items-center{ class: ('btn btn-default disabled' if project_buttons) }= anchor.label
|
.stat-text.d-flex.align-items-center{ class: ('btn btn-default disabled' if project_buttons) }= anchor.label
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add structured data for projects
|
||||||
|
merge_request: 46858
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: approval_suggestions
|
name: approval_suggestions
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38992
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.3'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::composition analysis
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: async_commit_diff_files
|
name: async_commit_diff_files
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38450
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.3'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: auto_devops_banner_disabled
|
name: auto_devops_banner_disabled
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14218
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '10.0'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group:
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: branch_list_keyset_pagination
|
name: branch_list_keyset_pagination
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35819
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.2'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: bulk_update_health_status
|
name: bulk_update_health_status
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33065
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.2'
|
||||||
type: development
|
type: development
|
||||||
group: group::portfolio management
|
group: group::portfolio management
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
name: ci_bridge_dependency_variables
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46530
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273734
|
||||||
|
type: development
|
||||||
|
group: group::pipeline authoring
|
||||||
|
default_enabled: false
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
name: ci_jwt_signing_key
|
name: ci_jwt_signing_key
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34249
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258546
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/258546
|
||||||
milestone: '13.6'
|
milestone: '13.6'
|
||||||
type: development
|
type: development
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: ci_store_pipeline_messages
|
name: ci_store_pipeline_messages
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33762
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.2'
|
||||||
type: development
|
type: development
|
||||||
group: group::continuous integration
|
group: group::continuous integration
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
name: default_merge_ref_for_diffs
|
name: default_merge_ref_for_diffs
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34472
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34472
|
||||||
rollout_issue_url:
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/276917
|
||||||
milestone: '13.4'
|
milestone: '13.4'
|
||||||
type: development
|
type: development
|
||||||
group: group::source code
|
group: group::source code
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: feature_flags_legacy_read_only
|
name: feature_flags_legacy_read_only
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38353
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240985
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/240985
|
||||||
milestone: '13.7'
|
milestone: '13.3'
|
||||||
type: development
|
type: development
|
||||||
group: group::progressive delivery
|
group: group::progressive delivery
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: force_autodevops_on_by_default
|
name: force_autodevops_on_by_default
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/21136
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '11.3'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::configure
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: grape_gitlab_json
|
name: grape_gitlab_json
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36472
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.2'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: graphql_logging
|
name: graphql_logging
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27885
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '12.0'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group:
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: hide_jump_to_next_unresolved_in_threads
|
name: hide_jump_to_next_unresolved_in_threads
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37873
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.3'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: lfs_check
|
name: lfs_check
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27451
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '11.11'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group:
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: merge_red_head_comments_position_on_demand
|
name: merge_red_head_comments_position_on_demand
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34148
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.1'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: merge_ref_auto_sync
|
name: merge_ref_auto_sync
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/29569
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '12.1'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: merge_ref_auto_sync_lock
|
name: merge_ref_auto_sync_lock
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31082
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '12.2'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: remove_legacy_github_client
|
name: remove_legacy_github_client
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37555
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.3'
|
||||||
type: development
|
type: development
|
||||||
group: group::import
|
group: group::import
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: remove_resolve_note
|
name: remove_resolve_note
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45549
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.6'
|
||||||
type: development
|
type: development
|
||||||
group: group::source code
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: rugged_commit_tree_entry
|
name: rugged_commit_tree_entry
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/25896
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '11.9'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::gitaly
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: rugged_list_commits_by_oid
|
name: rugged_list_commits_by_oid
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/27441
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '11.10'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::gitaly
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: snippets_binary_blob
|
name: snippets_binary_blob
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37419
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.3'
|
||||||
type: development
|
type: development
|
||||||
group: group::editor
|
group: group::editor
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: squash_options
|
name: squash_options
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33930
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.2'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::source code
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: sse_image_uploads
|
name: sse_image_uploads
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35126
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.2'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::static site editor
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: webauthn
|
name: webauthn
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26692
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '13.4'
|
||||||
type: development
|
type: development
|
||||||
group:
|
group: group::access
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: gitlab_sidekiq_enable_semi_reliable_fetcher
|
name: gitlab_sidekiq_enable_semi_reliable_fetcher
|
||||||
introduced_by_url:
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23854
|
||||||
rollout_issue_url:
|
rollout_issue_url:
|
||||||
milestone:
|
milestone: '11.6'
|
||||||
type: ops
|
type: ops
|
||||||
group:
|
group: group::geo
|
||||||
default_enabled: true
|
default_enabled: true
|
||||||
|
|
|
@ -11,6 +11,8 @@ GitLab offers a way to view the changes made within the GitLab server for owners
|
||||||
GitLab system administrators can also take advantage of the logs located on the
|
GitLab system administrators can also take advantage of the logs located on the
|
||||||
file system. See [the logs system documentation](logs.md) for more details.
|
file system. See [the logs system documentation](logs.md) for more details.
|
||||||
|
|
||||||
|
You can generate an [Audit report](audit_reports.md) of audit events.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
**Audit Events** is a tool for GitLab owners and administrators
|
**Audit Events** is a tool for GitLab owners and administrators
|
||||||
|
|
Before Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 8.6 KiB |
|
@ -4,17 +4,12 @@ group: Geo
|
||||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
|
||||||
---
|
---
|
||||||
|
|
||||||
# Geo self-service framework (alpha)
|
# Geo self-service framework
|
||||||
|
|
||||||
NOTE: **Note:**
|
NOTE: **Note:**
|
||||||
This document might be subjected to change. It's a
|
This document is subject to change as we continue to implement and iterate on the framework.
|
||||||
proposal we're working on and once the implementation is complete this
|
Follow the progress in the [epic](https://gitlab.com/groups/gitlab-org/-/epics/2161).
|
||||||
documentation will be updated. Follow progress in the
|
If you need to replicate a new data type, reach out to the Geo
|
||||||
[epic](https://gitlab.com/groups/gitlab-org/-/epics/2161).
|
|
||||||
|
|
||||||
NOTE: **Note:**
|
|
||||||
The Geo self-service framework is currently in
|
|
||||||
alpha. If you need to replicate a new data type, reach out to the Geo
|
|
||||||
team to discuss the options. You can contact them in `#g_geo` on Slack
|
team to discuss the options. You can contact them in `#g_geo` on Slack
|
||||||
or mention `@geo-team` in the issue or merge request.
|
or mention `@geo-team` in the issue or merge request.
|
||||||
|
|
||||||
|
@ -26,38 +21,40 @@ minimal effort of the engineer who created a data type.
|
||||||
## Nomenclature
|
## Nomenclature
|
||||||
|
|
||||||
Before digging into the API, developers need to know some Geo-specific
|
Before digging into the API, developers need to know some Geo-specific
|
||||||
naming conventions.
|
naming conventions:
|
||||||
|
|
||||||
Model
|
- **Model**:
|
||||||
: A model is an Active Model, which is how it is known in the entire
|
A model is an Active Model, which is how it is known in the entire
|
||||||
Rails codebase. It usually is tied to a database table. From Geo
|
Rails codebase. It usually is tied to a database table. From Geo
|
||||||
perspective, a model can have one or more resources.
|
perspective, a model can have one or more resources.
|
||||||
|
|
||||||
Resource
|
- **Resource**:
|
||||||
: A resource is a piece of data that belongs to a model and is
|
A resource is a piece of data that belongs to a model and is
|
||||||
produced by a GitLab feature. It is persisted using a storage
|
produced by a GitLab feature. It is persisted using a storage
|
||||||
mechanism. By default, a resource is not a replicable.
|
mechanism. By default, a resource is not a Geo replicable.
|
||||||
|
|
||||||
Data type
|
- **Data type**:
|
||||||
: Data type is how a resource is stored. Each resource should
|
Data type is how a resource is stored. Each resource should
|
||||||
fit in one of the data types Geo supports:
|
fit in one of the data types Geo supports:
|
||||||
:- Git repository
|
- Git repository
|
||||||
:- Blob
|
- Blob
|
||||||
:- Database
|
- Database
|
||||||
: For more detail, see [Data types](../../administration/geo/replication/datatypes.md).
|
|
||||||
|
|
||||||
Geo Replicable
|
For more detail, see [Data types](../../administration/geo/replication/datatypes.md).
|
||||||
: A Replicable is a resource Geo wants to sync across Geo nodes. There
|
|
||||||
|
- **Geo Replicable**:
|
||||||
|
A Replicable is a resource Geo wants to sync across Geo nodes. There
|
||||||
is a limited set of supported data types of replicables. The effort
|
is a limited set of supported data types of replicables. The effort
|
||||||
required to implement replication of a resource that belongs to one
|
required to implement replication of a resource that belongs to one
|
||||||
of the known data types is minimal.
|
of the known data types is minimal.
|
||||||
|
|
||||||
Geo Replicator
|
- **Geo Replicator**:
|
||||||
: A Geo Replicator is the object that knows how to replicate a
|
A Geo Replicator is the object that knows how to replicate a
|
||||||
replicable. It's responsible for:
|
replicable. It's responsible for:
|
||||||
:- Firing events (producer)
|
- Firing events (producer)
|
||||||
:- Consuming events (consumer)
|
- Consuming events (consumer)
|
||||||
: It's tied to the Geo Replicable data type. All replicators have a
|
|
||||||
|
It's tied to the Geo Replicable data type. All replicators have a
|
||||||
common interface that can be used to process (that is, produce and
|
common interface that can be used to process (that is, produce and
|
||||||
consume) events. It takes care of the communication between the
|
consume) events. It takes care of the communication between the
|
||||||
primary node (where events are produced) and the secondary node
|
primary node (where events are produced) and the secondary node
|
||||||
|
@ -65,8 +62,8 @@ Geo Replicator
|
||||||
Geo in their feature will use the API of replicators to make this
|
Geo in their feature will use the API of replicators to make this
|
||||||
happen.
|
happen.
|
||||||
|
|
||||||
Geo Domain-Specific Language
|
- **Geo Domain-Specific Language**:
|
||||||
: The syntactic sugar that allows engineers to easily specify which
|
The syntactic sugar that allows engineers to easily specify which
|
||||||
resources should be replicated and how.
|
resources should be replicated and how.
|
||||||
|
|
||||||
## Geo Domain-Specific Language
|
## Geo Domain-Specific Language
|
||||||
|
@ -144,7 +141,7 @@ replicator.model_record
|
||||||
```
|
```
|
||||||
|
|
||||||
The replicator can be used to generate events, for example in
|
The replicator can be used to generate events, for example in
|
||||||
ActiveRecord hooks:
|
`ActiveRecord` hooks:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
after_create_commit -> { replicator.publish_created_event }
|
after_create_commit -> { replicator.publish_created_event }
|
||||||
|
@ -207,14 +204,12 @@ For example, to add support for files referenced by a `Widget` model with a
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: **Note:**
|
|
||||||
|
|
||||||
If there is a common constraint for records to be available for replication,
|
If there is a common constraint for records to be available for replication,
|
||||||
make sure to also overwrite the `available_replicables` scope.
|
make sure to also overwrite the `available_replicables` scope.
|
||||||
|
|
||||||
1. Create `ee/app/replicators/geo/widget_replicator.rb`. Implement the
|
1. Create `ee/app/replicators/geo/widget_replicator.rb`. Implement the
|
||||||
`#carrierwave_uploader` method which should return a `CarrierWave::Uploader`.
|
`#carrierwave_uploader` method which should return a `CarrierWave::Uploader`,
|
||||||
And implement the class method `.model` to return the `Widget` class.
|
and implement the class method `.model` to return the `Widget` class:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
@ -241,7 +236,7 @@ For example, to add support for files referenced by a `Widget` model with a
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Add this replicator class to the method `replicator_classes` in
|
1. Add this replicator class to the method `replicator_classes` in
|
||||||
`ee/lib/gitlab/geo.rb`:
|
`ee/lib/gitlab/geo.rb`:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
REPLICATOR_CLASSES = [
|
REPLICATOR_CLASSES = [
|
||||||
|
@ -252,8 +247,8 @@ For example, to add support for files referenced by a `Widget` model with a
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
|
1. Create `ee/spec/replicators/geo/widget_replicator_spec.rb` and perform
|
||||||
the setup necessary to define the `model_record` variable for the shared
|
the necessary setup to define the `model_record` variable for the shared
|
||||||
examples.
|
examples:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
@ -324,9 +319,7 @@ For example, to add support for files referenced by a `Widget` model with a
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
|
1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
|
||||||
|
|
||||||
1. Add `widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
|
1. Add `widget_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`.
|
||||||
|
|
||||||
1. Create `ee/spec/factories/geo/widget_registry.rb`:
|
1. Create `ee/spec/factories/geo/widget_registry.rb`:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
@ -380,17 +373,17 @@ For example, to add support for files referenced by a `Widget` model with a
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
Widgets should now be replicated by Geo!
|
Widgets should now be replicated by Geo.
|
||||||
|
|
||||||
#### Verification
|
#### Verification
|
||||||
|
|
||||||
There are two ways to add verification related fields so that the Geo primary
|
There are two ways to add verification related fields so that the Geo primary
|
||||||
can track verification state:
|
can track verification state.
|
||||||
|
|
||||||
##### Option 1: Add verification state fields to the existing `widgets` table itself
|
##### Option 1: Add verification state fields to the existing `widgets` table itself
|
||||||
|
|
||||||
1. Add a migration to add columns ordered according to [our guidelines](../ordering_table_columns.md)
|
1. Add a migration to add columns ordered according to [our guidelines](../ordering_table_columns.md)
|
||||||
for verification state to the widgets table:
|
for verification state to the widgets table:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
@ -467,7 +460,7 @@ for verification state to the widgets table:
|
||||||
|
|
||||||
1. Create a `widget_states` table and add a partial index on `verification_failure` and
|
1. Create a `widget_states` table and add a partial index on `verification_failure` and
|
||||||
`verification_checksum` to ensure re-verification can be performed efficiently. Order
|
`verification_checksum` to ensure re-verification can be performed efficiently. Order
|
||||||
the columns according to [our guidelines](../ordering_table_columns.md):
|
the columns according to [the guidelines](../ordering_table_columns.md):
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
@ -525,12 +518,12 @@ for verification state to the widgets table:
|
||||||
To do: Add verification on secondaries. This should be done as part of
|
To do: Add verification on secondaries. This should be done as part of
|
||||||
[Geo: Self Service Framework - First Implementation for Package File verification](https://gitlab.com/groups/gitlab-org/-/epics/1817)
|
[Geo: Self Service Framework - First Implementation for Package File verification](https://gitlab.com/groups/gitlab-org/-/epics/1817)
|
||||||
|
|
||||||
Widgets should now be verified by Geo!
|
Widgets should now be verified by Geo.
|
||||||
|
|
||||||
#### Metrics
|
#### Metrics
|
||||||
|
|
||||||
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
|
Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
|
||||||
`GeoNodeStatus` for display in the UI, and sent to Prometheus.
|
`GeoNodeStatus` for display in the UI, and sent to Prometheus:
|
||||||
|
|
||||||
1. Add fields `widgets_count`, `widgets_checksummed_count`,
|
1. Add fields `widgets_count`, `widgets_checksummed_count`,
|
||||||
`widgets_checksum_failed_count`, `widgets_synced_count`,
|
`widgets_checksum_failed_count`, `widgets_synced_count`,
|
||||||
|
@ -570,7 +563,7 @@ Metrics are gathered by `Geo::MetricsUpdateWorker`, persisted in
|
||||||
attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
|
attribute. Check out `spec/factories/merge_request_diffs.rb` for an example.
|
||||||
|
|
||||||
Widget replication and verification metrics should now be available in the API,
|
Widget replication and verification metrics should now be available in the API,
|
||||||
the Admin Area UI, and Prometheus!
|
the Admin Area UI, and Prometheus.
|
||||||
|
|
||||||
#### GraphQL API
|
#### GraphQL API
|
||||||
|
|
||||||
|
@ -587,7 +580,6 @@ the Admin Area UI, and Prometheus!
|
||||||
|
|
||||||
1. Add the new `widget_registries` field name to the `expected_fields` array in
|
1. Add the new `widget_registries` field name to the `expected_fields` array in
|
||||||
`ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
|
`ee/spec/graphql/types/geo/geo_node_type_spec.rb`.
|
||||||
|
|
||||||
1. Create `ee/app/graphql/resolvers/geo/widget_registries_resolver.rb`:
|
1. Create `ee/app/graphql/resolvers/geo/widget_registries_resolver.rb`:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
|
@ -696,14 +688,14 @@ the Admin Area UI, and Prometheus!
|
||||||
```
|
```
|
||||||
|
|
||||||
Individual widget synchronization and verification data should now be available
|
Individual widget synchronization and verification data should now be available
|
||||||
via the GraphQL API!
|
via the GraphQL API.
|
||||||
|
|
||||||
1. Take care of replicating "update" events. Geo Framework does not currently support
|
Make sure to replicate the "update" events. Geo Framework does not currently support
|
||||||
replicating "update" events because all entities added to the framework, by this time,
|
replicating "update" events because all entities added to the framework, by this time,
|
||||||
are immutable. If this is the case
|
are immutable. If this is the case
|
||||||
for the entity you're going to add, please follow <https://gitlab.com/gitlab-org/gitlab/-/issues/118743>
|
for the entity you're going to add, follow <https://gitlab.com/gitlab-org/gitlab/-/issues/118743>
|
||||||
and <https://gitlab.com/gitlab-org/gitlab/-/issues/118745> as examples to add the new event type.
|
and <https://gitlab.com/gitlab-org/gitlab/-/issues/118745> as examples to add the new event type.
|
||||||
Please also remove this notice when you've added it.
|
Also, remove this notice when you've added it.
|
||||||
|
|
||||||
#### Admin UI
|
#### Admin UI
|
||||||
|
|
||||||
|
@ -711,7 +703,7 @@ To do: This should be done as part of
|
||||||
[Geo: Implement frontend for Self-Service Framework replicables](https://gitlab.com/groups/gitlab-org/-/epics/2525)
|
[Geo: Implement frontend for Self-Service Framework replicables](https://gitlab.com/groups/gitlab-org/-/epics/2525)
|
||||||
|
|
||||||
Widget sync and verification data (aggregate and individual) should now be
|
Widget sync and verification data (aggregate and individual) should now be
|
||||||
available in the Admin UI!
|
available in the Admin UI.
|
||||||
|
|
||||||
#### Releasing the feature
|
#### Releasing the feature
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB |
|
@ -119,7 +119,7 @@ repository, you can run `git remote -v`.
|
||||||
If there are [merge conflicts](#merge-conflicts), Git will prompt you to fix
|
If there are [merge conflicts](#merge-conflicts), Git will prompt you to fix
|
||||||
them before continuing the rebase.
|
them before continuing the rebase.
|
||||||
|
|
||||||
To learn more, check Git's documentation on [rebasing](ttps://git-scm.com/book/en/v2/Git-Branching-Rebasing)
|
To learn more, check Git's documentation on [rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)
|
||||||
and [rebasing strategies](https://git-scm.com/book/en/v2/Git-Branching-Rebasing).
|
and [rebasing strategies](https://git-scm.com/book/en/v2/Git-Branching-Rebasing).
|
||||||
|
|
||||||
### Interactive rebase
|
### Interactive rebase
|
||||||
|
|
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 152 KiB |
Before Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 4.6 KiB |